Сообственно, мелочный вопрос. В общем случае, так ли должен выглядеть «идеальный» класс?
class Name
{
public:
// Методы, для работы с классом и его данными.
// Сами данные отсутствуютprotected:
// Методы класса для их внутренего использования.
// Данные также отсутствуютprivate:
// Данные класса, доступ и работа с которыми осуществляеться
// посредством public-методов. Сами методы отсутствуют
};
Мне кажется, что это зависит от задачи. Самое главное, чего нужно придерживаться, что один класс решает или отвечает ровно за одну поставленную перед ним задачу, а информация о том, как он её решает должна быть зарыта внутри класса так глубоко, что бы внешний код смог его сломать;
Хотя с мнением можно аргументировано поспорить
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, MBy, Вы писали:
MBy>Привет!
MBy>Сообственно, мелочный вопрос. В общем случае, так ли должен выглядеть «идеальный» класс?
Слово "идеальный" тут не подходит... Коплиен давно назвал: каноническая форма класса...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Он и в тундре будет выглядеть идеальным
N>Мне кажется, что это зависит от задачи. Самое главное, чего нужно придерживаться, что один класс решает или отвечает ровно за одну поставленную перед ним задачу, а информация о том, как он её решает должна быть зарыта внутри класса так глубоко, что бы внешний код смог его сломать;
Иногда идеальный вариант:
struct point
{
int x;
int y;
};
Нет? А Вы поглядите сколько кода надо написать в таком варианте и при полной инкапсуляции. А главное, что эта инкапсуляция даст, кроме увеличения кода?
Здравствуйте, remark, Вы писали:
R>Он и в тундре будет выглядеть идеальным
Только боюсь его 100 км/ч за 3.6 сек. никому будет не нужна;
N>>Мне кажется, что это зависит от задачи. Самое главное, чего нужно придерживаться, что один класс решает или отвечает ровно за одну поставленную перед ним задачу, а информация о том, как он её решает должна быть зарыта внутри класса так глубоко, что бы внешний код смог его сломать;
R>Нет? А Вы поглядите сколько кода надо написать в таком варианте и при полной инкапсуляции. А главное, что эта инкапсуляция даст, кроме увеличения кода?
Какую задачу решает данный класс? По мне, так просто хранение двух величин. И инкапсуляции тут вполне достаточно (из моего поста это кстати следует ) – приведите пример легально кода, который поставит в ступор объект этого класса, то есть нарушит его внутреннюю логику;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, remark, Вы писали:
N>>Мне кажется, что это зависит от задачи. Самое главное, чего нужно придерживаться, что один класс решает или отвечает ровно за одну поставленную перед ним задачу, а информация о том, как он её решает должна быть зарыта внутри класса так глубоко, что бы внешний код смог его сломать;
R>Иногда идеальный вариант: R>
R>struct point
R>{
R> int x;
R> int y;
R>};
R>
R>Нет? А Вы поглядите сколько кода надо написать в таком варианте и при полной инкапсуляции. А главное, что эта инкапсуляция даст, кроме увеличения кода?
Иногда это идеальный вариант, иногда — нет. Всё от задачи зависит.
Здравствуйте, MBy, Вы писали:
MBy>Привет!
MBy>Сообственно, мелочный вопрос. В общем случае, так ли должен выглядеть «идеальный» класс?
Безотносительно рассуждений о несостоятельности слова "иделльный" — не нравиться мне ваш клас. Я бы убрал из него protected секцию а всё что в ней отпавил с private
Здравствуйте, np9mi7, Вы писали:
N>Здравствуйте, remark, Вы писали:
R>>Он и в тундре будет выглядеть идеальным
N>Только боюсь его 100 км/ч за 3.6 сек. никому будет не нужна;
Идеальную сущность не заботят такие приземлённые мелочи
N>>>Мне кажется, что это зависит от задачи. Самое главное, чего нужно придерживаться, что один класс решает или отвечает ровно за одну поставленную перед ним задачу, а информация о том, как он её решает должна быть зарыта внутри класса так глубоко, что бы внешний код смог его сломать;
R>>Нет? А Вы поглядите сколько кода надо написать в таком варианте и при полной инкапсуляции. А главное, что эта инкапсуляция даст, кроме увеличения кода?
N>Какую задачу решает данный класс? По мне, так просто хранение двух величин. И инкапсуляции тут вполне достаточно (из моего поста это кстати следует ) – приведите пример легально кода, который поставит в ступор объект этого класса, то есть нарушит его внутреннюю логику;
Не знаю, насчёт внутренней логики (т.е. не понимаю, что это такое), а вот код, нарушающий инвариант класса, пожалуйста:
point p;
p.x = -1; // Нарушили, что числа должны быть положительными
p.y = 1000000; // Нарушили, что числа должны быть не больше размера экрана, допустим 1024
Здравствуйте, bkat, Вы писали:
B>Здравствуйте, MBy, Вы писали:
MBy>>Привет!
MBy>>Сообственно, мелочный вопрос. В общем случае, так ли должен выглядеть «идеальный» класс?
B>Ну в общем да. Это и есть «идеальный» класс — класс без данных и явных методов
Может тогда:
class Name;
Или:
// Идеальный класс Name - к сожалению его нельзя представить в реальных теминах
Здравствуйте, remark, Вы писали:
R>Идеальную сущность не заботят такие приземлённые мелочи
Поэтому в тундре нужно ездить на Aston Martin DB9 V12
R>Не знаю, насчёт внутренней логики (т.е. не понимаю, что это такое)
Логика у этого объекта проста — сохранить две целочисленные величины;
R>а вот код, нарушающий инвариант класса, пожалуйста:
R>
R>point p;
R>p.x = -1; // Нарушили, что числа должны быть положительными
R>p.y = 1000000; // Нарушили, что числа должны быть не больше размера экрана, допустим 1024
R>
А если это не координаты экрана? А если это f(x, y) — производятся вычисления мат. функции на парах принадлежащих пространству Z x Z? Этим кодом ты ничего не испортил
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, np9mi7, Вы писали:
R>>а вот код, нарушающий инвариант класса, пожалуйста:
R>>
R>>point p;
R>>p.x = -1; // Нарушили, что числа должны быть положительными
R>>p.y = 1000000; // Нарушили, что числа должны быть не больше размера экрана, допустим 1024
R>>
N>А если это не координаты экрана? А если это f(x, y) — производятся вычисления мат. функции на парах принадлежащих пространству Z x Z? Этим кодом ты ничего не испортил
Что значит "если"??? Я дал вполне конкрентый пример, с вполне конкретным предназначением класса.
Непонятно. Вот представь, ты пишешь класс сокета, а тебе говорят, а если это класс не сокет, а окно, то твой код неправильный. Абсурд...
Здравствуйте, remark, Вы писали:
N>>А если это не координаты экрана? А если это f(x, y) — производятся вычисления мат. функции на парах принадлежащих пространству Z x Z? Этим кодом ты ничего не испортил
R>Что значит "если"??? Я дал вполне конкрентый пример, с вполне конкретным предназначением класса. R>Непонятно. Вот представь, ты пишешь класс сокета, а тебе говорят, а если это класс не сокет, а окно, то твой код неправильный. Абсурд...
Напомню, что посыл была такой R>Иногда идеальный вариант:
struct point
{
int x;
int y;
};
(про экран и ограничения ни слова нет), далее оказывается, что это экран и координаты в пределах [0, 1024). Тогда твой класс не идеально подходит для решения данной задачи . Зная твоё отношение к unsigned всё же осмелюсь написать такое — более идеальное (решающую проблему > 0):
struct point
{
unsigned short x;
unsigned short y;
};
, далее, если приложение действительно может (в результате вычислений или просто из внешних источников) получить в point не валидные координаты за отрезком [0, 1024), то написал бы так:
struct point
{
int x;
int y;
bool is_valid() const{
return x > 0 && x < 1024 && y > 0 && y < 1024;
}
};
, потому как так или иначе придеться делать эту проверку;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, korzhik, Вы писали:
K>мне кажется клиппинг лучше делать на более высоких уровнях.
Согласен, например в месте в котором могут быть получены невалидные данные. Так или иначе, метод или функция выполняющая эту проверку завязана на логику point, а значит входит в её интерфейс — это и хотел показать. В коде есть небольшая неточность, думаю все обратили внимание:
struct point
{
int x;
int y;
bool is_valid() const{
return!(x < 0) && x < 1024 && !(y < 0) && y < 1024;
}
};
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Здравствуйте, np9mi7, Вы писали:
N>Согласен, например в месте в котором могут быть получены невалидные данные. Так или иначе, метод или функция выполняющая эту проверку завязана на логику point, а значит входит в её интерфейс — это и хотел показать.
А вот входит ли валидация в интерфейс — и как она туда входит — это большой вопрос.
В ряде случаев разумнее сделать внешнюю функцию (или даже набор функций), нежели раздувать интерфейс класса.
Здравствуйте, np9mi7, Вы писали:
N>Здравствуйте, korzhik, Вы писали:
K>>мне кажется клиппинг лучше делать на более высоких уровнях.
N>Согласен, например в месте в котором могут быть получены невалидные данные. Так или иначе, метод или функция выполняющая эту проверку завязана на логику point, а значит входит в её интерфейс — это и хотел показать.
Тем не менее, хоть некая другая функция/класс входит в интерфейс point, записать в point невалидные данные никто не мешает, т.к. на доступность членов point это никак не влияет. И тем не менее такой класс point может быть подходящим решением задачи.
Что я хочу сказать. Делать или нет полную инкапсуляцию — решение компромиссное. В какой-то ситуации ограниченное "расползание" ответственности за инвариант может быть вполне приемлемым и лучше, чем описание "идеального" класса. Особенно при использовании таких классов как pair/tuple.
Здравствуйте, Кодт, Вы писали:
К>А вот входит ли валидация в интерфейс — и как она туда входит — это большой вопрос.
Согласен, что это большой вопрос. Исхожу из тех предпосылок, что интерфейс класса это не только открытые методы и данные, а ещё все свободные функции и операторы, которые описывают связь между объектами этого класса и другими объектами (это я Herb — а Sutter — а начитался Namespaces & Interface Principle);
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.