pivoo -> "Применение protected-методов" :
p> При проектировании классов какие должны быть предпосылки к объявлению p> метода protected или private
p> Мне кажется, что методы которые специфичны для конкретно этого класса p> должны объявляться private, а остальные, но которые не должны быть p> public должны объявляться protected.
p> Корректно сформулировать вопрос не удалось, но надеюсь вы меня p> поняли.
p> Правильно ли я думаю?
Тут все просто.
Сделай все методы private изменяй из на protected/public при необходимости,
т.е. когда другой класс захочет их заюзать.
Здравствуйте, prVovik, Вы писали:
V>Идея все спроектировать и спланировать заранее — использовалась у нас при коммунизме. Она вроде бы хорошая, но, как показала история, не работает
Планирование — залог успеха проекта, пренебрежение им — залог провала. И СССР тут не при чем.
V>Поэтому, надо действовать иначе, а именно не принимать проектного решения до тех пор, пока не будешь в нем уверен на все 100%, иначе надо всячески оттягивать момент принятия такого решения.
Если у вас в объектной модели 2-3 сотни классов, в каждом из которых имеются какие-то оттянутые (непринятые) решения, то это 100% приведет к срыву сроков, так как это ведет к взрывному росту сложности и количества деталей, необходимых держать в голове (т.е. количеству неотъемлемых знаний, за которыми скрываются незаменимые люди, что в свою очередь, всегда зло).
Вообще пуристский (самый правильный, но обычно трудно реализуемый :) подход изложил S.Yu.Gubanov, но в несколько категоричной форме, и кажется перепутал причину и следствие . Причина — это то, что наследование реализации = в целом есть зло, так как кроет в себе опасность, не видимую на первый взгляд, но которая, если по-хорошему, приводит к серьезному удару по low coupling и testability, так как принуждает при реализации потомков делать какие-то заключения о _реализации_ предка. Пример:
class B
{
public:
int public_op()
{
return real_op1();
}
protected:
virtual int real_op1()
{
return real_op2();
}
virtual int real_op2()
{
return 1;
}
};
class C : public B
{
protected:
virtual int real_op2()
{
return real_op1();
}
}
Код корректный. Класс B — корректный, класс C — корректный, но вот при выполнении слдедующего кода (тоже корректного), использующего нашу модель:
C c;
c.public_op();
Мы воткнемся в stack overflow. Почему? Классы C и B связаны более жестко, чем это может показаться.
Так вот после признания наследования реализации злом, мы приходим к выводу, что protected — тоже зло, так как без наследования реализации такой модификатор ни к чему . Идея в общем-то здоровая и сильно упрощающая модель, поддержку и тестирование, но обячно менее продуктивна.
Теперь о protected. Мое мнение заключается в том, что как protected надо объявлять методы реализации, облегченные для доверительного вызывающего кода (т.е. наследников и friend'ов). Облегченные, например, в смысле отсутствия проверки на входные параметры или не публикующие исключения. То есть:
class B
{
public:
void public_op(int p1, int p2, void* p3)
{
// делаем проверку аргументовif (p1 > 1 || p2 <100 || p3 == NULL)
throw invalid_argument("f.u.");
// ловим исключения, чтобы их потом опубликовать (например сообщением пользователю!)try
{
real_op(p1, p2, p3);
}
catch (std::exception e)
{
exception_publisher::instance().publish(e);
}
}
protected:
void real_op(int p1, int p2, void* p3)
{
// а тут уже реализация без проверки и публикации
}
}
Тогда, реализуя "class C : public B" мы можем использовать более быструю реализацию op (real_op), так как сами уже будем проверять передаваемые параметры и сами будем публиковать исключения, если это потребуется.
В других ситуациях:
"в базе есть кусок красивый кусок кода, который так и хочется вызвать из потомков",
"в базе есть метод, побочный эффект которого очень хорошо меняет состояние объекта",
"да в базе это уже реализовано, только вот тут надо if'чик воткнуть, а тут подтереть, да дат подписать"
и т.п. "удобности" и ложные упрощения,
использование protected неоправданно и следует либо выделять метод, в том числе статический, либо выделять класс, в том числе внутренний для базы protected хелпер, который использовать уже в безопасной манере.
V>Логика тут простая: процедура понижения степени защиты метода занимает несколько секунд, а обратная процедура может потребовать переписывания большого количества кода.
А тесты и спецификации переписывать уже непринято? Ведь изменения видимости метода класса — это огромное изменение модели, поэтому потребуется переписать массу тестов, чтобы протестировать получение объектом нового публичного сообщения в каждом из его состояний.
Здравствуйте, hrg, Вы писали:
hrg>pivoo -> "Применение protected-методов" :
p>> При проектировании классов какие должны быть предпосылки к объявлению p>> метода protected или private
p>> Мне кажется, что методы которые специфичны для конкретно этого класса p>> должны объявляться private, а остальные, но которые не должны быть p>> public должны объявляться protected.
p>> Корректно сформулировать вопрос не удалось, но надеюсь вы меня p>> поняли.
p>> Правильно ли я думаю?
hrg>Тут все просто. hrg>Сделай все методы private изменяй из на protected/public при необходимости, hrg>т.е. когда другой класс захочет их заюзать.
Это не правильный подход к проектированию классов (исходя из правила 32 в
книге Скотта Майерса "Наиболее эффективное использование С++", почему-то
я ему доверяю...). Нужно делать так, что бы переделывать, даже по мелочи не
приходилось.
Hello, Mishka!
You wrote on Fri, 30 Jul 2004 14:10:24 GMT:
p>>> Вопрос не в целях проекта а в правильном проектировании p>>> классов, хочется делать не тяп-ляп ... p>>> чтобы не было мучительно больно за бесцельно прожитое время ...
M> Практика показала, что нужно писать код на чём-нибудь простом вроде C#, M> а не рисовать UML диаграммы. И использовать принцип минимализма.
Практика каждому свое показывает
With best regards, Sergey.
Posted via RSDN NNTP Server 1.9 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, pivoo, Вы писали:
P>При проектировании классов какие должны быть предпосылки P>к объявлению метода protected или private...
Рискуя получить по шее от адептов создания иерархий классов... позволю себе посоветовать такую штуковину:
1) Объявляй интерфейс класса как абстрактный класс — у интерфейса, очевидно, все public.
2) В классе реализующем этот интерфейс все делай private кроме, разумеется, уже описанного интерфейса.
3) Этот класс никому внешнему не показывай, а показывай только интерфейс и фабрику по производству объектов реализующих этот интерфейс.
4) Забудь про все остальное наследование, пользуйся только двух уровневым ИНТЕРФЕЙС -> РЕАЛИЗАЦИЯ.
5) Вместо иерархий наследования используй композицию полиморфных объектов и абстрактные фабрики.
В некоторых случаях это будет приводить к большему количеству кода, но оно того стоит. Сопровождать такую систему гораздо проще.
Здравствуйте, pivoo, Вы писали:
P>Так а protected для кого придумали тогда.
Я же сказал: SYG>>4) Забудь про все остальное наследование, пользуйся только двух уровневым ИНТЕРФЕЙС -> РЕАЛИЗАЦИЯ.
и нету никакого protected-а. Когда придумывали protected, тогда до интерфейсов еще не додумались. Protected — это пережиток прошлого, так сказать "ложное направление развития ООП".
Здравствуйте, pivoo, Вы писали:
P>Здравствуйте, hrg, Вы писали:
hrg>>гавново... (зачеркнуто) это тоже просто: напиши цели проекта сюда, а мы тут hrg>>уж как нибудь
P>Вопрос не в целях проекта а в правильном проектировании P>классов, хочется делать не тяп-ляп ... P>чтобы не было мучительно больно за бесцельно прожитое время ...
Это явно по-молодости.
Один из военных законов Мэрфи: Если это глупо, но работает — значит, это не глупо.
В общем абсолютной истины (то бишь, правильности) — нет. Как напишешь, так и будет правильно. Если, конечно, специально лабуду всякую писать не будешь.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Сантехник, Вы писали:
С>Методы, используемые иерархией классов с твоим проектируемым С>классом в корне — protected.
Небольшое добавление. protected — это интерфейс для наследников, причем интерфейс может быть использован в обе стороны. Либо потомком для доступа к некоторой информации базового класса, которая должная остаться недоступной окружающему миру, либо базовым классом для делегирования деталей реализации некоторого алгоритма потомку (например, паттерн "Шаблонный метод").
Второй вариант представлен во всей красе в std::basic_streambuf (C++ STL).
p>> Вопрос не в целях проекта а в правильном проектировании p>> классов, хочется делать не тяп-ляп ... p>> чтобы не было мучительно больно за бесцельно прожитое время ...
Практика показала, что нужно писать код на чём-нибудь простом вроде C#, а не рисовать UML диаграммы. И использовать принцип минимализма.
Здравствуйте, pivoo, Вы писали:
P>При проектировании классов какие должны быть предпосылки P>к объявлению метода protected или private
Идея все спроектировать и спланировать заранее — использовалась у нас при коммунизме. Она вроде бы хорошая, но, как показала история, не работает
Поэтому, надо действовать иначе, а именно не принимать проектного решения до тех пор, пока не будешь в нем уверен на все 100%, иначе надо всячески оттягивать момент принятия такого решения. Как говориться: Не знаешь брода — не лезь в воду. Исходя из этого принципа, можно дать тебе рекомендацию:
1) если ты полностью уверен, что метод будет использоваться клиентами класса, делай его public
2) если ты полностью уверен, что метод будет использоваться потомками класса, делай его protected
3) все остальное делай private.
Логика тут простая: процедура понижения степени защиты метода занимает несколько секунд, а обратная процедура может потребовать переписывания большого количества кода. То есть цена ошибки гораздо выше. Делай выводы...
При проектировании классов какие должны быть предпосылки
к объявлению метода protected или private
Мне кажется, что методы которые специфичны для конкретно
этого класса должны объявляться private, а остальные, но
которые не должны быть public должны объявляться protected.
Корректно сформулировать вопрос не удалось, но надеюсь
вы меня поняли.
Здравствуйте, pivoo, Вы писали:
P>Правильно ли я думаю?
Методы, являющиеся интерфесом класса, т.е. которые будут дергаться
другими классами — public
Методы, используемые иерархией классов с твоим проектируемым
классом в корне — protected.
Все методы, специфичные только для данного класса — private.
pivoo -> "Re[2]: Применение protected-методов" :
hrg>> Тут все просто. hrg>> Сделай все методы private изменяй из на protected/public при hrg>> необходимости, hrg>> т.е. когда другой класс захочет их заюзать.
p> Это не правильный подход к проектированию классов (исходя из правила p> 32 в книге Скотта Майерса "Наиболее эффективное использование С++", p> почему-то я ему доверяю...). Нужно делать так, что бы переделывать, p> даже по мелочи не приходилось.
(задумчиво) вообще то во всех современых походах, которые я видел
предлагаются итеративные методы. Хотя классический "водопад" — это конечно
соблазнительно.
korzhik -> "Re: Применение protected-методов" :
P>> При проектировании классов какие должны быть предпосылки к P>> объявлению метода protected или private
k> 1. Методы которые являются деталью реализации не должны k> вызываться напрямую клиентами класса поэтому должны быть private.
(догадливо) осталось только выяснить, каких из них являются деталью
реализации.
k> 2. Методы которые должны использоваться производными классами, но не k> клиентами на прямую, делай protected
А если они не будут ими использоваться?
k> ну это конечно всё поверхностно
ЗЫ Ты бы минусами без объяснений не разбрасывался?
Yury Kopyl aka hrg | http://id.totem.ru | "бысто сп..ил и ушел — называется
нашел..."
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Рискуя получить по шее от адептов создания иерархий классов... позволю себе посоветовать такую штуковину:
SYG>1) Объявляй интерфейс класса как абстрактный класс — у интерфейса, очевидно, все public. SYG>2) В классе реализующем этот интерфейс все делай private кроме, разумеется, уже описанного интерфейса. SYG>3) Этот класс никому внешнему не показывай, а показывай только интерфейс и фабрику по производству объектов реализующих этот интерфейс. SYG>4) Забудь про все остальное наследование, пользуйся только двух уровневым ИНТЕРФЕЙС -> РЕАЛИЗАЦИЯ. SYG>5) Вместо иерархий наследования используй композицию полиморфных объектов и абстрактные фабрики.
SYG>В некоторых случаях это будет приводить к большему количеству кода, но оно того стоит. Сопровождать такую систему гораздо проще.
Так а protected для кого придумали тогда.
И вобще, вопрос связан с тем, что хочется писать грамотные классы,
а никто не знает, будет ли конкретно этот класс использоваться
в иерархии наследования в дальнейшем(может даже и отдаленном)
будующем и не факт что мной. Поэтому хочется получить достаточно
четкие (если это вобще возможно) правила по выбору private или protected.
Здравствуйте, hrg, Вы писали:
hrg>pivoo -> "Re[2]: Применение protected-методов" :
hrg>>> Тут все просто. hrg>>> Сделай все методы private изменяй из на protected/public при hrg>>> необходимости, hrg>>> т.е. когда другой класс захочет их заюзать.
p>> Это не правильный подход к проектированию классов (исходя из правила p>> 32 в книге Скотта Майерса "Наиболее эффективное использование С++", p>> почему-то я ему доверяю...). Нужно делать так, что бы переделывать, p>> даже по мелочи не приходилось.
hrg>(задумчиво) вообще то во всех современых походах, которые я видел hrg>предлагаются итеративные методы. Хотя классический "водопад" — это конечно hrg>соблазнительно.
Итеративный-то он итеративный, но при проектировании необходимо все учитывать.
А реализация класса не должна зависеть от области его применения,
т.е. если область изменяется, хорошо спроектированный класс меняться
не должен. И итеративность тут вовсе не при чем.
hrg> Yury Kopyl aka hrg | http://id.totem.ru | Гордость мешает доходам!
Здравствуйте, hrg, Вы писали:
hrg>Тут все просто. hrg>Сделай все методы private изменяй из на protected/public при необходимости, hrg>т.е. когда другой класс захочет их заюзать.
Совершенно согласен. Это так называемый минималисткий подход. Делаешь сначала все методы private, а потом по необходимости их открываешь. А вы что думали, что можно всё спроектировать изначально, как об этом говорят "гуру" типа Буча?
Hello, pivoo!
You wrote on Fri, 30 Jul 2004 10:40:55 GMT:
p> Это не правильный подход к проектированию классов (исходя из правила 32 p> в книге Скотта Майерса "Наиболее эффективное использование С++", p> почему-то я ему доверяю...). Нужно делать так, что бы переделывать, даже p> по мелочи не приходилось.
Здравствуйте, hrg, Вы писали:
k>> 1. Методы которые являются деталью реализации не должны k>> вызываться напрямую клиентами класса поэтому должны быть private.
hrg>(догадливо) осталось только выяснить, каких из них являются деталью hrg>реализации.
а чего догадываться то?
ты же сам разрабатываешь класс и знаешь для чего нужен тот или иной метод.
hrg>ЗЫ Ты бы минусами без объяснений не разбрасывался?
Время нет объяснять
я просто не согласен с таким минималистическим подходом к проектированию классов
вот и выразил своё не согласие поставив -1. На рейтинг он всё равно не скажется.
pivoo -> "Re[4]: Применение protected-методов" :
hrg>> (задумчиво) вообще то во всех современых походах, которые я видел hrg>> предлагаются итеративные методы. Хотя классический "водопад" — это hrg>> конечно соблазнительно.
p> Итеративный-то он итеративный, но при проектировании необходимо все p> учитывать. p> А реализация класса не должна зависеть от области его применения, p> т.е. если область изменяется, хорошо спроектированный класс меняться p> не должен. И итеративность тут вовсе не при чем.
Ты библиотеку,которую будеь выкладывать/продавать/разное на сторону
проектируешь или приложение, где видимость всех классов ясна?
korzhik -> "Re[3]: Применение protected-методов" :
k>>> 1. Методы которые являются деталью реализации не должны k>>> вызываться напрямую клиентами класса поэтому должны быть k>>> private.
hrg>> (догадливо) осталось только выяснить, каких из них являются hrg>> деталью реализации. k> а чего догадываться то? k> ты же сам разрабатываешь класс и знаешь для чего нужен тот или иной k> метод.
Т.к. я в основом сейчас разрабатываю архитектуру через TDD, то не совсем не
хочется тратить своем время на прогнозирование как оно возможно будет
работать. Опыт показал, что как бы ни хорошо был написал класс, все равно 2
раза переделывать
Yury Kopyl aka hrg | http://id.totem.ru | "Сегодня с нами ты не пьешь, а
завтра Родине изменишь!"
Здравствуйте, hrg, Вы писали:
k>> а чего догадываться то? k>> ты же сам разрабатываешь класс и знаешь для чего нужен тот или иной k>> метод.
hrg>Т.к. я в основом сейчас разрабатываю архитектуру через TDD,
А, ну тогда понятно.
В общем разные подходы имеют право на жизнь.
hrg> Ты библиотеку,которую будеь выкладывать/продавать/разное на сторону hrg>проектируешь или приложение, где видимость всех классов ясна?
А фиг его знает, по разному повернуться может.
Видимо все-таки вопрос не корректно задал,
мне интересно было как правильно делать,
а не как сделать что бы всего лишь компилировалось
и работало в данный момент.
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>и нету никакого protected-а. Когда придумывали protected, тогда до интерфейсов еще не додумались. Protected — это пережиток прошлого, так сказать "ложное направление развития ООП".
Мне очень нравится internal protected (C#), а также package модификатор (Java). Очень полезные штуки для прятанья деталей.
Здравствуйте, Mishka, Вы писали:
M>Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>>и нету никакого protected-а. Когда придумывали protected, тогда до интерфейсов еще не додумались. Protected — это пережиток прошлого, так сказать "ложное направление развития ООП".
M>Мне очень нравится internal protected (C#), а также package модификатор (Java). Очень полезные штуки для прятанья деталей.
Здравствуйте, korzhik, Вы писали:
K>а можете объяснить что это за штуки?
Модификаторы доступа в компонентно-ориентированном программировании.
Берёшь и пишешь:
Компонента 1
public class A
{
protected internal void f(){}
}
public class B
{
public void g()
{
A a = new A();
a.f(); // доступ есть, поскольку объявлено как internal (внутренний)
}
}
Компонента 2
public class С : A
{
public void g()
{
f(); // доступ есть, поскольку объявлено как protected
}
}
Очень полезно, когда на уровне компонента метод должен быть public, а для всего остального мира — protected.
pivoo -> "Re[6]: Применение protected-методов" :
hrg>> Ты библиотеку,которую будеь выкладывать/продавать/разное на hrg>> сторону проектируешь или приложение, где видимость всех классов hrg>> ясна?
p> А фиг его знает, по разному повернуться может. p> Видимо все-таки вопрос не корректно задал, мне интересно было как p> правильно делать, а не как сделать что бы всего лишь компилировалось p> и работало в данный момент.
гавново... (зачеркнуто) это тоже просто: напиши цели проекта сюда, а мы тут
уж как нибудь
Здравствуйте, hrg, Вы писали:
hrg>гавново... (зачеркнуто) это тоже просто: напиши цели проекта сюда, а мы тут hrg>уж как нибудь
Вопрос не в целях проекта а в правильном проектировании
классов, хочется делать не тяп-ляп ...
чтобы не было мучительно больно за бесцельно прожитое время ...
pivoo -> "Re[8]: Применение protected-методов" :
hrg>> гавново... (зачеркнуто) это тоже просто: напиши цели проекта сюда, hrg>> а мы тут уж как нибудь
p> Вопрос не в целях проекта а в правильном проектировании p> классов, хочется делать не тяп-ляп ... p> чтобы не было мучительно больно за бесцельно прожитое время ...
Ну как тебе сказать? Правильность, она бывает разная.
Здравствуйте, Frostbitten, Вы писали:
F>Планирование — залог успеха проекта, пренебрежение им — залог провала. И СССР тут не при чем.
Это, конечно, правильно, но только не стоит слишком полагаться на планирование. Дело тут вот в чем. Планирование хорошо тогда, когда оно безошибочно. А это утопия Поэтому, я считаю, что лучше отложить смутное архитектурное решение на потом, чем допустить в нем ошибку, особенно на ранней стадии. Откладывая решение, мы, таким образом, не отказываемся от планирования, но, зато, оберегаемся от архитектурных ошибок.
>Если у вас в объектной модели 2-3 сотни классов, в каждом из которых имеются какие-то оттянутые (непринятые) решения, то это 100% приведет к срыву сроков, так как это ведет к взрывному росту сложности и количества деталей, необходимых держать в голове (т.е. количеству неотъемлемых знаний, за которыми скрываются незаменимые люди, что в свою очередь, всегда зло).
Не очень понял о чем это вы? Что за сложность и какие такие детали надо держать в голове?
>спецификации переписывать уже непринято?
Автоматизированные системы построения документации спасут...
>Ведь изменения видимости метода класса — это огромное изменение модели, поэтому потребуется переписать массу тестов, чтобы протестировать получение объектом нового публичного сообщения в каждом из его состояний.
Ну а что мешает написать тест для закрытого метода, особенно, если он делает что-то осмысленное?
Sergey -> "Re[11]: Применение protected-методов" :
p>>>> Вопрос не в целях проекта а в правильном проектировании p>>>> классов, хочется делать не тяп-ляп ... p>>>> чтобы не было мучительно больно за бесцельно прожитое время ...
M>> Практика показала, что нужно писать код на чём-нибудь простом вроде M>> C#, а не рисовать UML диаграммы. И использовать принцип минимализма.
S> Практика каждому свое показывает
Хочешь поговрить об этом?
Yury Kopyl aka hrg | http://id.totem.ru | "Спам придумали боги в отместку
за наши молитвы."
Здравствуйте, pivoo, Вы писали:
P>При проектировании классов какие должны быть предпосылки P>к объявлению метода protected или private
P>Мне кажется, что методы которые специфичны для конкретно P>этого класса должны объявляться private, а остальные, но P>которые не должны быть public должны объявляться protected.
P>Корректно сформулировать вопрос не удалось, но надеюсь P>вы меня поняли.
P>Правильно ли я думаю?
То, что не может быть открыто внешним клиентам класса, не должно объявляться public.
То из оставшегося, что не может быть открыто наследникам класса, должно объявляться private.
Остальное — protected.