Как стать автором
Обновить

Принципы для разработки: KISS, DRY, YAGNI, BDUF, SOLID, APO и бритва Оккама

Время на прочтение 8 мин
Количество просмотров 232K
Всего голосов 22: ↑19 и ↓3 +16
Комментарии 9

Комментарии 9

НПП ИТЭЛМА всегда рада молодым специалистам, выпускникам автомобильных, технических вузов, а также физико-математических факультетов любых других высших учебных заведений.


Ребят, а вот ваша вакансия старшего инженера-программиста в Москве с зп «от 60 000 руб. до вычета налогов» — это какая-то шутка?
Они думают если укажут ЗП в 5 раз ниже рыночной, то сделают вклад в дэмпинг зарплат)
НЛО прилетело и опубликовало эту надпись здесь
А я за выбор YAGNI + DRY + KISS.
Дублирование кода – пустая трата времени и ресурсов. Вам придется поддерживать одну и ту же логику и тестировать код сразу в двух местах, причем если вы измените код в одном месте, его нужно будет изменить и в другом.


Вот это лютый бред и трешак, который привёл к монолитизации и колоссальному увеличению связанности и мешает людям подняться на ступень выше в написании качественного кода. С ним возятся до сих пор, хотя больше плохого, чем хорошего. Ну при условии что вы не мамкин сайт домашний пишите, а приложение миллионов на 5-7 строк кода. Он актуален исключительно в среде теоретиков и джунов, чтобы последние не копипастили один и тот же код в разных классах.
На практике, люди, упоротые этим принципом и не знающие других подходов с огромной болью живут в огромном монолитие с единой dll типа DAL единой dll типа DomainModel и т.д.
Всё это таскается из одного проекта в другой, шарится между десятками сервисов и апи и потом распилить такое на микро сервисы просто невозможно, точнее бизнес не хочет. Цена поддержки растёт кратно. Зато без копирования, ага.

Как нужно делать:
1. Не копировать код в рамках 1 класса и одной, при возможности одной dll.
2. Делать всё в рамках одной фичи. А ля микросервис. Это означает что нет никаких папок с кучей разных репозиотриев а ля Reposotories/AccountRepository и тут же Reposotories/OrdersRepository. А есть 2 фичи (Accounts/ Orders/) внутри которых есть такие репо (Accounts/AccountRepo, Accounts/AccountFactory, Orders/OrderRepo...). В будущем это позволит разделить контексты И если вдруг фиче про ордера нужен доступ к данным из аккаунта, то да, копипастится логика хоть полностью и делается свой репо (Orders/AcountForOrdersRepo… ). Менять её придётся разве что раз в 1000 лет. А вот поддерживать и менять в рамках одной фичи — сколько угодно раз. И нафига тогда нужен такая связанность с Account фичей? Нет уж.
3. По мере разрастания кода — разносить вообще в разные библиотеки (контексты) и репозитории.
А DRY на помойку.

Прежде чем переходить к реализации, убедитесь, что все хорошо продумано.

Это тоже теоретическая чушь, которая на практике сводится к:
1) мы уже делали такое и знаем что примерно нужно сделать ещё раз. Тогда проблемы нет.
2) мы ещё не делали такое и хз что нас ждёт. В этом случае ничего не поможет, ничего не угадать. Например мы на своём проекте несколько лет использовали singlar для для работы множества клиентов с сервером и сервер с очередью через RebbitMQ. В итоге отказались от подхода, как нестабильного, перешли на realtime запрос-ответ. Угадать заранее, фактически без прототипа в продакшене такое было невозможно.
Что же на самом деле лучше сделать в таком случае?
а) Изучить максимум инфы по данной технологии.
б) делать простые небольшие изолированные куски. Потом с увеличением их числа вовремя рефакторить и объединять в контексты. Постоянный рефакторинг — только он поможет избежать факапа. А рефакторинг подразумевает поднятие на уровень выше в архитектуре и её пересмотр в том числе. Когда время пришло.

SOLID
Вот это must have и за его нарушение (чаще всего S) увольнять к чертям. Оно хоть как-то спасает от связанности и роста проблем.

Не создавайте ненужных сущностей без необходимости.

Очередной теоретический бред для джунов, наверное. Сущности всегда создаются в зависимости от контекста и бизнеса. Если у тебя 5 вариантов работы с ордерами и в одном случае нужны одни поля, а в другом — другие и только id + name общие, то это разные сущности. И их нужно создавать. А не гонять одну God object по всему домену. Увеличивая связанность. Если тебе нужно вернуть объект в виде json то не нужно возвращать сущность из предметной области. Пусть она хоть 1 в 1 пока совпадает с DTO объектом. Ключевое слово тут «пока» совпадает.

Фаулер и Макконели верно говорят, что самое дорогое — поддержка. А поддержка дорожает с увеличением сложности. А сложность в том числе берётся и от связанность, из-за невозможности просто удалить и заново переписать кусок. А вдруг кому-то что-то сломает?!

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

+100500.
Именно так.

Браво! особенно по первой части.


не совсем так думаю про:


Не создавайте ненужных сущностей без необходимости.

мне всегда казалось это о другом
Например я работал как-то в одной команде с отличным матиматиком (притворяющимся программистом ;) очень не плохо в целом) который каждую маломальскую сущнусь стремился усложнить по максимому.
Сущность user уже с первых строк кода могла быть реализовнана как целая домення область из user-core, user-address, credentials, user audit, connected apps, payment data
и так со всеми остальными, тоесть в среденм в его коде по сравнению со всеми остальными было почемуто раз в 5 больше ненужных усложнений в виде сущностей.
Слава Богу его можно было убедить словами и рефакторинг он не воспринимал болезненно. Но я всегда впоминал именно этот принцип и его ужасное нарушение. Может я конечно что-то не так понял. ;)

который каждую маломальскую сущнусь стремился усложнить по максимому.

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

Но, если у нас предметная область различается хоть на 1 поле, тогда:
Сущность user уже с первых строк кода могла быть реализовнана как целая домення область из user-core, user-address, credentials, user audit, connected apps, payment data

Это правильно. Хороший контекст и домен превыше всего. Вообще всего. Потому что это залог:
1. минимизации ошибок в реализации
2. минимизации скрытых ошибок и сайд-эффектов
3. возможности передать код след. разработчику, и позволить ему разобраться в нём так, что тот выполнит п.1. и 2.
Можно жить с низкой производительностью — её можно улучшить. Можно жить с техническими багами реализации или недоделками (ну типа нет 100500 валидации на такое-то условие) — их можно исправить. Нельзя существовать с продуктом, которые делает не то, что нужно, да ещё и скрыто. И при этом не позволяет себя исправить ( например исправление только за счёт костылей, что вносит сумятицу и сайд-эффекты. разраб уволился, с ним и знание «а почему так», а код и контекст не говорят почему)

Но конечно, заготовки делать на случай просматривающегося контекста — это тоже зло. Разработка и развитие предметной области сродне лепки из пластилина или глины (обратное резьбе по камню): меся обрастает, потом переосмысление, рефакторинг всего. Если есть опыт, то рефакторинг проходит легко. Если говнокодили в начале, то с болью. Но нужно развивать доменную область, которая отображает фактическую модель систему — а не:
а) изначально запланированную, но которая оказалось избыточной\недоделанной
б) изначально незапланированную, но вылепленную без «развития», а потому таскающую за собой кучу легаси свойств и зависимостей из других контекстов, которые поленились создать\не поняли что надо создать.

почемуто раз в 5 больше ненужных усложнений в виде сущностей.
Слава Богу его можно было убедить словами и рефакторинг он не воспринимал болезненно.

Ну это и есть то самое развитие. Насоздавал. Понял что 5 из 8 сущностей лишние или дубли — удалил. Это норма.
Если рефакторинг перед началом каждой новой задачи, во время изменения куска кода или фикса бага то и нет проблем с поступательным развитием. А если рефакторинг — это плановая задача «вернуть тех. долг», то всё, считай нет и не будет его никогда.

ЗЫ Сори, меня раз в месяц комменты работают.

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

Ну тут в статье single responsibility сформулировали ровно так, как он звучать не должен (исходя из слов самого дяди Боба), аналогично и DRY.
В самой упомянутой книжке четко написано — далеко не любое дублирование кода нарушает DRY. И приводятся конкретные примеры когда это не так. Нарушение DRY — это не дублирование кода, это дублирование информации.


Ну это и есть то самое развитие. Насоздавал. Понял что 5 из 8 сущностей лишние или дубли — удалил. Это норма.

Не создавать то, в пользе чего не уверен, гораздо более оптимальная стратегия, чем сперва создать а потом удалять на рефакторинге. Вообще, добавить что-то почти всегда сильно проще, чем избавиться от ненужного, поэтому если необходимость чего-то не обосновано, то и писать это по умолчанию не следует, как бы ни хотелось из соображений "ну потом та надо будет!!!1!".

Нарушение DRY — это не дублирование кода, это дублирование информации.


Тем ни менее это тоже не совсем верно. Я бы сказал нельзя дублировать контексты, но не их части. Где контекст предметной области — это определённая фича с её нюансами и правилами, а части — это конкретные данные и доступ к ним, реализация правил и ограничений, алгоритмы. Вот конкретные данные и алгоритмы можно и нужно дублировать. А контексты — нет. Информации, данных, нужно ровно столько, сколько её нужно в рамках предметной области, контекста или суб-контекста. Если нужно одни и те же данные в двух сервисах дублировать, значит нужно дублировать, а не шарить код. Если можно не дублировать (например, очевидна перспектива вынесения общего сервиса), то нужно не дублировать. Но в жизни не очень грамотными разработчиками принята за аксиому и священную корову норма, что дублировать «низя и точка». От сюда на практике случаев общих библиотек предметной области или DAL в разы больше, чем случаев проблем из-за дублированной инфы.

Итого, весь принцип DRY является высосанным из пальца неуклюжим определением, попыткой реально сложную неочевидную вещь объяснить на пальцах, сделав только хуже. Ни чета определением из той же физики. Одно дело объяснить папусу, почему земля круглая, а другое дело заставить его после этого строить ракету или пойти в кругосветку, обладая только знанием, что земля круглая. Просто автор DRY, Д. Миллер, сам не очень хорошо понимает то, о чём пишет. А после этого ещё хуже интерпретируют читатели. А сводилось всё к тому, что должен быть 1 файл конфигурации в 1 месте для одной системы.

Не создавать то, в пользе чего не уверен, гораздо более оптимальная стратегия, чем сперва создать а потом удалять на рефакторинге.


Видимо мы про какие-то разные ситуации говорим. Вы, стало быть, про «создание впрок» или нечто подобное. Но т.к. рефакторинг происходит постоянно, то сложно даже прочертить границу когда нужно создавать. Сейчас или через час. Понятное дело, что создавать сущности которые через неделю наверное понадобится — это бред. Но опять же программирование, как живопись или скульптура, процесс постоянных изменений, добавления объёма и формирование формы. А потому рефакторинг — это часть написания кода и добавить во время разработки сколько надо сущностей, половину потом удалить потому что предметная область обрела новые детали и вырисовалась новая форма — это и есть единственно правильный и оптимальный подход.Это то, о чём я говорю. В противовес ему я знаю только 1 вариант: всё запланировать и расписать заранее(водопад), вплоть до классов и методов, но потом с этим г. невозможно просто работать и от этого все нормальные компании давно отказались. Вариант же «добавлять по мере необходимости» и есть часть моёго подхода. Просто необходимость меняется с прорисовкой детали и там где у тебя был 1 класс (сущность), может появиться 3, но потом из-за тех. деталей, выявлений общего поведения чего-то ещё, може остаться в итоге 2 класс. ну и т.д. Это просто нюансы.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий