Как стать автором
Обновить
6
0
Давид Шекунц @Dionid

Full-stack Software Engineer

Отправить сообщение
Да, крутой пример, спасибо! Лайкнул бы, но рейтинг хейтеры сожрали)
Наша ветка — прекрасный пример тому, что несмотря на приличное количество контрпримеров, основной текст (и тон) вашего поста остался без изменений.

Да, потому что это мой пост и мое мнение, а есть ваше мнение.

Я хочу, чтобы вы не пропагандировали идею, что что-то, называющееся «законом Деметры» на самом деле является сколько-нибудь объективным правилом, ведущим к хорошему коду.

Для вас нет, а мне и моим коллегам знание этого принципа полезно для принятия решения использовать или не использовать его в той или иной ситуации.

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

У вас есть позиция против LoD, ок, это ваша позиция.
Ну то есть ваша цель — она «получить побольше комментариев»?

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

А «правила» вообще существуют в определенных рамках.

Оно называет «Правило / Закон Деметры», вы хотите чтобы я перевел это как-то по-другому? Кажется, вы не заметили, что лично я использую в статье слово «принцип»
Правда же, совсем иначе звучит?

Согласен, но вы очень категоричны, мне нравится мое название, оно завлекает и заставляет людей написать почти 40 комментариев)

… а вмержить все равно не дадут, потому что правила.

Мы говорим про терминологию, а не устав процесса разработки компании, это абсолютно разные вещи. Это как соотносить «замок» на двери, и «замок» при вязке собак.

Поэтому, какое бы не было название у термина / паттерна, если его несоблюдение не мешает скомпилировать / воспроизвести программу с требующейся логикой это всегда «рекомендация». А если вы решили добавить его в устав, тогда становиться «правилом», но только в определенных рамках.
Случай с текстом не критический (хоть и влияет на восприятие), а вот случай с «обращением к локальной переменной» приведет к ошибке во время компиляции / исполнения кода.

Так вот, хоть и дословный перевод «Law of Demeter» получается «Правило / Закон Деметры», но, конечно же, на деле, это «рекомендация», потому что соблюдение / не соблюдение данного «правила» не повлияет на runtime или компиляцию кода.

Поэтому, какое бы не было название у термина / паттерна, если его несоблюдение не мешает скомпилировать / воспроизвести программу с требующейся логикой это всегда «рекомендация».
Мне не нравится неполнота правила.

Можете привести пример полноценного правила?

Неа. «Любой адекватный программист» понимает, что есть правила, а есть рекомендации, и одно от другого надо отличать.

А можете привести пример «правил», которые нарушать нельзя нигде и никогда?
С момента определения getter Comments вы можете скрыть любую внутреннюю связь / имплементацию.
Вам не нравится неполнота текста в описании правила на Википедии? Да, ребята ограничились описанием самого правила.

Любой адекватный программист понимает, что правила – это ориентир, а не неприкосновенная истина.

Ими можно пользоваться, а можно этого не делать. Выбор за каждым.
Переопределение getter – это один из приемов, который позволяет придерживаться LoD.

Просто не везде бывают getter (например в Golang в любом случае пришлось бы писать метод getComments)

repository.Active()

Это как-то слишком похоже на QueryBuider, поэтому я скорее за «repository.Where(ActiveSpecification())», но это лично моя вкусовщина.
И самое основное, что вам в нем не нравится?
Ну как-как. Раньше post.Comments (извините, я выше перепутал) возвращал все комментарии, станет возвращать только «активные». И все.

Через переопределение getter?

post.Where(ActiveSpecification())

А, вы в формате Active Record пишите, понял. Я использую Repository, чтобы больше сохранять чистоту Сущностей.
Мне кажется мы говорим о разных вещах, поэтому уточню: что в вашем понимании «LoD»? С терминологической точки зрения
А если нам не нужно об этом знать, то это будет спрятано в comment.Posts, и ничего снаружи трогать будет не надо.

Как именно будет спрятано?

А она ей и не является.

Вы выстаиваете цепочку методов от post, а спецификация должна существовать как отдельный класс с chain methods или как command.
LoD ничего не говорит про логику домена.

Я не говорил что LoD это говорит, наоборот, if бизнес-логика требует управлять вложенными сущностями -> можно использовать LoD

Агрегаты мне как раз очень нравятся

Это супер и они как раз являются отличными примером того, как LoD помогает структурировать код.
И опятьже ".Active()" это раскрытие подробностей, о которых внешнему коду может быть (зависит от бизнес-требований, о чем я писал выше) абсолютно не нужно знать.

posts.Comments.Active().OnlyByUser(...).Today()

Спецификация не должна быть частью сущности post, вот здесь есть хороший пример Specification blog.byndyu.ru/2014/07/command-and-query-responsibility.html
LoD стимулирует запихнуть весь API в один объект


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

Я думаю, что вам стоит почитать про Агрегаты из DDD, скорее всего, вам они тоже не понравятся, они тоже направлены на то, чтобы управлять всеми операциями, которые относятся к подчиненным / вложенным Сущностям.

а это совершенно не обязательно правильно

Да, именно так, поэтому я и написал в статье, что надо использовать «здравый смысл»)
«post.Comments.LastBy(c => c.TimeStamp)» – если когда-нибудь в вашем коде окажется, что вы не можете брать все комментарии, а только «активные», вам придется везде переписать на «post.Comments.LastBy(c => c.TimeStamp && c.isActive)» и тоже самое в любом месте, где есть «post.Comments...»

«post.GetLastCommentByTimeStamp» – позволит вам внести коррективу с «активными» постами только в рамках Post => меньше рефакторинга и опасности для оставшегося кода.

«А что если нам нужно где-то все получать, а где-то только активные?» – тогда появляются «post.GetLastActiveCommentByTimeStamp» и «post.GetLastCommentByTimeStamp», да, больше методов и большие названия (что точно минус), но они человекочитабельные и хорошо поддаются рефакторингу (что плюс).

Если же там дико сложные выборки с ужасными названиями, то просто используем паттерн Спецификация, который очень сильно уменьшит названия и даст больше гибкости, оставив преимущества LoD.
«является публичным API» – да, это поскольку вы приводите сейчас в пример распространенную библиотеку / стандарт, а LoD помогает ответить на вопрос: как вы сами в своем уникальном коде приложения определите публичный API.

Если у вас (одна из причин описанных выше) тогда LoD даст положительный эффект, если нет, тогда LoD не поможет.
Мое основное утверждение: «если перед вами задача трансформировать или получать данные из объекта, который имеет комплексные связи / сложную логику выборки, лучше всего воспользоваться LoD, а именно, создать метод, который скроет под собой все цепочки задействованных связей.»
Ладно, я понял, сообщество очень принципиальное, я буду аккуратнее подходить к его чувствам с формулировками)

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность