ООП. Некоторые аспекты, неясные новичку. Ruby.

 
+
-
edit
 

HolyBoy

аксакал

Возникло желание и небольшая надобность сделать веб-морду для одной БД. Решил использовать RoR, т.к. хочется изучить что-то новое на относительно несложном проекте.

Сразу скажу, что ООП для меня — тёмный лес, не потому, что читать умные книжки не умею, а из-за того, что никак не пойму его сути и условий применения. Вот, к примеру, нынешний проект. Для простоты предположим, что мы собираем буратин и продаем их.

Надумал пару вариантов:

Первый.

У нас есть класс A, описывающий некие детали, положим, что свойствами этого класса будут название детали и её масса. В РоР создаваемые объекты класса могут заноситься в таблицу, т.о. получается, что создав объект класса А мы автоматом получаем таблицу деталей.

Есть класс B — это сами буратины. Если его сделать наследником класса A, то он будет иметь свойствами как название так и массу. Существует необходимость для объекта класса B указать перечень деталей, его составляющих, значит, третьим свойством этого класса будет массив объектов класса A. Причем, этот массив может быть и пустым, это просто означает, что буратино стандартный и его конструкцию можно посмотреть в справочнике.

И, наконец, есть класс C — накладная. Он вроде бы ничего не наследует, но свойствами его, помимо массива объектов класса B, должен быть массив такой же размерности, содержащий в себе количество буратин по каждой позиции. Прочие свойства типа даты и «чего-там-душа-пожелает» тривиальны.

Недостаток этого варианта вижу в том, что используется слишком много массивов, быстро будет расходоваться память, особенно на операциях вида «вывести на экран все накладные от даты №1 по дату №2», также будут тормозить вычисления количества проданных экземпляров и тд.

Второй

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

Создаем класс Б, такой же, как класс С в первом варианте. Здесь увеличивается количество дублирующей информации в базе, зато вроде шустрее должно работать.


Что из вышеперечисленного неверно и что можно сделать лучше?
 

Murkt

Pythoneer

Используется не массив как таковой, а связь "многие-ко-многим". Попробуй посмотреть в документации РоР - many to many (m2m), или ещё как-нибудь так. Я могу написать приблизительный код на Django, но РоР (да и вообще Руби) я не знаю.
[team Їжачки - сумні падлюки]  

HolyBoy

аксакал

Murkt> Используется не массив как таковой, а связь "многие-ко-многим". Попробуй посмотреть в документации РоР - many to many (m2m), или ещё как-нибудь так. Я могу написать приблизительный код на Django, но РоР (да и вообще Руби) я не знаю.


А, понял.
Т.е. можно для класса задать свойство соответствующее и оно заработает? Ок. Спасибо.
 
+
-
edit
 

Balancer

администратор
★★★★★
Оптимальное решение на мой взгляд такое.

1. Объект «деталь».

2. Объект «буратино», имеющий привязки к объектам «детали».

3. Объект «накладная» с нужными связями.

Наследования как такового нет.

Наследование, вообще, нужно в том и только том случае, когда дочерний объект является небольшим расширением или модификацией родительского, но принципиально в нём ничего не меняется.

Буратино - не является наследником его деталей :)

Но может быть, например, класс «Деревянная кукла», наследниками которой будут «Буратино» и «Пиноккио».

Если при наследовании какой-то компонент модели меняется сильно, то нужно думать, не нужно ли вынести его в отдельный класс или связь.
 
US Сергей-4030 #27.08.2008 00:02  @Balancer#26.08.2008 23:31
+
-
edit
 

Сергей-4030

исключающий третье
★★
Balancer> Оптимальное решение на мой взгляд такое.
Balancer> 1. Объект «деталь».
Balancer> 2. Объект «буратино», имеющий привязки к объектам «детали».
Balancer> 3. Объект «накладная» с нужными связями.

ИМХО, можно немного детализировать, . Типа, есть "склад" с деталями. Есть "изделие", которое есть набор деталей + ссылка на "техпроцесс". Деталь сама по себе тоже "изделие", почему нет?
У нас будет еще Builder, который вообще бы лучше был "Производство", но в нашем случае пускай Склад выполняет и функции Builderа тоже

code text
  1. static {
  2.    ОписаниеИзделия Буратина:= собрать { Мальвина, хер }
  3.    ОписаниеИзделия Мальвина:= собрать { рука,нога,попа); }
  4.    ОписаниеИзделия рука:= элементарная деталь
  5.    ОписаниеИзделия нога:= элементарная деталь
  6.    ОписаниеИзделия попа:= элементарная деталь
  7. }


сделать Буратину:

code text
  1. поставить(ОписаниеИзделия описание) {
  2.      если(есть на складе готовый (описание))
  3.          return выдать_экземпляр();
  4.      если(это элементарная деталь)
  5.          бросить_эксепшен;
  6.      Изделие изделие = new Изделие
  7.      try {
  8.         foreach(детальID:описание) {
  9.               изделие.добавить(поставить(детальID));
  10.         }
  11.      } catch(e) {
  12.          расформировать частично собранное изделие
  13.          бросить эксепшн
  14.      }
  15.      return изделие;
  16. }


запрос:

code text
  1. try {
  2.      список = взять_список_чего_надо();
  3.      для всего списка:
  4.           изделие = склад.поставить(описаниеИзделия);
  5.      послать_пользователю(бухгалтерия.сформировать_накладную(список))
  6.      послать_почтой(все изделия)
  7.      забиллить_клиента
  8. } catch() {
  9.      положить все уже готовые изделия обратно на склад или расформировать если надо()
  10.      послать_клиента_нах();
  11. }
 
Это сообщение редактировалось 27.08.2008 в 00:13
US Сергей-4030 #27.08.2008 00:11  @Balancer#26.08.2008 23:31
+
-
edit
 

Сергей-4030

исключающий третье
★★
Balancer> Буратино - не является наследником его деталей :)

Тут есть деликатное отличие. Буратино НЕ является наследником своей ноги или руки, НО ЯВЛЯЕТСЯ классом-имплементацией интерфейса "Деталь". Тут наследование - интерфейсное. Буратино есть (сложная) деталь, рука есть (простая) деталь, нога есть (простая) деталь. Но, конечно, Буратино не есть наследник от ноги, руки и головы.
 
+
-
edit
 

HolyBoy

аксакал

Ромин пост понял, Серегины пока нет, но пытаюсь понять. :)
 
US Сергей-4030 #27.08.2008 00:55  @HolyBoy#27.08.2008 00:49
+
-
edit
 

Сергей-4030

исключающий третье
★★
HolyBoy> Ромин пост понял, Серегины пока нет, но пытаюсь понять. :)

Тут смысл в том, что собственно не про ООП надо думать, а о OOD. :) Design patterns - вот чего неплохо бы почитать. Они, конечно, не есть наука, а есть всего только практика, но они - правильная практика. :)

PS И надо-таки различать интерфейсное наследование от классового. Интерфейсное это такое: есть интерфейс "тяжелый", у него есть свойство "масса()". "Камень" или "Самолет" не есть подклассы "Тяжелого", они имплементируют этот интерфейс. Конкретные механизмы "интерфейсного наследования" отличаются от языка к языку.
 

Murkt

Pythoneer

Murkt>> Используется не массив как таковой, а связь "многие-ко-многим". Попробуй посмотреть в документации РоР - many to many (m2m), или ещё как-нибудь так. Я могу написать приблизительный код на Django, но РоР (да и вообще Руби) я не знаю.
HolyBoy> А, понял.
HolyBoy> Т.е. можно для класса задать свойство соответствующее и оно заработает? Ок. Спасибо.
Ага, где-то так. В Джанге будет выглядеть так:
code python
  1. class Part(Model):
  2.     ...
  3. class Buratino(Model):
  4.     parts = ManyToManyField(Part)

И получить потом список всех деталей определённого буратины - buratina.parts.all(). В РоР оно будет чуть иначе выглядеть, но суть должна остаться та же самая.
[team Їжачки - сумні падлюки]  
UA Murkt #27.08.2008 01:04  @Сергей-4030#27.08.2008 00:55
+
-
edit
 

Murkt

Pythoneer

Сергей-4030> И надо-таки различать интерфейсное наследование от классового. Интерфейсное это такое: есть интерфейс "тяжелый", у него есть свойство "масса()". "Камень" или "Самолет" не есть подклассы "Тяжелого", они имплементируют этот интерфейс. Конкретные механизмы "интерфейсного наследования" отличаются от языка к языку.
Посмотри какой язык используется - Руби. При чём здесь интерфейсное наследование может быть? Фтопку его.
[team Їжачки - сумні падлюки]  
US Сергей-4030 #27.08.2008 02:22  @Murkt#27.08.2008 01:04
+
-
edit
 

Сергей-4030

исключающий третье
★★
Сергей-4030>> И надо-таки различать интерфейсное наследование от классового. Интерфейсное это такое: есть интерфейс "тяжелый", у него есть свойство "масса()". "Камень" или "Самолет" не есть подклассы "Тяжелого", они имплементируют этот интерфейс. Конкретные механизмы "интерфейсного наследования" отличаются от языка к языку.
Murkt> Посмотри какой язык используется - Руби. При чём здесь интерфейсное наследование может быть? Фтопку его.

Интерфейсное наследование не атрибут языка а атрибут OOD. В Руби оно имплементируется микс-инами.
 
UA Murkt #27.08.2008 09:27  @Сергей-4030#27.08.2008 02:22
+
-
edit
 

Murkt

Pythoneer

Сергей-4030> Интерфейсное наследование не атрибут языка а атрибут OOD. В Руби оно имплементируется микс-инами.
В Руби - duck typing, там интерфейсное наследование просто не нужно. Если что-то реализовано, ты и так можешь его вызвать, и наследование здесь ни к чему.
[team Їжачки - сумні падлюки]  
US Сергей-4030 #27.08.2008 18:13  @Murkt#27.08.2008 09:27
+
-
edit
 

Сергей-4030

исключающий третье
★★
Сергей-4030>> Интерфейсное наследование не атрибут языка а атрибут OOD. В Руби оно имплементируется микс-инами.
Murkt> В Руби - duck typing, там интерфейсное наследование просто не нужно. Если что-то реализовано, ты и так можешь его вызвать, и наследование здесь ни к чему.

Да, пожалуй. Увлекся-с. :) Но я не про кодирование в данном случае говорил, я про дизайн, а там определять интерфейсы надо в любом случае.
 
UA Murkt #27.08.2008 18:48  @Сергей-4030#27.08.2008 18:13
+
-
edit
 

Murkt

Pythoneer

Сергей-4030> Да, пожалуй. Увлекся-с. :) Но я не про кодирование в данном случае говорил, я про дизайн, а там определять интерфейсы надо в любом случае.
В любом случае, если используемый язык - Джава :D Шутка юмора. Смотря как понимать слова "определять интерфейсы".
[team Їжачки - сумні падлюки]  
US Сергей-4030 #27.08.2008 19:05  @Murkt#27.08.2008 18:48
+
-
edit
 

Сергей-4030

исключающий третье
★★
Сергей-4030>> Да, пожалуй. Увлекся-с. :) Но я не про кодирование в данном случае говорил, я про дизайн, а там определять интерфейсы надо в любом случае.
Murkt> В любом случае, если используемый язык - Джава :D Шутка юмора. Смотря как понимать слова "определять интерфейсы".

Вот в этом смысле:
It's also important to understand the difference between class inheritance and interface inheritance (or subtyping). Class inheritance defines an object's implementation in terms of another object's implementation. In short, it's a mechanism for code and representation sharing. In contrast, interface inheritance (or subtyping) describes when an object can be used in place of another.
 


В Руби любой объект может быть использован вместо другого на этапе кодирования, но при дизайне надо знать свои интерфейсы.
 
UA Murkt #27.08.2008 20:06  @Сергей-4030#27.08.2008 19:05
+
-
edit
 

Murkt

Pythoneer

Murkt>> В любом случае, если используемый язык - Джава :D Шутка юмора. Смотря как понимать слова "определять интерфейсы".
Сергей-4030> В Руби любой объект может быть использован вместо другого на этапе кодирования, но при дизайне надо знать свои интерфейсы.
Я имею в виду - как определять. Так, что я знаю, что нужны вот такие-то вот методы и поля (написано в документации/комментариях), или именно создавать классы интерфейсов/миксинов?
[team Їжачки - сумні падлюки]  
US Сергей-4030 #27.08.2008 20:14  @Murkt#27.08.2008 20:06
+
-
edit
 

Сергей-4030

исключающий третье
★★
Murkt> Я имею в виду - как определять. Так, что я знаю, что нужны вот такие-то вот методы и поля (написано в документации/комментариях), или именно создавать классы интерфейсов/миксинов

В данном случае - в дизайн документации, видимо.
 
UA Murkt #27.08.2008 21:14  @Сергей-4030#27.08.2008 20:14
+
-
edit
 

Murkt

Pythoneer

Murkt>> Я имею в виду - как определять. Так, что я знаю, что нужны вот такие-то вот методы и поля (написано в документации/комментариях), или именно создавать классы интерфейсов/миксинов
Сергей-4030> В данном случае - в дизайн документации, видимо.
Претензий больше не имею ;)
[team Їжачки - сумні падлюки]  
US Сергей-4030 #27.08.2008 21:22  @Murkt#27.08.2008 21:14
+
-
edit
 

Сергей-4030

исключающий третье
★★
Murkt>>> Я имею в виду - как определять. Так, что я знаю, что нужны вот такие-то вот методы и поля (написано в документации/комментариях), или именно создавать классы интерфейсов/миксинов
Сергей-4030>> В данном случае - в дизайн документации, видимо.
Murkt> Претензий больше не имею ;)

Типа, сорри, увлекся. ;)
 

в начало страницы | новое
 
Поиск
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru