Цифровой товар, выделить суперклассы
От: Foror http://foror.ru
Дата: 09.04.06 05:31
Оценка:
Делаю магазин по продаже цифровых товаров, на java, столкнулся с проблемой
выделения сущностей.

поля, которые должен иметь каждый товар:

abstract Ware {
name
rating
amountPurchases
createDate
price
}

дальше товар, которым предстоит торговать, с дополнительными полями:

Фильм img, about, [size, file] 1
Книга img, about, [size, file] 1
Программа img, about, [size, file] 1
Альбом img, about 2
Активационный номер img, about 2
Композиция(mp3) [size, file] 3

Делать три сущности, как-то не хочется, да и название не могу им придумать. Может есть какое-то более
интересное решение?
Re: Цифровой товар, выделить суперклассы
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 09.04.06 10:10
Оценка: +1
Здравствуйте, Foror, Вы писали:

F>Делать три сущности, как-то не хочется, да и название не могу им придумать. Может есть какое-то более

F>интересное решение?

Если дополнительных полей не так уж много, сделайте один класс Товар и включите в него все поля, которые нужны. Для отдельных товаров, где данные поля не нужны, их можно держать пустыми или инициализировать специальными значениями.

Если же Вы будете выносить общие для всех товаров поля в суперклассы, то неминуемо совершите ошибку, которую допустил Гради Буч. Об этом смотрите в статье: http://www.triz-ri.ru/themes/method/creative/creative57.asp
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re: Цифровой товар, выделить суперклассы
От: LeonidV Ниоткуда http://vygovskiy.com
Дата: 09.04.06 11:31
Оценка:
А чем плохи четыре класса? Я бы так и сделал. Особенно, если потом придется доблять новые товары.
И нечего себе сложностей искать, на мой взгляд.
http://jvmmemory.com — простой способ настройки JVM
Re[2]: Цифровой товар, выделить суперклассы
От: LeonidV Ниоткуда http://vygovskiy.com
Дата: 09.04.06 11:37
Оценка:
Не знаю как на этом форуме соообщения править. Поэтому так дополню (не внимательно глянул первое сообщение).
1 сущность — абстрактный класс товара, который описывает стандартные его свойства. А последующие описывают товары (один класс — один тип товара). Делать как написал предыдующий оратор, я бы точно не стал. Потом эти if() включать...
Преимущества:

http://jvmmemory.com — простой способ настройки JVM
Re: Цифровой товар, выделить суперклассы
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 09.04.06 12:04
Оценка: +1
Здравствуйте, Foror, Вы писали:

F>Делаю магазин по продаже цифровых товаров, на java, столкнулся с проблемой

F>выделения сущностей.

F>поля, которые должен иметь каждый товар:


F>abstract Ware {

F>name
F>rating
F>amountPurchases
F>createDate
F>price
F>}

F>Делать три сущности, как-то не хочется, да и название не могу им придумать. Может есть какое-то более

F>интересное решение?


Вот у меня вопрос. Пользователь магазина сам сможет добавлять новые виды товаров, или каждый раз должен будет напрягать тебя для этого?
По мне, так товар — клас не абстрактный, а конкретный. Только помимо всего прочего должен содержать в себе ссылку на описание его типа. Описание типа — это имя с описанием набора допустимых аттрибутов. А конкретный экземпляр товара — это один инстанс класса Ware и набор значений аттрибутов, соотвествующих его типу.
Re[3]: Цифровой товар, выделить суперклассы
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 09.04.06 12:10
Оценка: -1
Здравствуйте, LeonidV, Вы писали:

LV>1 сущность — абстрактный класс товара, который описывает стандартные его свойства. А последующие описывают товары (один класс — один тип товара). Делать как написал предыдующий оратор, я бы точно не стал. Потом эти if() включать...


Вы, видимо, не прочитали статью. Иначе бы поняли, что if'ы замучают, если сделать так, как написали Вы.
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re[4]: Цифровой товар, выделить суперклассы
От: LeonidV Ниоткуда http://vygovskiy.com
Дата: 09.04.06 20:05
Оценка:
Здравствуйте, Кирилл Лебедев, Вы писали:

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


Статью прочитал (кстати, спасибо за ссылочку), про if'ы не понял. Три раза пытался ответ написать, а потом понял — говорить так, не зная полной архитетуры, очень сложно. Я вообще делаю очень похоже на то, как Lucker написал. У меня задача такая — сделать магазин с незабитым ассортиментом.
http://jvmmemory.com — простой способ настройки JVM
Re[2]: Цифровой товар, выделить суперклассы
От: GlebZ Россия  
Дата: 09.04.06 23:08
Оценка: 1 (1) -1
Здравствуйте, Lucker, Вы писали:

L>Вот у меня вопрос. Пользователь магазина сам сможет добавлять новые виды товаров, или каждый раз должен будет напрягать тебя для этого?

L>По мне, так товар — клас не абстрактный, а конкретный. Только помимо всего прочего должен содержать в себе ссылку на описание его типа. Описание типа — это имя с описанием набора допустимых аттрибутов. А конкретный экземпляр товара — это один инстанс класса Ware и набор значений аттрибутов, соотвествующих его типу.
Тут все зависит не от статики, а от поведения класса предка, и окружения.
Если класс товар является:
1. Неотъемлемым свойством остальных товаров
2. Его поведение независит от того, от кого его наследует
то вполне можно и реально создавать именно абстрактного предка. Это может положительно сыграть на простоте реализации. Если есть надежда что хоть для одного товара данные правила не будут выполнятся, то лучше композиция. Типы можно и в runtime генерить.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[5]: Цифровой товар, выделить суперклассы
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 10.04.06 19:14
Оценка: 1 (1) -2
Здравствуйте, LeonidV, Вы писали:

LV>Статью прочитал (кстати, спасибо за ссылочку), про if'ы не понял. Три раза пытался ответ написать, а потом понял — говорить так, не зная полной архитетуры, очень сложно.


Постараюсь пояснить. Ответ будет содержать несколько пунктов:

1. Обычно данные группируют в класс для того, чтобы упростить работу с ними. Проще работать с классом целиком, чем с каждым полем класса, будь оно представлено в виде самостоятельной переменной.

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

2. Из п. 1 следует, что группировка делается ради пользователя класса. Иными словами, создание класса оправдано в том и только том случае, если это упрощает пользовательский код. Если мы создали группу (например, класс), из-за которой вызывающий код усложнился, то, вероятнее всего, произведенная группировка ошибочна. И от нее надо отказаться. Или следует ее переделать.

3. Заменяя один класс на иерархию, мы тем самым разбиваем группу на куски. Был один класс (Товар), а стало несколько: Базовый_Товар, Товар_с_Картинкой, Товар_с_Мелодией, Товар_с_Видео_Клипом и т.д.

Разбивая группу на части, мы устраняем преимущество, созданное группировкой. Посудите сами, если раньше мы могли работать с Товаром, как с единым целым, то теперь нам нужно различать, с каким товаром мы имеем дело. Фактически, замена класса на иерархию обуславливает появление оператора if в пользовательском коде:
if (typeid(*pObj) == typeid(Базовый_Товар))
{
   // делаем одно
}
else if (typeid(*pObj) == typeid(Товар_с_Картинкой))
{
   // делаем другое
}
else if (typeid(*pObj) == typeid(Товар_с_Мелодией))
{
   // делаем третье
}
else if (typeid(*pObj) == typeid(Товар_с_Видео_Клипом))
{
   // делаем четвертое
}

Такое ветвление придется написать, например, в коде отображения товара на витрине.

4. В некоторых – весьма простых! – случаях ветвление можно заменить полиморфизмом. Для этого код, следующий за оператором if, нужно поместить в виртуальную функцию соответствующего класса:
class Товар
{
public:

   virtual void DrawOnPage(HtmPage & rPage);
};

class Товар_с_Картинкой : public Товар
{
public:

   virtual void DrawOnPage(HtmPage & rPage);
};

class Товар_с_Мелодией : public Товар
{
public:

   virtual void DrawOnPage(HtmPage & rPage);
};

class Товар_с_Видео_Клипом : public Товар
{
public:

   virtual void DrawOnPage(HtmPage & rPage);
};

Такое решение действительно устраняет if, но оно неработоспособно, если требуется создать несколько вариантов оформления html-страницы. При добавлении нового варианта (стиля оформления сайта) нужно будет добавлять новую функцию DrawOnPage во все классы иерархии. Причина этой проблемы в том, что мы привязали бизнес-логику (класс Товар) к представлению (класс HtmlPage). А сделали мы это только ради того, чтобы устранить if.

Оператор if появился только после преобразования класса Товар в иерархию. Соответственно, рассуждая логически, можно найти первопричину проблем – разбиение класса Товар на группу классов и выделение суперкласса. (Ситуация, аналогичная задаче с датчиками из статьи.)

5. Отсюда вывод: Лучше добавить лишних полей, но сохранить один класс, чем преобразовать класс в иерархию классов, выделяя в суперкласс общие поля.

Иными словами на группу (класс) лучше смотреть с точки зрения кода, который будет ее использовать, чем с точки зрения отдельных элементов этой группы.
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re: Цифровой товар, выделить суперклассы
От: UnIc0dE  
Дата: 11.04.06 02:37
Оценка:
Здравствуйте, Foror, Вы писали:

F>Делаю магазин по продаже цифровых товаров, на java, столкнулся с проблемой

F>выделения сущностей.

F>поля, которые должен иметь каждый товар:


F>abstract Ware {

F>name
F>rating
F>amountPurchases
F>createDate
F>price
F>}

F>дальше товар, которым предстоит торговать, с дополнительными полями:


F>Фильм img, about, [size, file] 1

F>Книга img, about, [size, file] 1
F>Программа img, about, [size, file] 1
F>Альбом img, about 2
F>Активационный номер img, about 2
F>Композиция(mp3) [size, file] 3

F>Делать три сущности, как-то не хочется, да и название не могу им придумать. Может есть какое-то более

F>интересное решение?

Я бы сделал так:
База данных:
tableWare                tableProperties
ID........................ware_ID   
name                      prop_name 
rating                    prop_value 
amountPurchases
createDate
price

В tableProperties хранишь все пары (имя — значение) дополнительных свойств.

Код:
Создаешь один единственный суперкласс Ware и все дополнительные свойства из tableProperties загоняешь в ArrayList. Ну а дальше дело техники, как тебе эти значения получать. Пишешь, например метод возвращающий список всех доступных дополнительных свойств. Другой метод, который тебе по имени свойства возвращает его значение.

И все. добавляй себе сколько угодно нового товара с новыми дополнительными свойствами, все будет работать.
Если добро всегда побеждает зло, значит кто победил — тот и добрый.
Re: Цифровой товар, выделить суперклассы
От: Coldi  
Дата: 11.04.06 09:47
Оценка:
Классы: Продукт, Катерория, Свойство товара, Значение свойства товара

У категории — коллекция свойств товара

У товара — коллекция значений свойств

У свойства товара — ссылка на категорию

У значения свойства — ссылка на свойство товара

Или вы хотите чтобы клиент сам дописывал нужные классы если он решил внести в ассортимент новый тип товаров? Это прекрасный способ привязать к себе клиента, но до поры до времени.
Re[6]: Цифровой товар, выделить суперклассы
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 12.04.06 09:28
Оценка: +3
Здравствуйте, Кирилл Лебедев, Вы писали:

КЛ>5. Отсюда вывод: Лучше добавить лишних полей, но сохранить один класс, чем преобразовать класс в иерархию классов, выделяя в суперкласс общие поля.

и получить швейцарский армейский нож?
Re[6]: Цифровой товар, выделить суперклассы
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 12.04.06 22:35
Оценка: -1
Здравствуйте, Кирилл Лебедев, Вы писали:

КЛ>3. Заменяя один класс на иерархию, мы тем самым разбиваем группу на куски. Был один класс (Товар), а стало несколько: Базовый_Товар, Товар_с_Картинкой, Товар_с_Мелодией, Товар_с_Видео_Клипом и т.д.


Неверно. Мы оставляем исходную группу неизменной. Наследники только образуют новые группы.

КЛ>Разбивая группу на части, мы устраняем преимущество, созданное группировкой. Посудите сами, если раньше мы могли работать с Товаром, как с единым целым, то теперь нам нужно различать, с каким товаром мы имеем дело. Фактически, замена класса на иерархию обуславливает появление оператора if в пользовательском коде:

[...]
КЛ>Такое ветвление придется написать, например, в коде отображения товара на витрине.

Посылка правильная, выводы неверные. if-ы появятся только при глупости или лени проектировщика.

КЛ>4. В некоторых – весьма простых! – случаях ветвление можно заменить полиморфизмом. Для этого код, следующий за оператором if, нужно поместить в виртуальную функцию соответствующего класса:

[...]
КЛ>Такое решение действительно устраняет if, но оно неработоспособно, если требуется создать несколько вариантов оформления html-страницы. При добавлении нового варианта (стиля оформления сайта) нужно будет добавлять новую функцию DrawOnPage во все классы иерархии. Причина этой проблемы в том, что мы привязали бизнес-логику (класс Товар) к представлению (класс HtmlPage). А сделали мы это только ради того, чтобы устранить if.

Правильно сделали. И дальше нужно идти по тому же пути — углублять структуризацию, а не шарахаться от неё путём внесения аналитических if на верхний уровень.

КЛ>Оператор if появился только после преобразования класса Товар в иерархию. Соответственно, рассуждая логически, можно найти первопричину проблем – разбиение класса Товар на группу классов и выделение суперкласса. (Ситуация, аналогичная задаче с датчиками из статьи.)


Неправда ваша. Операторы if(тип) появляются при низкой квалификации проектировщика. Проверено неоднократно.

КЛ>5. Отсюда вывод: Лучше добавить лишних полей, но сохранить один класс, чем преобразовать класс в иерархию классов, выделяя в суперкласс общие поля.


Не согласен. Как минимум, остаётся ещё возможность агрегации, да и с наследованием не всё так фатально, как кажется на первый взгляд. Есть, как минимум ещё один выход: сделать фабрику для рисовальщиков. Фабрика будет генерировать классы в зависимости от контекста (т.е., например — способа оформления).

public interface IDrawer
{
  public void draw(HtmlPage page)
  { /*...*/ }
}

public class Ware implements IWare
{
  public IDrawer create_drawer(int drawing_mode)
  {
    // WareDrawer - фабрика, создающая рисовальщиков для класса Ware
    // в зависимости от значния параметра.
    return SomeWareDrawerFactory.create_new_drawer(this, drawing_mode);
  }
}

// Пример реализации WareDrawerFactory
public class SomeWareDrawerFactory
{
  // Внимание: обратите внимание на тип параметра to_draw!
  public static IDrawer create_new_drawer(Ware to_draw, int drawing_mode)
  {
    if (drawing_mode == 1) return new DrawerForMode1(to_draw);
    if (drawing_mode == 2) return new DrawerForMode2(to_draw);
    return null;
  }
}


Наследники Ware перекрывают create_drawer обращением к "своим" фабрикам. Результирующий "рисовальщик" есть производное от выбора по типу товара и способу отображения.

Да, естественно, в этом случае получится n*m типов рисовальщтков, где n — количество типов товара, а m — количество "типов оформления". Но по сути тоже самое мы получаем и в любом случае, коль начинаем беседу о "типах" товара и отображения.

КЛ>Иными словами на группу (класс) лучше смотреть с точки зрения кода, который будет ее использовать, чем с точки зрения отдельных элементов этой группы.

+1

И использование получится очень простым и полиморфным:

public void DrawOnPage(IWare ware, HtmlPage page, int draw_mode)
{
  IDrawer drawer = ware.create_drawer(draw_mode);
  drawer.draw(page);
}


Можно ещё поиграться с замыканиями ware и drawer, подумать о предварительном создании набора рисовальщиков, возможно, о введении зависимости от типа страницы и т.д. и т.п.

Кстати, только в фабриках анализ типа объекта может быть уместен, да и то лишь в том случае, если требуется привязать тип создаваемого объекта к типу объекта-аргумента.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[7]: Очапатка
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 12.04.06 22:39
Оценка:
Разумеется, не:
public interface IDrawer
{
  public void draw(HtmlPage page)
  { /*...*/ }
}

а просто:
public interface IDrawer
{
  public void draw(HtmlPage page);
}
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[7]: Цифровой товар, выделить суперклассы
От: UnIc0dE  
Дата: 13.04.06 00:51
Оценка: 6 (1)
Если вы посмотрите на исходный текст, то там последняя фраза следующая:

Делать три сущности, как-то не хочется, да и название не могу им придумать. Может есть какое-то более
интересное решение?


Так что как поизвращаться с наследниками у автора проблемы не возникает. Наоборот, он старается от этого избавиться. И правильно делает. Из условия задачи выходит что 3 наследника причиняют больше неудобств чем выгоды.
По моему глубокому IMHO, создавать наследников следует только если от этого есть какая-то практическая польза, а не тупо передирать патерны из учебника, чтобы получилось красиво.
В данном конкретном случае можно обойтись одним единственным класом, только если автор не объяснит зачем ему нужны наследники. Пока это не ясно.
Если добро всегда побеждает зло, значит кто победил — тот и добрый.
Re: Цифровой товар, выделить суперклассы
От: Аноним  
Дата: 13.04.06 06:07
Оценка:
Здравствуйте, Foror, Вы писали:

...
F>Делать три сущности, как-то не хочется, да и название не могу им придумать. Может есть какое-то более
F>интересное решение?

Не то, что б совсем уж имхо...

Самое важное: любое, принятое тобой решение, должно предполагать единообразную обработку различных товаров (реализуют один интерфейс).
В остальном я бы предложил воспользоваться таким правилом: потомок должен создаваться, если у него будут уникальные поля и методы. Например, у фильма: trailer и ShowTrailer(). Если нет — в товар добавь тип товара.
Еще один нюанс. Подумай в каком направлении будет происходить развитие. Возможно, лучше сразу заложить в арихитектуру будущие изменения.
Re[8]: Цифровой товар, выделить суперклассы
От: GlebZ Россия  
Дата: 13.04.06 08:27
Оценка:
Здравствуйте, UnIc0dE, Вы писали:

UIE>Так что как поизвращаться с наследниками у автора проблемы не возникает. Наоборот, он старается от этого избавиться. И правильно делает. Из условия задачи выходит что 3 наследника причиняют больше неудобств чем выгоды.

Из контекста вообще ничего не видно. Пользуясь только информацией о данных, можно только сделать выводы как это может лежать на БД. И то только в классической нормализованной модели. Обычно приходится держать в голове наиболее криминальные транзакции. Делать же выводы по дизайну ООП можно только основываясь на поведении(о чем совершенно не знает г-п Лебедев). Данные в данном случае — вторичны.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[8]: Цифровой товар, выделить суперклассы
От: Кирилл Лебедев Россия http://askofen.blogspot.com/
Дата: 13.04.06 09:19
Оценка:
Здравствуйте, UnIc0dE, Вы писали:

UIE>По моему глубокому IMHO, создавать наследников следует только если от этого есть какая-то практическая польза, а не тупо передирать патерны из учебника, чтобы получилось красиво.


Полностью согласен с Вашей точкой зрения. Не смотря на то, что данные не важны (и это правильно отметил Глеб Земсков), важно то, как они сгруппированы. Группировка же должна делаться, исходя из удобств использования, а не из того, как эти данные "лежат" в базе данных. Чего, к сожалению, не понимает (и не хочет понять!) Глеб Земсков. Иными словами, пользователь первичен, а база данных — вторична. Проблема оптимизации количества запросов к базе данных хотя и важна, но тоже вторична. И решается она совсем на другом системном уровне.
С уважением,
Кирилл Лебедев
Software Design blog — http://askofen.blogspot.ru/
Re[9]: Цифровой товар, выделить суперклассы
От: GlebZ Россия  
Дата: 13.04.06 09:33
Оценка:
Здравствуйте, Кирилл Лебедев, Вы писали:

КЛ>Группировка же должна делаться, исходя из удобств использования,

Ну вот, хоть что-то.
КЛ>а не из того, как эти данные "лежат" в базе данных. Чего, к сожалению, не понимает (и не хочет понять!) Глеб Земсков.
И где это ты слышал? О независимости модели данных и объектной модели слышал?
КЛ>Иными словами, пользователь первичен, а база данных — вторична.
Интересная постановка задачи. Никогда об этом не задумывался.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re: Цифровой товар, выделить суперклассы
От: Foror http://foror.ru
Дата: 13.04.06 11:39
Оценка:
Здравствуйте, Foror, Вы писали:

F>Делать три сущности, как-то не хочется, да и название не могу им придумать. Может есть какое-то более

F>интересное решение?

Я буду делать две сущности + одна абстрактная. Первая сущность может
иметь своё изображение, и товар, который наследует эту сущность, должен выводиться пользователю
с учетом этих данных. Вторая сущность имеет файл и изображение, а значит для товара данного
типа будет свой вывод. От третьей сущности(которая имеет только файл) отказался, т.к. только
одна Музыкальная композиция имеет случай с файлом без изображения. Этот частный случай наследует
напрямую от абстрактного товара.

А делать динамические поля пока не нужно, и вообще наврятли я думаю понадобятся от специфики
продаваемого товара.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.