Re[3]: Закон Деметера на практике
От: GlebZ Россия  
Дата: 18.02.07 17:05
Оценка: 12 (3)
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>Если шашечки, почему тогда не первый вариант? Он на один метод меньше, значит проще.

Мы же смотрим именно концептуальную целостность гипотетической задачи. Если мы выделили сущность "обслуживание", значит это конгломерат некоторых действий обслуживающих сценарии связнные с обслуживанием. У нас есть три сущности — "машина", "колесо", "обслуживание" или объект занимающийся обслуживанием. У нас есть некоторые сценарий, в число которых не входит вариант надуть машину. Соответвенно машина тут лишняя. Остается обслуживание и колесо, и два возможных варианта:
1. колесо.надуть(обслуживание объект_обслуживания)
2. обслуживание.надуть(колесо объект_колесо).
Любой из этих вариантов будет верным, но второй вариант в большинстве случаев будет вернее. Обслуживание может инициировать надувание колеса, колесо — нет. Обслуживание может объединить сценарии связанные с обслуживанием все мащины (или можем даже выделить сущность "обслуживание колеса".
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[2]: Закон Деметера на практике
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 18.02.07 12:26
Оценка: 6 (2) +1
Здравствуйте, GlebZ, Вы писали:

MP>> Надо ли стремиться к выполнению закона Деметера, или это "шашечки"?

GZ>По жизни — это шашечки.

Если ты подходиш с принципом — один класс решает одну задачу, то очень даже не шашечки. То есть, если класс "умеет" "качать" колёса, то не его заботой должно "извлечение" колёс из машины.

GZ>Концептуально и логически, в данном контексте, верен третий вариант. Надуть колеса — это один из методов обслуживания. Колесо само по себе не надувается.


Имхо, соотносить один в один объекты реального мира и в программе это большая ошибка.
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re: Закон Деметера на практике
От: MaximVK Россия  
Дата: 20.02.07 08:51
Оценка: 3 (2)
Здравствуйте, Mikhail Polykovsky, Вы писали:

3-й вариант. За исключением того, что "левоеПереднееКолесо" — не очень удачный вариант. Т.к. машины могут обладать разным количеством колес и придется писать разные "обслуживания". Т.е. возможность получить колеса в виде коллекции у тебя явно напрашивается. Что касается дальнейших изменений, то тут вариантов может быть много. Что может меняться? Понадобиться качать не только колеса, а еще и шарики, надувные лодки и брюшной пресс? Придется обслуживать не только машины, а велосипеды, тракторы или самолеты? Появяться машины с самоподкачивающимися колесами или детские велосипеды с колесами из сплошной резины? Будешь учитывать все варианты — сделаешь супергибкое решение, но просядешь по срокам так, что твое решение уже нафиг никому не будет нужно. Не учтешь какого-нить варианта, потеряешь клиентов из-за тормозов с кастомизацией или расширением функциональности. Идеальной стратегии нет и это исключительно хорошо, т.к. именно благодаря этой неопределенности и существует возможность у маленькой компании из 5 человек сделать продукт, который станет лучшим на рынке.

P.S. Кстати, был у меня коллега, который в оголтелой погоне за соблюдением закона Дементора наплодил такое количество врапперов по проекту, что их стало чуть ли не больше, чем обычных классов.
Re[3]: Закон Деметера на практике
От: DrDred Россия  
Дата: 18.02.07 10:51
Оценка: 1 (1) +1
Здравствуйте, Mikhail Polykovsky, Вы писали:

ANS>>Но при первой же необходимости вырефакторил бы в третий вариант.


MP>А как определить, что появилась необходимость?

По-моему а Фаулера в "Рефакторинге" была мысль насчет 3-х использований, то есть первый раз мы просто пишем как есть, если мы проходим по этому коду второй раз, и он нам не нравится, мы помечаем его как потенциального кандидата на рефакторинг, ну аж если мы попали сюда в третий раз...
На самом деле все смотрится по обстоятельствам, и думаю можно вполне доверять своему чутью..
... << RSDN@Home 1.2.0 alpha rev. 672>>
--
WBR, Alexander
Re[3]: Закон Деметера на практике
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 18.02.07 11:02
Оценка: 2 (1)
Здравствуйте, Mikhail Polykovsky, Вы писали:


ANS>>При именно такой постановке задания, я бы остановился на первом варианте


MP>Который нарушает закон


Хм. Криво посотрел на код Я за такой вариант:
Машина.обслуживание() {
   колёса.накачать()
}

И никакого нарушения.

ANS>>Но при первой же необходимости вырефакторил бы в третий вариант.


MP>А как определить, что появилась необходимость?


При помощи сдравого смысла. Кстати, я и тут не точно выразился Я говорил о рефакторинге не в твой третий вариант, а в вариант когда колёса накачивает некий "Насос". То есть, "ОбслуживающийПерсонал" получает у "Машины" колёса и передаёт их "Насосу" для накачки. Но плодить такое без надобности я бы не стал. Начал бы с кода, который привёл выше.
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[7]: Закон Деметера на практике
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 19.02.07 09:07
Оценка: 2 (1)
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>Ну хорошо, пусть Фильтр. Покажи мне пожалуйста, как бы ты сделал метод отбора Машин по МаркеКолеса в классе Фильтр. Метод получает на вход массив объектов "Машина".


Тут есть два способа.
1-й. Сделать Фильтр, который получает на вход список машин, у которых получает список колёс и сам определяет есть ли колёса, удовлетворяющие условию:
 колёса := машина.всеКолёса().
 foreach (колесо: колёса) {
  if (колесо.марка = искомаяМарка) return true;
 }


2-й. Сделать ФильтрМашин, который получает на вход список машин, вытягует у каждой машины список колёс и передаёт уже этот список колёс на проверку ФильтруКолёс:
 колёса := машина.всеКолёса().
 фильтрКолёс = new ФильтрКолёс(искомаяМарка).
 return фильтрКолёс.проверить(колёса).


В первом случае ты можеш фильтровать только машины. Во втором, можешь машины, и можеш колёса (например на складе). Объём кода почти одинаков (понятно, что во втором случае больше инфраструктуры — типа конструкторов и пр.). Первый случай нарушает Закон Деметера, второй нет. Выбор за тобой.

ЗЫ. Работающие программы получаются и без следования Закону Деметера Просто его нарушение может быть звоночком, что есть и более удачные варианты.
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re: Закон Деметера на практике
От: Janii  
Дата: 19.02.07 10:40
Оценка: 2 (1)
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>Как вы считаете, какой из вариантов более аккуратный? Какой облегчает поддержку и дальшейшие изменения программы?


Это зависит от задачи, IMHO. Абстрактно дать лучший ответ сложно, но я бы, в тех условиях что даны, по умолчанию считал лучшим вот такой вариант:

void обслуживание(Машина машина){
   машина.НакачатьКолеса(); 
}


MP>Надо ли стремиться к выполнению закона Деметера, или это "шашечки"?


Стремиться надо, но важно не переусердствовать. Минимизация связывания — это дорогостоящая операция и затраты на нее далеко не всегда оправданы.
Re: Закон Деметера на практике
От: Dmitry Dolgopolov  
Дата: 21.02.07 17:36
Оценка: 2 (1)
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>Но мне вот что непонятно. Если мне в метод, например, передается объект "Машина", у которой надо накачать колеса, как лучше поступить?


Есть несколько вариантов, при которых не нарушается упомянутый закон. Если объект класса Машина умеет обрабатывать сообщение накачатьКолесо(), тогда можно рассмотреть такой вариант:
void Персонал::обслужитьМашину(Машина машина)
{
    машина.накачатьКолесо(переднее-левое);
    машина.накачатьКолесо(переднее-правое);
    машина.накачатьКолесо(заднее-левое);
    машина.накачатьКолесо(заднее-правое);
    ...
}

Однако, если колеса в большинстве случаев качаются все вместе, тогда более подходящий вариант следующий:
void Персонал::обслужитьМашину(Машина машина)
{
    машина.накачатьКолеса();
    ...
}

Выбор, наверное, зависит еще и от возможности исключений в каждом из приведенных методов объекта "машина".
Re[3]: Закон Деметера на практике
От: DrDred Россия  
Дата: 18.02.07 10:51
Оценка: 1 (1)
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>Я правильно понял, что это за третий вариант?

Да... Просто так имхо было чуть покрасивше, ибо не нужно было привязываться к методам вида getLeftFrontWeel()
... << RSDN@Home 1.2.0 alpha rev. 672>>
--
WBR, Alexander
Re[3]: Закон Деметера на практике
От: GlebZ Россия  
Дата: 18.02.07 16:49
Оценка: 1 (1)
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Если ты подходиш с принципом — один класс решает одну задачу, то очень даже не шашечки. То есть, если класс "умеет" "качать" колёса, то не его заботой должно "извлечение" колёс из машины.

По жизни может быть что и класс колесо может быть избыточным, и есть неотъемлимая часть машины.

ANS>Имхо, соотносить один в один объекты реального мира и в программе это большая ошибка.

А тут нет реального мира. Объект обслуживание — может не быть объектом реального мира, а эту работу выполняет водитель. И сущность водитель или станция тех. обслуживания мы можем не учитывать. Обслуживание — это может быть синт. абстракция созданная для достижения целей программы.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 18.02.07 06:50
Оценка:
Здравствуйте.
Читаю книгу "Программист-прагматик", там один из советов — придерживаться закона Деметера. Закон звучит так:

Любой метод объекта должен обращаться только к методам, принадлежащим:
— тому же классу
— любым объектам, переданным в метод в качестве аргументов
— любым создаваемым им объектам
— любым непосредственно содержащимся объектам компонентов


То есть

void Demeter::example(B& b){
  b.invert(); // Так можно
  
  b.getUser.name(); // Так не рекомендуется
}


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

1 вариант (нарушение закона):
void обслуживание(Машина машина){
  машина.левоеПереднееКолесо().накачать();
}


2 вариант (добавление лишнего(?) метода в класс "Машина"):
void обслуживание(Машина машина){
  машина.накачатьЛевоеПереднееКолесо();
}


3 вариант (добавление лишнего(?) метода в текущий класс):
void обслуживание(Машина машина){
  колесо = машина.левоеПереднееКолесо(); 
  накачать(колесо);
}

void накачать(Колесо колесо){
  колесо.накачать();


Как вы считаете, какой из вариантов более аккуратный? Какой облегчает поддержку и дальшейшие изменения программы? Надо ли стремиться к выполнению закона Деметера, или это "шашечки"?
Re: Закон Деметера на практике
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 18.02.07 08:53
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

Имхо, второй вариант бессмысленный.
Третий вариант имеет смысл если метод "накачать(Колесо колесо)" будет вынесен из "Машины" в, например, класс "Насос".

При именно такой постановке задания, я бы остановился на первом варианте Но при первой же необходимости вырефакторил бы в третий вариант.

MP> Надо ли стремиться к выполнению закона Деметера, или это "шашечки"?


Желательно придерживаться.
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re: Закон Деметера на практике
От: DrDred Россия  
Дата: 18.02.07 09:26
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

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


void ТО(Машина машина)
{
    накачать_колеса(машина.getWheels())
}
void накачать_колеса(Колесо[] колеса)
{
    foreach(колесо in колеса) {}
}
... << RSDN@Home 1.2.0 alpha rev. 672>>
--
WBR, Alexander
Re[2]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 18.02.07 10:24
Оценка:
Здравствуйте, DrDred, Вы писали:

DD>Здравствуйте, Mikhail Polykovsky, Вы писали:


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


DD>
DD>void ТО(Машина машина)
DD>{
DD>    накачать_колеса(машина.getWheels())
DD>}
DD>void накачать_колеса(Колесо[] колеса)
DD>{
DD>    foreach(колесо in колеса) {}
DD>}
DD>


Я правильно понял, что это за третий вариант?
Re[2]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 18.02.07 10:27
Оценка:
ANS>При именно такой постановке задания, я бы остановился на первом варианте

Который нарушает закон


ANS>Но при первой же необходимости вырефакторил бы в третий вариант.


А как определить, что появилась необходимость?
Re: Закон Деметера на практике
От: GlebZ Россия  
Дата: 18.02.07 11:51
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>Как вы считаете, какой из вариантов более аккуратный? Какой облегчает поддержку и дальшейшие изменения программы? Надо ли стремиться к выполнению закона Деметера, или это "шашечки"?

По жизни — это шашечки. Концептуально и логически, в данном контексте, верен третий вариант. Надуть колеса — это один из методов обслуживания. Колесо само по себе не надувается.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[4]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 18.02.07 12:25
Оценка:
ANS> При помощи сдравого смысла. Кстати, я и тут не точно выразился Я говорил о рефакторинге не в твой третий вариант, а в вариант когда колёса накачивает некий "Насос". То есть, "ОбслуживающийПерсонал" получает у "Машины" колёса и передаёт их "Насосу" для накачки. Но плодить такое без надобности я бы не стал. Начал бы с кода, который привёл выше.

Видишь ли, для меня сложность вознеикает именно тогда, когда требуется отдать малую часть вложенного объекта на сторону для каких-то действий.

Например, есть список Машин, у Машин есть Колеса, у Колес есть МаркаКолеса. Чтобы сделать Отчет по МаркамКолес, нужно перебрать все Машины, обратиться к Колесам, получить МаркуКолеса и вывести в Отчет. В такой терминологии как ты распределишь вызовы по методам?
Re[2]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 18.02.07 12:27
Оценка:
MP>>Как вы считаете, какой из вариантов более аккуратный? Какой облегчает поддержку и дальшейшие изменения программы? Надо ли стремиться к выполнению закона Деметера, или это "шашечки"?
GZ>По жизни — это шашечки. Концептуально и логически, в данном контексте, верен третий вариант. Надуть колеса — это один из методов обслуживания. Колесо само по себе не надувается.

Если шашечки, почему тогда не первый вариант? Он на один метод меньше, значит проще.
Re[3]: Принципы выбора объектов
От: Mikhail Polykovsky Россия  
Дата: 18.02.07 12:32
Оценка:
ANS>Имхо, соотносить один в один объекты реального мира и в программе это большая ошибка.

Почему? Вроде бы ООП на этом построено?
Re[4]: Принципы выбора объектов
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 18.02.07 12:57
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

ANS>>Имхо, соотносить один в один объекты реального мира и в программе это большая ошибка.


MP>Почему? Вроде бы ООП на этом построено?


ООП построен на том, что объекты в программе (а не в реальном мире) обмениваются сообщениями. В "Философии" об этом много философствовали
Автор: Andrei N.Sobchuck
Дата: 15.06.06
, так что тут не то место чтобы спорить на эту тему.
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[5]: Закон Деметера на практике
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 18.02.07 12:57
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:


MP>Например, есть список Машин, у Машин есть Колеса, у Колес есть МаркаКолеса. Чтобы сделать Отчет по МаркамКолес, нужно перебрать все Машины, обратиться к Колесам, получить МаркуКолеса и вывести в Отчет. В такой терминологии как ты распределишь вызовы по методам?


Если бы мне в одном месте, по ходу дела, понадобилось бы отобрать машины по марке колеса, я бы, скорее всего, не заморачивался с законом Деметера. А вот если уже в двух (или в трёх ), то скорее всего создал бы класс "Фильтр", который умеет фильтровать машины по некому "Критерию".
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[6]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 18.02.07 13:11
Оценка:
MP>>Например, есть список Машин, у Машин есть Колеса, у Колес есть МаркаКолеса. Чтобы сделать Отчет по МаркамКолес, нужно перебрать все Машины, обратиться к Колесам, получить МаркуКолеса и вывести в Отчет. В такой терминологии как ты распределишь вызовы по методам?

ANS>Если бы мне в одном месте, по ходу дела, понадобилось бы отобрать машины по марке колеса, я бы, скорее всего, не заморачивался с законом Деметера. А вот если уже в двух (или в трёх ), то скорее всего создал бы класс "Фильтр", который умеет фильтровать машины по некому "Критерию".


Ну хорошо, пусть Фильтр. Покажи мне пожалуйста, как бы ты сделал метод отбора Машин по МаркеКолеса в классе Фильтр. Метод получает на вход массив объектов "Машина".
Re[4]: Принципы выбора объектов
От: GlebZ Россия  
Дата: 18.02.07 17:09
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

ANS>>Имхо, соотносить один в один объекты реального мира и в программе это большая ошибка.


MP>Почему? Вроде бы ООП на этом построено?

Уже давно нет. Мы делаем синтетическую задачу в совершенно другом окружении в виде компьютера. Поэтому программа должна строится на основе действий(сценариев) пользователя при общении с компьютером. А действия бывает иногда противоречат объектам реального мира, или объекты реального мира могут быть слишком усложнены для реализации на компьютере.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re: Закон Деметера на практике
От: Miroff Россия  
Дата: 20.02.07 07:34
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

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


Не передавать в метод обслуживание экземпляр машины. Поскольку метод "обслуживание" потенциально машино-зависим разумно делегировать эту функциональность машине:
class Машина {
  void обслуживание() {
      self.ЛевоеПереднееКолесо.накачать();
    }
}
Машина машина = Машина.new();
машина.обслуживание();


В будущем, метод обслуживание может сильно распухнуть, тогда потребуется оставив базовые операции вида "НакачатьКолеса" или "ПротеретьФары" применить паттерн Strategy.

MP>Как вы считаете, какой из вариантов более аккуратный? Какой облегчает поддержку и дальшейшие изменения программы? Надо ли стремиться к выполнению закона Деметера, или это "шашечки"?

Закон Деметра позволяет избежать длинных цепочек делегации вида "машина.правоеПереднееКолесо.накачать". Такие цепочки череваты ошибками, небезопасны (кто сказал что у машины есть правое колесо?) и черезмерно усложняют код (если проверять существование колеса)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 20.02.07 07:41
Оценка:
MP>>Аргументация в том, что уменьшается связанность и упрощается изменение классов. Но мне вот что непонятно. Если мне в метод, например, передается объект "Машина", у которой надо накачать колеса, как лучше поступить?

M>Не передавать в метод обслуживание экземпляр машины. Поскольку метод "обслуживание" потенциально машино-зависим разумно делегировать эту функциональность машине


Хорошо, этот пример я понял. А что делать в случае необходимости фильтра
Автор: Mikhail Polykovsky
Дата: 18.02.07
? Тоже закладывать его в класс Машина? Или в класс Колесо?
Re[3]: Закон Деметера на практике
От: Miroff Россия  
Дата: 20.02.07 08:16
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>Хорошо, этот пример я понял. А что делать в случае необходимости фильтра
Автор: Mikhail Polykovsky
Дата: 18.02.07
? Тоже закладывать его в класс Машина? Или в класс Колесо?

Машина не осведомлена о наличии других мащин, равно, как и колесо не осведомлено о наличии других колес. Фильтрами должна заниматься коллекция машин или та прослойка, которая достает машины из БД, файлов и т.п. В этом случае, да, машины должны предоставлять этой коллекции/прослойке информацию о своих свойствах.
class СписокМашин {
  СписокМашин фильтрПоТипуКолеса( типКолеса ) {
      //Здесь мы генерим запрос или нашу перебираем коллекцию машин
        //Например:
        СписокМашин совпадение = СписокМашин.new()
        foreach машина in self.список {
            if (машина.типКолес == типКолеса) {
                совпадение.push(машина)
            }
        }
        return совпадение
    }
}

списокМашины.фильтрПоТипуКолеса( Шипованный );
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 20.02.07 08:37
Оценка:
MP>>Хорошо, этот пример я понял. А что делать в случае необходимости фильтра
Автор: Mikhail Polykovsky
Дата: 18.02.07
? Тоже закладывать его в класс Машина? Или в класс Колесо?

M>Машина не осведомлена о наличии других мащин, равно, как и колесо не осведомлено о наличии других колес. Фильтрами должна заниматься коллекция машин или та прослойка, которая достает машины из БД, файлов и т.п. В этом случае, да, машины должны предоставлять этой коллекции/прослойке информацию о своих свойствах.

M> if (машина.типКолес == типКолеса) {


И вот здесь, насколько я понимаю, нарушается закон Деметера? Это самый оптимальный вариант?
Re[5]: Закон Деметера на практике
От: Miroff Россия  
Дата: 20.02.07 08:56
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>И вот здесь, насколько я понимаю, нарушается закон Деметера? Это самый оптимальный вариант?

Или я что-то не так понимаю, или не нарушается:

Любой метод объекта должен обращаться только к методам, принадлежащим:
— тому же классу
— любым объектам, переданным в метод в качестве аргументов
— любым создаваемым им объектам
любым непосредственно содержащимся объектам компонентов


Этот закон можно грубо переформулировать как "никаких ссылок через две точки".
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Закон Деметера на практике
От: MaximVK Россия  
Дата: 20.02.07 09:06
Оценка:
Здравствуйте, Miroff, Вы писали:

M>Этот закон можно грубо переформулировать как "никаких ссылок через две точки".


Почти так. В оригинале звучит "не общайтесь со странниками".
Re[5]: Закон Деметера на практике
От: Miroff Россия  
Дата: 20.02.07 09:10
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>И вот здесь, насколько я понимаю, нарушается закон Деметера? Это самый оптимальный вариант?

Или я что-то не так понимаю, или не нарушается:

Любой метод объекта должен обращаться только к методам, принадлежащим:
— тому же классу
— любым объектам, переданным в метод в качестве аргументов
— любым создаваемым им объектам
любым непосредственно содержащимся объектам компонентов


Этот закон можно грубо переформулировать как "никаких ссылок через две точки".
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 20.02.07 09:12
Оценка:
MP>>И вот здесь, насколько я понимаю, нарушается закон Деметера? Это самый оптимальный вариант?
M>Или я что-то не так понимаю, или не нарушается:

M>

M>Любой метод объекта должен обращаться только к методам, принадлежащим:
M>— тому же классу
M>— любым объектам, переданным в метод в качестве аргументов
M>— любым создаваемым им объектам
M>— любым непосредственно содержащимся объектам компонентов


M>Этот закон можно грубо переформулировать как "никаких ссылок через две точки".


Любую ссылку через две точки можно развернуть в две ссылки с одной точкой, используя временную переменную. В чем же тогда смысл?
Re[7]: Закон Деметера на практике
От: Miroff Россия  
Дата: 20.02.07 09:21
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>В чем же тогда смысл?

В том и смысл, чтобы не делать так, что обращение можно свернуть в "через две точки". Если сворачивается, значит что-то сделано неправильно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 20.02.07 12:41
Оценка:
MP>>В чем же тогда смысл?
M>В том и смысл, чтобы не делать так, что обращение можно свернуть в "через две точки". Если сворачивается, значит что-то сделано неправильно.

Извини, что-то я недопонял. Ведь любую строку

object.subObject.method()

можно преобразовать в

sub = object.subObject
sub.metod()

и по твоим словам закон Деметера соблюден. А по моему мнению все равно нарушается, просто в скрытой форме.
Re[7]: Закон Деметера на практике
От: GlebZ Россия  
Дата: 20.02.07 15:46
Оценка:
Здравствуйте, Mikhail Polykovsky, Вы писали:

MP>Ну хорошо, пусть Фильтр. Покажи мне пожалуйста, как бы ты сделал метод отбора Машин по МаркеКолеса в классе Фильтр. Метод получает на вход массив объектов "Машина".

Это изначально неверная постановка задачи. Потому как реализация по закону Деметры — разделяет функциональность в том числе по методам. И это будет не один метод. Что-то типа следующего:
public class CarsCollectionHelper
{
.....
   public List<Car> FilterByMark(List<Car> source, Mark mark)
   {
        List<Wheel> wheels=GetWheels(source);
        List<Wheel> wheelsMarked=FilterByMark(wheels, mark);
        return GetOwnerCars(wheelsMarked);
   }
   List<Wheel> GetWheels(List<Car> source){...}
   List<Wheel> FilterByMark(List<Wheel> source){...}
   List<Car> GetOwnerCars(List<Wheel> source){...}
}
Re[8]: Закон Деметера на практике
От: Mikhail Polykovsky Россия  
Дата: 20.02.07 19:10
Оценка:
MP>>Ну хорошо, пусть Фильтр. Покажи мне пожалуйста, как бы ты сделал метод отбора Машин по МаркеКолеса в классе Фильтр. Метод получает на вход массив объектов "Машина".
GZ>Это изначально неверная постановка задачи. Потому как реализация по закону Деметры — разделяет функциональность в том числе по методам. И это будет не один метод. Что-то типа следующего:
GZ>
GZ>public class CarsCollectionHelper
GZ>{
GZ>.....
GZ>   public List<Car> FilterByMark(List<Car> source, Mark mark)
GZ>   {
GZ>        List<Wheel> wheels=GetWheels(source);
GZ>        List<Wheel> wheelsMarked=FilterByMark(wheels, mark);
GZ>        return GetOwnerCars(wheelsMarked);
GZ>   }
GZ>   List<Wheel> GetWheels(List<Car> source){...}
GZ>   List<Wheel> FilterByMark(List<Wheel> source){...}
GZ>   List<Car> GetOwnerCars(List<Wheel> source){...}
GZ>}
GZ>


Ага, значит плодить методы, каждый из которых занимается небольшой частью работы. Спасибо, понял.
Re[2]: Закон Деметера на практике
От: Dmitry Dolgopolov  
Дата: 21.02.07 17:49
Оценка:
DD>void Персонал::обслужитьМашину(Машина машина)
DD>{
DD>    машина.накачатьКолесо(переднее-левое);
DD>    машина.накачатьКолесо(переднее-правое);
DD>    машина.накачатьКолесо(заднее-левое);
DD>    машина.накачатьКолесо(заднее-правое);
DD>    ...
DD>}

Чтобы было более понятно, метод накачатьКолесо() класса Машина:
void Машина::накачатьКолесо(ИдентификаторКолеса колесо)
{
    колеса[колесо].накачать();
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.