Re: Проблема проектирования
От: SP_ Украина  
Дата: 10.07.07 09:30
Оценка: 9 (3) +1
Здравствуйте, Kostyan2204, Вы писали:
K>Как это реализовать?
Один из вариантов
class IProduction
{

};

class IPurchased : public IProduction
{
....
}

class ISelfMade : public IProduction
{
....
}

class IDesign
{
...
}

class IForeignDesign : public IDesign
{
....
}

class ISelfDesign : public IDesign
{

}


class Izdelie 
{
    IDesign* design;
    IProduction * production;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Проблема проектирования
От: mrozov  
Дата: 10.07.07 22:48
Оценка: +1 -3
Здравствуйте, Kostyan2204, Вы писали:

K>Как это реализовать?


Ну реализовать-то это не сложно. Но, если я правильно понимаю, то вопрос в том — как это реализовать красиво с точки зрения ООП?

Когда ты говоришь, что в одном случае у класса должны быть поля, а в другом нет, то это уже отступление от канонов. Дело не в том, какие поля/свойства должны быть, а в том, каким должно быть поведение.

Т.е. — для каких участков программы важно наличие или отсутствие поля Price? Для сохранения и загрузки? Значит в некоем базовом классе Producer должны быть абстрактные методы Save и Load. А в двух наследниках SelfProducer и OtherProducer эти методы должны быть реализованы с учетом наличия или отсутствия этого поля.

Нужно по-разному отображать данные в отчете? Значит в классе Producer нужен абстрактный метод GetReportData. И т.п.

При любом другом подходе тебе так или иначе придется писать код типа
if (row.Purchased) return row.Price else return 0;

а тогда какая, собственно, разница, как все это программировать? Тогда проще всего сразу сделать один класс со всеми нужными свойствами и не париться с иерархиями, меньше проблем будет. Главное, получать доступ к данным только через специальные методы, проверяющие поля-флаги.
Re[2]: Проблема проектирования
От: mrozov  
Дата: 12.07.07 09:43
Оценка: +2 -2
Забавные люди, ей-богу...

Обратите внимание на то, к чему тут призывают автора — завести с полдюжины дополнителных интерфейсов.
Вопрос — зачем? Чтобы вместо кода
if (!obj.IsSelfMade)
 return obj.Price;

Писать код
if (!obj.Production.IsSelfMade)
 return ((SelfMadeProduct)obj.Production).Price;

Ну и кому от этого легче? Тому кто пишет исходные классы? Нет, объем его работы увеличился. Тому, кто их использует? Боже, нет, его жизнь только усложнилась. Может, такой код проще поддерживать? Тоже нет. Так в чем выгода? В объектной ориентированности? Так это не ООП, это обезьянничество на тему ООП, не более того.

ООП это станет только тогда, когда для того, кто использует исходный класс, вообще не имеет значения — есть там поле Price или нет. Этого частично можно добиться спрятав внутри SelfMadeProduct некое значение поля Price по-умолчанию, но это:
1. Только полумера
2. Это проще и быстрее сделать в самом исходном классе, чем писать три дополнительных.

Построение иерархии становится оправданным только тогда, когда вы используете полиморфность на полную катушку — наделяя разных наследников разным поведением.
Re: Проблема проектирования
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 10.07.07 11:39
Оценка: 3 (1) +1
Здравствуйте, Kostyan2204,

Как я понял из Вашего описания, каждое изделие должно быть:

  1. Спроектировано.
  2. Изготовлено.
  3. И сохранено и учтено в Вашей базе данных.

Исходя из этого, с изделием нужно связать данные, которые:

  1. относятся к проектированию;
  2. относятся к изготовлению;
  3. важны для хранения и учета.

Эти данные могут быть инкапсулированы в отдельных классах:

  1. Проектировщикхранит информацию о том, кто проектировал.
  2. Изготовительхранит информацию об изготовителе и способе изготовления.
  3. Регистраторхранит информацию, важную для регистрации и учета.

Таким образом, отдельное Изделие сожно представить в виде набора из трех ссылок на три объекта:

  1. Проектировщик.
  2. Изготовитель.
  3. Регистратор.

На C++ это можно представить так:

class CDesigner;
class CProducer;
class CRegistrar;

class CProduct
{
   CDesigner * m_pDesigner;
   CProducer * m_pProducer;
   CRegistrar * m_pRegistrar;
};


Конкретные дизайнеры и производители могут быть выведены из базовых классов:

class CDesigner;
   class CSelfDesigner : public CDesigner;
   class COtherDesigner : public CDesigner;

class CProducer;
   class CSelfProducer : public CProducer;
   class COtherProducer : public COtherProducer;


Если классы COtherDesigner и CSelfProducer не содержат никаких данных, объекты этих классов могут быть созданы в одном экземпляре, и во всех изделиях, где это надо, должны быть ссылки на эти единственные экземпляры (здесь я применяю паттерн, который описан у Фаулера, как Special Case).
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re: Проблема проектирования
От: apilikov Россия  
Дата: 10.07.07 10:05
Оценка: 2 (1) -1
Здравствуйте, Kostyan2204, Вы писали:

K>Приветствую!


K>Помогите разобраться с проблемой проектирования.


K>Есть суперкласс Izdelie. (базовый для всех изделий). У всех изделий есть следующие атрибуты:

K>1) long ID; //Уникальный код изделия
K>2) string FullName; //Полное наименование материала
K>3) decimal Mass; //Масса изделия
K>4) Purchased; // Признак того, что изделие покупное

K>Изделия могут менять признак с ПОКУПНОЕ на СОБСТВЕННОЕ ИЗГОТОВЛЕНИЕ (и наоборот)


K>Если издлеия являются покупными, то у них имеются атрибуты ( Buyer — закупщик, Price — цена). Наоборот, изделия собственного производства, таких атрибутов у него нет.


K>С ДРУГОЙ СТОРОНЫ

K>Все изделия деляться на две группы (СОБСТВЕННОГО ПРОЕКТИРОВАНИЯ и ЧУЖОГО ПРОЕКТИРОВАНИЯ).
K>Изделия собственного проектирования (в отличии от чужих) имеют атрибут НОМЕР ЧЕРТЕЖА и ФАМИЛИЯ РАЗРАБОТЧИКА.

K>Как это реализовать?


а сделать абстрактный класс изделие и 2-х наследников от него тебе не удобно?
а ссылку на изделие реализовать как ссылку на абстрактный класс, а если нужно вызывать специфические функции приводить его к одному из наследников.
естественно тебе потребуется какой-то енумовский мембер который будет говорить какое это изделие. по нему можно будет ориентироваться.
либо сделать проще. не делать абстрактных классов а сделать один класс изделия который будет включать в себя поля характерные как для одного типа изделий так и для другого. это менее красиво зато проще.
на чем пишешь?
Re[5]: Проблема проектирования
От: mrozov  
Дата: 13.07.07 12:35
Оценка: -2
Здравствуйте, IB, Вы писали:

IB>Здравствуйте, mrozov, Вы писали:


M>>Нет, не означает.

IB>А какой ценой это "не означает"? Можешь привести решение, которое позволит при наличии в самом "Продукте" методов Save и Load избавить "Продукт" от знаний о конкретном хранилище?
Я тебе приведу два:
— сериализация — сохранение в Stream
— метод save/load является фабрикой для объектов, которые как раз и совмещают знание внутренности данного с конкретным хранилищем.
Фаулера почитай, в конце концов.

M>>Нет, не значит.

IB>Хоть сам-то понял на что ответил? =) Ты утверждаешь, что у автора топика гарантировано будет одно хранилище с фиксированной структурой, которое не поменяется в течении жизни приложения... Смело.
Я ничего такого не утверждаю, это ты у нас мастер неудачного чтения чужих мыслей.
Я уже не говорю о том, что первая часть твоего утверждения не имеет отношения ко второй.

M>>Есть понятие "сериализация".

IB>Понятие "сериализация" позволит тебе передать объект на клиента.
Два балла. Понятие "сериализация" позволяет мне сохранить данные в поток и восстановить из него. Это идеальный патерн для всех ситуаций, когда внутренее содержимое данных не имеет значения для кода извне.

M>>А еще есть паттерн "стратегия".

IB>Есть много замечательных паттернов, но с двух попыток боюсь, ты не угадал..
Бояться не надо, надо знать.
Фабричный метод + стратегия.

IB>Наверное самый логичный выход из такой ситуации, воспользоваться паттерном DTO, но зачем бороться с проблемами с помощю паттернов, когда можно их просто не создавать? То есть, убрать из объекта зависимость от хранилища, выкинув оттуда методы Save и Load и поместив их в соответствующий сервис?


Потому что для этого с внутренним содержимым должен уметь работать этот сервис.
Что возможно и даже оптимально (отражение + кодогенерация), но к ООП уже никакого отношения не имеет.

M>>Неправильный вывод. Когда как, зависит от многих прочих равных.

IB>Правильный, при прочих равных.
Глупый, если уж говорить точнее.

M>>Иногда (если при добавлении объекта в коллекцию нужно выполнть доплнительные шаги) в объекте появляются специальные методы, парные им.

IB>И часто такое бывает? Можешь придумать пример, чтобы возникла такая необходимость в данной задаче?
А при чем тут часто или нечасто? Такое бывает редко, благодаря универсальности операции добавления указателя в список. Но мне доводилось делать.

M>>Я именно об этом и написал, ты не заметил или не понял?

IB>Нет, ты писал как раз про полиморфизм через наследование, либо не смог свою мысль правильно донести...
Ты не смог это понять, что не то же самое. Я в конце написал, что для простых случаев проще всего вопользоваться условным выражением.

M>>То мы введем стратегию отображения в том или ином виде.

IB>Стратегия, как я посмотрю, твой любимый паттерн.. ) Так кто у нас будет формировать данные для отображения, стратегия или сам класс?
По обстоятельствам. Если поддержка разных вариантов сохранения не нужна (а она как правило не нужна), то в классе.
IB>И где у нас таки должен находиться метод формирования ReportData?
По обстоятельствам. Чаще всего в хранимой процедуре Несколько реже — в классе, разумеется. На выходе она будет выдавать что-то типа xml-я, воспринимаемого компонентой формирования отчета.

M>>И привяжем ее к этому конкретному потомку. Так или иначе.

IB>Так "так" или "иначе", и в каком виде?
По обстоятельствам. Хоть через Spring, это детали.

M>>Придется. Без вариантов.

IB>=) То что ты вариантов не знаешь, не значит что их нет..
Правильных ООП-вариантов нет. Другие существуют, но они еще сложнее.
Re[5]: Проблема проектирования
От: GlebZ Россия  
Дата: 13.07.07 15:22
Оценка: +2
Здравствуйте, mrozov, Вы писали:

M>Этот код:

M>
M>public double Price
M>{
M> get
M> {
M>  if (_isSelfMade)
M>    return SELF_PRICE;
M>  else
M>    return _price;
M> }
M>}
M>

M> — короче
Да.
M> — удобнее для понимания
Нет. И еще раз нет.
M> — быстрее, в конце концов
Нет.

Если короче, то отнюдь не значит что удобнее в использовании и быстрее. В случае, описанном здесь
Автор: SP_
Дата: 10.07.07
мы имеем классический пример агрегации. Фактически по типизации мы можем сказать, что данный объект имеет цену, или нет скрывая реализацию за интерфейсом. Мы можем собрать коллекцию IPurchased и обрабатывать ее единобразным образом. Мы можем забыть об основном объекте и просто раздавать IPurchased тем методам которым интересна только цена, а не состояние объекта. В твоем случае, мы получаем полное безразличие компилятора и проблему в том, что если возвращается цена, то это совсем не значит что мы ее купили, а значит только то, что нужно еще дополнительно ее проверить. И это не совсем есть гут.
Re[2]: Проблема проектирования
От: IB Австрия http://rsdn.ru
Дата: 12.07.07 15:58
Оценка: 3 (1)
Здравствуйте, mrozov, Вы писали:

M> Но, если я правильно понимаю, то вопрос в том — как это реализовать красиво с точки зрения ООП?

Ну давай, посмотрим, что в твоей версии не красиво, сточки зрения ООП...

M>Т.е. — для каких участков программы важно наличие или отсутствие поля Price? Для сохранения и загрузки?

Про сохранение и загрузку у автора топика ничего не было, однако что ты, что Кирилл вцепились в это сохранеие, ну да ладно..

M>Значит в некоем базовом классе Producer должны быть абстрактные методы Save и Load.

Наличие в базовом классе методов Save и Load — означает, что конкретная реализация класса должна знать о конкретном хранилище, куда придется сохранять цену. То есть, возникает совершенно ненужная связь, между классом продукта и хранилищем. Не нужная, потому что хранилище может быть самым разным для одного и того же объекта, в зависимости от ситуации — БД, XML, обычный файл и вообще все что угодно. А вдруг нам этот объект на удаленного клиента передать надо, будем и на клиенте такое же хранилище поддерживать и все эти потроха с собой таскать?
Теоретически, этой зависимости можно избежать, но зачем придумывать обходные маневры в виде красивых паттернов, когда можно просто не загонять себя в такую ситуацию, где эти маневры нужны?
Отсюда вывод, методов Save и Load ни в базовом классе, ни в классах конкертных продуктов быть не должно, в обычной коллекции методы Add и Remove разьве в объекте находятся, который сам себя в коллекцию помещает?

M>А в двух наследниках SelfProducer и OtherProducer эти методы должны быть реализованы с учетом наличия или отсутствия этого поля.

Полиморфизма можно добиться не только через наследование.

M>Нужно по-разному отображать данные в отчете? Значит в классе Producer нужен абстрактный метод GetReportData. И т.п.

То есть, мы еще в класс продукта и особенности его отображения запихнем? Тоже отличная идея. Что будем делать, если надо поразному данные о продуктах предоставлять, скажем, в виде таблицы и графика? А если разным пользователям, по разному его показывать надо, еще и поддержку прав там же реализуем?

M>При любом другом подходе тебе так или иначе придется писать

Не придется.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[4]: Проблема проектирования
От: mrozov  
Дата: 12.07.07 14:52
Оценка: +1
Здравствуйте, SP_, Вы писали:

SP_>А где написано что аффтара к таким извращениям подталкивают?

а ссылку на изделие реализовать как ссылку на абстрактный класс, а если нужно вызывать специфические функции приводить его к одному из наследников.

А вот обратного — ни разу.

SP_>По моему в обеих примерах есть ключевой глюк: в обоих if-ах опущена ветка else

Что в нем ключевого? Это просто возможный пример. Могут быть и другие.

SP_>с выносом логики расчета цены в соотвествующие классы. В этом случае мы используем

M>>полиморфность на полную катушку — наделяя разных наследников разным поведением.
SP_>

Неа, вы используете пушку для стрельбы по воробьям.
Этот код:
public double Price
{
 get
 {
  if (_isSelfMade)
    return SELF_PRICE;
  else
    return _price;
 }
}

— короче
— удобнее для понимания
— быстрее, в конце концов

Вариант с иерархией имеет смысл городить только тогда, когда меняется что-то большее, чем одно поле в зависимости от одного флага
И вот именно этот момент и важно доносить до людей — что ООП, это нечто большее, чем замена всех условных выражений наследованием.
Re[8]: Проблема проектирования
От: mrozov  
Дата: 13.07.07 09:33
Оценка: +1
Здравствуйте, SP_, Вы писали:

SP_>Здравствуйте, mrozov, Вы писали:


M>>Ты не запостил никакого решения. Ты всего-навсего описал названия классов в иерархии. Разницу чувствуешь?


SP_>А что есть какие то проблемы с реализацией этих классов?

Разумеется.

SP_> судя по оценкам моего поста с "названиями классов" топикстартеру все ясно

Судя по оценке у него не возникло вопросов. Это, сам понимаешь, не одно и то же.

Сформулирую иначе — человек, который может правильно воспринять столь лаконичный совет, в таком совете попросту не нуждается. Надеюсь, спорить не станешь?
Re[7]: Проблема проектирования
От: mrozov  
Дата: 13.07.07 14:55
Оценка: -1
Здравствуйте, IB, Вы писали:

Любопытно, нахрена ты сразу начал хамить, чем я тебя обидел? Превосходством в интеллекте?

Мне неинтересно с тобой спорить в таком духе, понимаешь? Я привел два классических примера из учебников по ООД. Сохранение/загрузка и отображение в отчете. Фаулер и .. уже не помню, Кериевски, что ли? Ты эти примеры даже не узнал и с ходу пошел плеваться минусами и оскорблениями.

То, о чем я говорю, применяется в индустрии уже десятилетиями. Та же сериализация, позволяющая сохранять данные в любом контейнере, поддерживающим интерфейс Stream. Методы типа Dump и прочее, прочее, прочее..

Желаю удачи тебе и твоим работодателям.
Re[3]: Проблема проектирования
От: MaximVK Россия  
Дата: 20.07.07 20:56
Оценка: +1
Здравствуйте, dr.Chaos, Вы писали:

DC>А какие премущества/недостатки у такого решения:


Ну хотя бы это требование для начала:

Изделия могут менять признак с ПОКУПНОЕ на СОБСТВЕННОЕ ИЗГОТОВЛЕНИЕ (и наоборот)"

.
Проблема проектирования
От: Kostyan2204  
Дата: 10.07.07 09:14
Оценка:
Приветствую!

Помогите разобраться с проблемой проектирования.

Есть суперкласс Izdelie. (базовый для всех изделий). У всех изделий есть следующие атрибуты:
1) long ID; //Уникальный код изделия
2) string FullName; //Полное наименование материала
3) decimal Mass; //Масса изделия
4) Purchased; // Признак того, что изделие покупное

Изделия могут менять признак с ПОКУПНОЕ на СОБСТВЕННОЕ ИЗГОТОВЛЕНИЕ (и наоборот)

Если издлеия являются покупными, то у них имеются атрибуты ( Buyer — закупщик, Price — цена). Наоборот, изделия собственного производства, таких атрибутов у него нет.

С ДРУГОЙ СТОРОНЫ
Все изделия деляться на две группы (СОБСТВЕННОГО ПРОЕКТИРОВАНИЯ и ЧУЖОГО ПРОЕКТИРОВАНИЯ).
Изделия собственного проектирования (в отличии от чужих) имеют атрибут НОМЕР ЧЕРТЕЖА и ФАМИЛИЯ РАЗРАБОТЧИКА.

Как это реализовать?
Re[2]: Проблема проектирования
От: Kostyan2204  
Дата: 10.07.07 10:26
Оценка:
Здравствуйте, apilikov, Вы писали:

A>а сделать абстрактный класс изделие и 2-х наследников от него тебе не удобно?


Возможно. Хотелось бы выслушать все варианты.

Разрабатываемая система будет являться хранилищем материалов, стандартных изделий и изделий собственного производства. Данные из неё должны будут использоваться в ERP-системе, а также в конструкторских спецификациях и технологических ведомостях.
(вобщем единое хранилище).

Может у вас есть ссылки на эту тему?
Интересуют восновном реализации (а не идея).

A>а ссылку на изделие реализовать как ссылку на абстрактный класс, а если нужно вызывать специфические функции приводить его к одному из наследников.

A>естественно тебе потребуется какой-то енумовский мембер который будет говорить какое это изделие. по нему можно будет ориентироваться.
A>либо сделать проще. не делать абстрактных классов а сделать один класс изделия который будет включать в себя поля характерные как для одного типа изделий так и для другого. это менее красиво зато проще.

A>на чем пишешь?

Пишу на C# 2.0
Re[3]: Проблема проектирования
От: apilikov Россия  
Дата: 10.07.07 10:28
Оценка:
Здравствуйте, Kostyan2204, Вы писали:

K>Здравствуйте, apilikov, Вы писали:


A>>а сделать абстрактный класс изделие и 2-х наследников от него тебе не удобно?


K>Возможно. Хотелось бы выслушать все варианты.


K>Разрабатываемая система будет являться хранилищем материалов, стандартных изделий и изделий собственного производства. Данные из неё должны будут использоваться в ERP-системе, а также в конструкторских спецификациях и технологических ведомостях.

K>(вобщем единое хранилище).

K>Может у вас есть ссылки на эту тему?

K>Интересуют восновном реализации (а не идея).

A>>а ссылку на изделие реализовать как ссылку на абстрактный класс, а если нужно вызывать специфические функции приводить его к одному из наследников.

A>>естественно тебе потребуется какой-то енумовский мембер который будет говорить какое это изделие. по нему можно будет ориентироваться.
A>>либо сделать проще. не делать абстрактных классов а сделать один класс изделия который будет включать в себя поля характерные как для одного типа изделий так и для другого. это менее красиво зато проще.

A>>на чем пишешь?

K>Пишу на C# 2.0

везет тебе. ну так что скажешь по поводу написанного выше?
Re[4]: Проблема проектирования
От: Kostyan2204  
Дата: 10.07.07 11:15
Оценка:
Здравствуйте, apilikov, Вы писали:

A>везет тебе. ну так что скажешь по поводу написанного выше?


Большое спасибо за предложенные варианты

Ещё подумаю немного, определюсь, потом скажу (и результат покажу )

P.S. А чем мне везёт?
Re[5]: Проблема проектирования
От: apilikov Россия  
Дата: 10.07.07 11:22
Оценка:
Здравствуйте, Kostyan2204, Вы писали:

K>Здравствуйте, apilikov, Вы писали:


A>>везет тебе. ну так что скажешь по поводу написанного выше?


K>Большое спасибо за предложенные варианты


K>Ещё подумаю немного, определюсь, потом скажу (и результат покажу )


K>P.S. А чем мне везёт?


тем что пишешь на С#. ))))
Re[3]: Проблема проектирования
От: SP_ Украина  
Дата: 12.07.07 14:29
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Забавные люди, ей-богу...


M>Обратите внимание на то, к чему тут призывают автора — завести с полдюжины дополнителных интерфейсов.

M>Вопрос — зачем?
M>.....
M>Ну и кому от этого легче?
А где написано что аффтара к таким извращениям подталкивают? По моему в обеих примерах есть ключевой глюк: в обоих if-ах опущена ветка else. Она необходима в любом случае, поэтому если туда написать сколько-нибудь осмысленную обрабоку, то станет очевидным рефакторинг:
return obj.Production.Price;


с выносом логики расчета цены в соотвествующие классы. В этом случае мы используем
M>полиморфность на полную катушку — наделяя разных наследников разным поведением.

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Проблема проектирования
От: SP_ Украина  
Дата: 12.07.07 15:16
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Вариант с иерархией имеет смысл городить только тогда, когда меняется что-то большее, чем одно поле в зависимости от одного флага

M>И вот именно этот момент и важно доносить до людей — что ООП, это нечто большее, чем замена всех условных выражений наследованием.
А меняется больше чем одно поле — кроме цены есть еще и закупщик. Да и описание в стартовом топике представляется мне максимально упрощенным с целью акцентировать проблему, а не детали бизнес-логики. Поэтому я запостил расширяемое решение.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Проблема проектирования
От: mrozov  
Дата: 13.07.07 08:10
Оценка:
Здравствуйте, IB, Вы писали:

IB>Здравствуйте, mrozov, Вы писали:


M>> Но, если я правильно понимаю, то вопрос в том — как это реализовать красиво с точки зрения ООП?

IB>Ну давай, посмотрим, что в твоей версии не красиво, сточки зрения ООП...

M>>Т.е. — для каких участков программы важно наличие или отсутствие поля Price? Для сохранения и загрузки?

IB>Про сохранение и загрузку у автора топика ничего не было, однако что ты, что Кирилл вцепились в это сохранеие, ну да ладно..
Это называется "пример". Ты это слово не заметил или не понял?

M>>Значит в некоем базовом классе Producer должны быть абстрактные методы Save и Load.

IB>Наличие в базовом классе методов Save и Load — означает, что конкретная реализация класса должна знать о конкретном хранилище, куда придется сохранять цену.
Нет, не означает.

IB>То есть, возникает совершенно ненужная связь, между классом продукта и хранилищем. Не нужная, потому что хранилище может быть самым разным для одного и того же объекта, в зависимости от ситуации — БД, XML, обычный файл и вообще все что угодно.

Нет, не значит.
IB>А вдруг нам этот объект на удаленного клиента передать надо, будем и на клиенте такое же хранилище поддерживать и все эти потроха с собой таскать?
Есть понятие "сериализация". А еще есть паттерн "стратегия".

IB>Теоретически, этой зависимости можно избежать, но зачем придумывать обходные маневры в виде красивых паттернов, когда можно просто не загонять себя в такую ситуацию, где эти маневры нужны?

IB>Отсюда вывод, методов Save и Load ни в базовом классе, ни в классах конкертных продуктов быть не должно,
Неправильный вывод. Когда как, зависит от многих прочих равных.

IB>в обычной коллекции методы Add и Remove разьве в объекте находятся, который сам себя в коллекцию помещает?

Иногда (если при добавлении объекта в коллекцию нужно выполнть доплнительные шаги) в объекте появляются специальные методы, парные им.

M>>А в двух наследниках SelfProducer и OtherProducer эти методы должны быть реализованы с учетом наличия или отсутствия этого поля.

IB>Полиморфизма можно добиться не только через наследование.
Я именно об этом и написал, ты не заметил или не понял?

M>>Нужно по-разному отображать данные в отчете? Значит в классе Producer нужен абстрактный метод GetReportData. И т.п.

IB>То есть, мы еще в класс продукта и особенности его отображения запихнем? Тоже отличная идея. Что будем делать, если надо поразному данные о продуктах предоставлять, скажем, в виде таблицы и графика? А если разным пользователям, по разному его показывать надо, еще и поддержку прав там же реализуем?
То мы введем стратегию отображения в том или ином виде. И привяжем ее к этому конкретному потомку. Так или иначе.

M>>При любом другом подходе тебе так или иначе придется писать

IB>Не придется.
Придется. Без вариантов.
Re[6]: Проблема проектирования
От: mrozov  
Дата: 13.07.07 08:12
Оценка:
Здравствуйте, SP_, Вы писали:

SP_>Здравствуйте, mrozov, Вы писали:


M>>Вариант с иерархией имеет смысл городить только тогда, когда меняется что-то большее, чем одно поле в зависимости от одного флага

M>>И вот именно этот момент и важно доносить до людей — что ООП, это нечто большее, чем замена всех условных выражений наследованием.
SP_>А меняется больше чем одно поле — кроме цены есть еще и закупщик. Да и описание в стартовом топике представляется мне максимально упрощенным с целью акцентировать проблему, а не детали бизнес-логики. Поэтому я запостил расширяемое решение.

Ты не запостил никакого решения. Ты всего-навсего описал названия классов в иерархии. Разницу чувствуешь?
Re[7]: Проблема проектирования
От: SP_ Украина  
Дата: 13.07.07 09:00
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Ты не запостил никакого решения. Ты всего-навсего описал названия классов в иерархии. Разницу чувствуешь?


А что есть какие то проблемы с реализацией этих классов? судя по оценкам моего поста с "названиями классов" топикстартеру все ясно
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Проблема проектирования
От: IB Австрия http://rsdn.ru
Дата: 13.07.07 10:47
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Это называется "пример". Ты это слово не заметил или не понял?

Где там это слово? =)

M>Нет, не означает.

А какой ценой это "не означает"? Можешь привести решение, которое позволит при наличии в самом "Продукте" методов Save и Load избавить "Продукт" от знаний о конкретном хранилище? Учти так же, что Load, как правило, производится не конкретного объекта, а коллекции объектов по самым разным предикатам.

IB>>То есть, возникает совершенно ненужная связь, между классом продукта и хранилищем. Не нужная, потому что хранилище может быть самым разным для одного и того же объекта, в зависимости от ситуации — БД, XML, обычный файл и вообще все что угодно.

M>Нет, не значит.
Хоть сам-то понял на что ответил? =) Ты утверждаешь, что у автора топика гарантировано будет одно хранилище с фиксированной структурой, которое не поменяется в течении жизни приложения... Смело.

M>Есть понятие "сериализация".

Понятие "сериализация" позволит тебе передать объект на клиента. Но твой объект оказался связан с внешним миром (хранилищем), поэтому для адекватной работы этого объекта на клиенте необходимо воссоздать окружение, с которым объект работает. Это одно из проявлений проблем с излишней связностью. Более того, даже если забыть про распределенные системы, нам банально надо передавать этот объект между слоями приложения и, например, в UI методам Load и Save делать абсолютно нечего. Как будем ограничивать? Будем надеяться на аккуратность разработчика или придумывать DTO для передачи данных между слоями?

M>А еще есть паттерн "стратегия".

Есть много замечательных паттернов, но с двух попыток боюсь, ты не угадал.. Наверное самый логичный выход из такой ситуации, воспользоваться паттерном DTO, но зачем бороться с проблемами с помощю паттернов, когда можно их просто не создавать? То есть, убрать из объекта зависимость от хранилища, выкинув оттуда методы Save и Load и поместив их в соответствующий сервис?

M>Неправильный вывод. Когда как, зависит от многих прочих равных.

Правильный, при прочих равных.

M>Иногда (если при добавлении объекта в коллекцию нужно выполнть доплнительные шаги) в объекте появляются специальные методы, парные им.

И часто такое бывает? Можешь придумать пример, чтобы возникла такая необходимость в данной задаче?

M>Я именно об этом и написал, ты не заметил или не понял?

Нет, ты писал как раз про полиморфизм через наследование, либо не смог свою мысль правильно донести...

M>То мы введем стратегию отображения в том или ином виде.

Стратегия, как я посмотрю, твой любимый паттерн.. ) Так кто у нас будет формировать данные для отображения, стратегия или сам класс? И где у нас таки должен находиться метод формирования ReportData?

M>И привяжем ее к этому конкретному потомку. Так или иначе.

Так "так" или "иначе", и в каком виде?

M>Придется. Без вариантов.

=) То что ты вариантов не знаешь, не значит что их нет..
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[6]: Проблема проектирования
От: IB Австрия http://rsdn.ru
Дата: 13.07.07 13:14
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Я тебе приведу два:

опять с двух попыток не угадал..

M> — сериализация — сохранение в Stream

Это означает, что Save и Load знают о конкретном Stream aka Хранилище...

M> — метод save/load является фабрикой для объектов, которые как раз и совмещают знание внутренности данного с конкретным хранилищем.

Угу, то есть, поскольку Save и Load сидят в объекте, то они знают о конкретном хранилище, мло того, здесь еще и нарушается принцип SRP — методы сохранения являются еще и фабриками.

M>Фаулера почитай, в конце концов.

То, что ты паттерны знаешь — это понятно, осталось научиться их применять...

M>Я ничего такого не утверждаю,

Ну перечитай, как еще можно истолковать твое утверждение?

M> это ты у нас мастер неудачного чтения чужих мыслей.

Я и не претендую, если не получается правильно их излагать — приходится догадываться...

M>Два балла. Понятие "сериализация" позволяет мне сохранить данные в поток и восстановить из него.

То есть, не поможет передать на клиента?

M>Это идеальный патерн для всех ситуаций, когда внутренее содержимое данных не имеет значения для кода извне.

И причем тут это? Тебе еще раз задачу повторить? Может быть непонятно? Надо организовать передачу "продукта" на клинтское приложение, как ты будешь это делать?
И ты так и не ответил на вопрос, как будет происходить передача объекта между слоями.

M>Бояться не надо, надо знать.

Знаю, не угадал.

M>Фабричный метод + стратегия.

Где у тебя находится фабричный метод? Стратегия чего?

M>Потому что для этого с внутренним содержимым должен уметь работать этот сервис.

Какое у данного объекта внутренне содержимое?

M>Что возможно и даже оптимально (отражение + кодогенерация), но к ООП уже никакого отношения не имеет.

Никакой кодогенерации и рефлекшена, сплошной ООП.

M>Глупый, если уж говорить точнее.

Не хами. Когда аргументы заканчиваются, можно просто промолчать.

M>А при чем тут часто или нечасто?

То есть не можешь придумать пример, чтобы возникла такая необходимость в данной задаче?
Зачем тогда вкрячивать Save и Load в класс, ради какой цели?

M>Я в конце написал, что для простых случаев проще всего вопользоваться условным выражением.

Условное выражение — это не полиморфизм.

M>По обстоятельствам. Если поддержка разных вариантов сохранения не нужна (а она как правило не нужна), то в классе.

А при сохранении будем разбираться, вот это хранить, а вто это в сад? Удачное решение.

M> Несколько реже — в классе, разумеется.

Разумеется нет, никогда в классе.

M>По обстоятельствам.

Ну хоть один прием?

M>Правильных ООП-вариантов нет.

Ты же знаешь паттерны — неужели ни один в голову не приходит?
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[8]: Проблема проектирования
От: IB Австрия http://rsdn.ru
Дата: 14.07.07 23:05
Оценка:
Здравствуйте, mrozov, Вы писали:

M>Любопытно, нахрена ты сразу начал хамить, чем я тебя обидел?

Я ?! Ты ничего не напутал? Перечитай что ли...

M>Мне неинтересно с тобой спорить в таком духе, понимаешь?

То есть, аргументов по делу нет? Я вообщем-то с самого начала это подозревал.

M>Я привел два классических примера из учебников по ООД.

А своих мозгов нету? Если это примеры из учебников, то выкинини эти учебники (ну или перечитай их правильно), так как я тебе привел классические косяки такого подхода. Ты случайно не книжки по антипаттернам читал, не разобравшись?

M> Сохранение/загрузка и отображение в отчете. Фаулер и .. уже не помню, Кериевски, что ли?

Ты прежде чем примеры приводить, разобрался бы к чему они... Фаулера поначалу не читай, его потом надо, начни с Меерса, Макконела и Саттера.

M>Ты эти примеры даже не узнал

Ну почему, характерные антипаттерны сложно не опознать.

M>То, о чем я говорю, применяется в индустрии уже десятилетиями.

Ты что-то путашеь. От этого десятилетиями предостерегают.

M>Та же сериализация, позволяющая сохранять данные

"Сериализация" ничего не хранит, это процесс упорядочивания и не более того. Как ты это упорядочивание собираешься использовать?
Такое впечатление, что ты начитался красивых слов про умные паттерны, но не очень представляешь где их применять...

M> в любом контейнере, поддерживающим интерфейс Stream.

Можешь огласить публичный контракт "интерфейса Stream"? Может быть он у Фаулера описан или еще у кого, главу не подскажешь?

M> Методы типа Dump и прочее, прочее, прочее..

Какой Dump, что прочее? Свои мысли есть или все на дядьку Мартина ссылаться будешь? Я тебе назадавал кучу вопросов, можешь на них внятно ответить? Там ничего сложного нет.
Мы уже победили, просто это еще не так заметно...
Re[8]: Проблема проектирования
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.07.07 12:54
Оценка:
Здравствуйте, mrozov, Вы писали:

Продемонстрировал массу понтов и мало знаний, а на заданные вопросы так по делу ничего ответить и не смог.
... << RSDN@Home 1.2.0 alpha rev. 688>>
AVK Blog
Re[9]: Проблема проектирования
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 20.07.07 12:54
Оценка:
Здравствуйте, IB, Вы писали:

M>> Сохранение/загрузка и отображение в отчете. Фаулер и .. уже не помню, Кериевски, что ли?

IB>Ты прежде чем примеры приводить, разобрался бы к чему они... Фаулера поначалу не читай, его потом надо, начни с Меерса, Макконела и Саттера.

Меерса обязательно! Он много про такие косяки пишет.
... << RSDN@Home 1.2.0 alpha rev. 688>>
AVK Blog
Re[7]: Проблема проектирования
От: BulatZiganshin  
Дата: 20.07.07 14:29
Оценка:
M>> — сериализация — сохранение в Stream
IB>Это означает, что Save и Load знают о конкретном Stream aka Хранилище...

не угадал. Stream — это интерфейс к хранилищам данных, предоставляющий для сериализаторов операции побайтового чтения/записи
Люди, я люблю вас! Будьте бдительны!!!
Re[8]: Проблема проектирования
От: IB Австрия http://rsdn.ru
Дата: 20.07.07 14:58
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>не угадал.

А я и не угадывал.

BZ>Stream — это интерфейс к хранилищам данных,

К весьма конкретным хранилищам данных, весьма конкретный интерфейс. Об чем собственно и речь.
Ограничивать себя в данной задаче стримом — это форменный мазохизм какой-то. Правильный ответ на данный вопрос — IoC, но и это не поможет убежать от всех тщательно разложенных граблей...

BZ>предоставляющий для сериализаторов операции побайтового чтения/записи

Файн, а если мне нужно не побайтовое? А на самом деле такое и нужно, я не зря про запросы с предикатами писал.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[2]: Проблема проектирования
От: dr.Chaos Россия Украшения HandMade
Дата: 20.07.07 16:06
Оценка:
Здравствуйте, SP_, Вы писали:

SP_>Здравствуйте, Kostyan2204, Вы писали:

K>>Как это реализовать?
SP_>Один из вариантов

А какие премущества/недостатки у такого решения:

class IProduction
{

};

class IDesign
{
...
}


class Izdelie : public IDesign, public IProduction 
{
}


или такого:

template<typename Poduction, typename Design>
class Izdelie : public Production, public Design
{
...
}


Ну оба варианта позволяют проще обращаться к нужным функциям.

1й вариант, позволяет всю реализацию совместить в одном месте, если иерархия неглубокая. Это удобнее чем рыться в разных файлах. На C# вроде так можно сделать.

2й вариант, обладает гибкостью изначального. Можно наделать кусков реализации а конкретный класс будет просто их комбинацией.

Из недостатков — наследование более сильная связь, но ИМХО так будет элегантнее.
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[9]: Проблема проектирования
От: BulatZiganshin  
Дата: 21.07.07 07:23
Оценка:
BZ>>Stream — это интерфейс к хранилищам данных,
IB>К весьма конкретным хранилищам данных, весьма конкретный интерфейс. Об чем собственно и речь.
IB>Ограничивать себя в данной задаче стримом — это форменный мазохизм какой-то. Правильный ответ на данный вопрос — IoC, но и это не поможет убежать от всех тщательно разложенных граблей...

BZ>>предоставляющий для сериализаторов операции побайтового чтения/записи

IB>Файн, а если мне нужно не побайтовое?

а если нужен интерфейс Show? или Sort? какое-то толчение воды в ступе
Люди, я люблю вас! Будьте бдительны!!!
Re[10]: Проблема проектирования
От: IB Австрия http://rsdn.ru
Дата: 21.07.07 11:35
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>а если нужен интерфейс Show? или Sort?

Во-первых, какое отношение имеет Show к хранилищу? А во-вторых, я довольно четко описал характерные требования к типичному механизму хранения, что-то непонятно? Так я могу растолковать...

BZ> какое-то толчение воды в ступе

Я задал совершенно конкретные вопросы, даже ответ подсказал, что не устраивает?
Мы уже победили, просто это еще не так заметно...
Re: Проблема проектирования
От: Аноним  
Дата: 25.07.07 08:46
Оценка:
Здравствуйте, Kostyan2204, Вы писали:

K>Приветствую!


K>Помогите разобраться с проблемой проектирования.


K>Есть суперкласс Izdelie. (базовый для всех изделий). У всех изделий есть следующие атрибуты:

K>1) long ID; //Уникальный код изделия
K>2) string FullName; //Полное наименование материала
K>3) decimal Mass; //Масса изделия
K>4) Purchased; // Признак того, что изделие покупное

K>Изделия могут менять признак с ПОКУПНОЕ на СОБСТВЕННОЕ ИЗГОТОВЛЕНИЕ (и наоборот)


K>Если издлеия являются покупными, то у них имеются атрибуты ( Buyer — закупщик, Price — цена). Наоборот, изделия собственного производства, таких атрибутов у него нет.


K>С ДРУГОЙ СТОРОНЫ

K>Все изделия деляться на две группы (СОБСТВЕННОГО ПРОЕКТИРОВАНИЯ и ЧУЖОГО ПРОЕКТИРОВАНИЯ).
K>Изделия собственного проектирования (в отличии от чужих) имеют атрибут НОМЕР ЧЕРТЕЖА и ФАМИЛИЯ РАЗРАБОТЧИКА.

K>Как это реализовать?


создайте класс который умеет регистрить другой класс.
типа

static void register(name_class)
static void unregister(name_class)
static find(name_class)

это позволит сохранять любое количество классов в одном базовом классе, тоесть есть супер класс и к нему прикручиваются дополнительные классы содержащие эти дополнительные и уникальные поля!
Re: Проблема проектирования
От: Хнык Россия  
Дата: 26.07.07 14:49
Оценка:
Здравствуйте, Kostyan2204, Вы писали:

K>Приветствую!


K>Помогите разобраться с проблемой проектирования.


K>Есть суперкласс Izdelie. (базовый для всех изделий). У всех изделий есть следующие атрибуты:

K>1) long ID; //Уникальный код изделия
K>2) string FullName; //Полное наименование материала
K>3) decimal Mass; //Масса изделия
K>4) Purchased; // Признак того, что изделие покупное

K>Изделия могут менять признак с ПОКУПНОЕ на СОБСТВЕННОЕ ИЗГОТОВЛЕНИЕ (и наоборот)


K>Если издлеия являются покупными, то у них имеются атрибуты ( Buyer — закупщик, Price — цена). Наоборот, изделия собственного производства, таких атрибутов у него нет.


K>С ДРУГОЙ СТОРОНЫ

K>Все изделия деляться на две группы (СОБСТВЕННОГО ПРОЕКТИРОВАНИЯ и ЧУЖОГО ПРОЕКТИРОВАНИЯ).
K>Изделия собственного проектирования (в отличии от чужих) имеют атрибут НОМЕР ЧЕРТЕЖА и ФАМИЛИЯ РАЗРАБОТЧИКА.

K>Как это реализовать?



    public class AbstractIzdelie
    {
        long _id;
        string _fullName;
        decimal _mass;
        InternalArhitect _internalArhitect;
        AlienDevelop _alienDeveloper;
        public long ID
        {
            get { return _id; }
        }
        public string FullName
        {
            get { return _fullName; }
        }
        public decimal Mass
        {
            get
            {
                return _mass;
            }
        }
        public decimal Price 
        {
            get { return _alienDeveloper.Price; }
        }
        public string Number
        { 
            get { return _internalArhitect.Number; }
        }
        public string Fio 
        {
            get { return _internalArhitect.Fio; }
        }
        public string Byer
        {
            get { return _alienDeveloper.Buyer; }
        }
    }
    struct InternalArhitect
    {
        public string Number;
        public string Fio;
    }
    struct AlienDevelop
    {
        public decimal Price;
        public string Buyer;
    }
Мну думает. Значит. Ага.
Re[2]: Проблема проектирования
От: Хнык Россия  
Дата: 26.07.07 14:55
Оценка:
Ещё добавить SetAsInternal — обнуляем структуру и SetAsAlien(AlienDevelop alienDeveloper)
Мну думает. Значит. Ага.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.