Pull to refresh

Comments 16

Мне где-то попадалась мысль, что когда пишешь какую-то функциональность первый раз — делай частное решение, когда сталкиваешься с этой же проблемой второй раз — скопирую код, модифицируй чтобы работал для этого случая и пометь на будущее и вот когда ты сталкиваешься с проблемой в третий раз — обобщай.

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

Подтверждение этой мысли я встречался и в своем коде и в коде коллег. Чаще было, что код излишне обобщен.

https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)


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

Спасибо за ссылку. Заодно вспомнил где я на него наткнулся — в книге Фаулера.

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

возвращается и тычет вам в лицо

Возможно, настоящая причина проблем в коллективе из статьи как раз в этом, а не в том, что каждый понимает одни и те же «лозунги» немного «по-своему».

Как это происходит:
1)Тимлид/ТехДир/Кто-то еще (Пусть будет Мистер М) делает ультимативным тоном спорное утверждение обильно посыпая его высокомерными ужимочками.
Обычно суть утверждения в следующем «Я Очень умный, надо делать так-то, а вы все Дебилы если со мной не согласны».
2) «Вы все» — слушают, но с такой оценкой себя они, конечно, не согласны — и начинается спор о том, чем «чьё кунг-фуDRY круче».

Последствия:
1)Когда оказывается, что М ошибся (так тоже бывает не редко) — признать это и принять решение которое было бы лучше для проекта ему мешает то заявление, в котором он назвал всех «идиотами»

2)«Вы все» — будут и дальше часть времени тратить не на то чтобы «дотащить проект», а на то чтобы найти где еще мистер М налажал

3)Эго МистераМ оплачено человеко-часами из бюджета проекта.

В чём мораль?
1)Не будьте «М». Вы не «самый умный в этой комнате».
2)Если вы нанимаете к себе в команду человека — постарайтесь убедиться что он не М.
Выглядит лучше, верно?


Нет. Не выглядит. Прозрачность потеряна. Введены лишние сущности. Хотя код и «модно» и «по-ООПовски», но он работает медленнее и стал заметно сложнее.

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

[
'price' => 'message about invalid price'
]

Но… Зачем?
Прозрачность потеряна.

ну вообще-то нет. Можно переименовать филд в requredAttributes что бы было "прозрачнее", но это в целом вопрос семантики кода.


Введены лишние сущности.

которые закрыты интерфейсом — не страшно.


Хотя код и «модно» и «по-ООПовски»

в каком месте оно "модно" и "по-ООПовски"? Это старые добрые процедуры. Процедура потому что функция не чистая, да и валидатор не должен кидать исключения. Для валидатора невалидные данные — это обычное дело.


но он работает медленнее и стал заметно сложнее.

на счет сложнее — да, но если у нас есть N валидаторов, саму логику мы можем инкапсулировать в какой-то более общий валидатор, например RequredAttributesValidator и дальше делать все за счет композиции. Тогда все красиво и "оопэшно".


Что до вопросов производительности — это спички. Не страшно. Для меня важнее что валидатор почему-то кидается исключениями.

В кавычках же («модно» и «по ООП-овски»).

Для меня важнее что валидатор почему-то кидается исключениями.

Кстати, а как надо делать? Собирать все проблемы в кучу и возвращать структуру
{
is_validated: false,
invalid_entries: []
}

?
P.s. с именами полей согласен, семантика не на высоте ;)
UFO just landed and posted this here

То есть клиентский код должен знать почему именно объект невалиден? Зачем тогда нужен валидатор?

При таком подходе эксепшены оправданы ;-)

Вот только мнится мне, что подход такой верен лишь в некоторых случаях (не люблю ультимативности в формулировках, а искать/выдумывать примеры не хочу).
UFO just landed and posted this here

то есть валидатор должен иметь стэйт? зачем?

validate($object): ErrorList тогда уже. isValid можно добавить как сокращение к проверке длины списка ошибок.

Многие пытаюсь усилить DRY через флаги в методах функций, что является неправильным


Например: контроллер getItems у которого есть флаг count_items, т.е. возвращает количество элементов.
Понять тут программиста можно — ведь получить товары и получить их количество очень похожие методы, но он тогда нарушает принцип Single Responsibility, ведь у нашего метода уже 2 ответственности.
Поэтому в этом случае в угоду DRY надо сделать методы: getItems, getCountItems.

пытаюсь усилить DRY через флаги в методах функций

но вроде как статья как раз об этом, нет? про то что DRY про знания а не про код. многие похожие с виду вещи имеют разные зоны отвественности (или относятся к разным ролям) и потому не являются дублированием.


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

Sign up to leave a comment.