Обновить

Комментарии 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. с именами полей согласен, семантика не на высоте ;)
НЛО прилетело и опубликовало эту надпись здесь

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

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

Вот только мнится мне, что подход такой верен лишь в некоторых случаях (не люблю ультимативности в формулировках, а искать/выдумывать примеры не хочу).
НЛО прилетело и опубликовало эту надпись здесь

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

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

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


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

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

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


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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
team.vk.company
Дата регистрации
Дата основания
Численность
свыше 10 000 человек
Местоположение
Россия
Представитель
Дмитрий Головин