YAGNI и DRY - Поцелуй смерти для вашего программного проекта

Узнайте, почему популярные программные мантры, такие как YAGNI, DRY и KISS, могут быть столь же разрушительными, сколь и соблазнительными.

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

Кто из нас не слышал людей и не рассказывал людям YAGNI, DRY или KISS? Это популярные мантры, потому что при правильном соблюдении они работают, чтобы направлять и подталкивать мышление к более эффективной разработке и программированию.

Однако у них есть и обратная сторона.

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

С ними трудно спорить, потому что с философской точки зрения эти обобщенные утверждения верны. Мы хотим им верить. Мы должны им верить. Если им не верить, возникает ощущение, что они не разработчик. Это затрудняет их оспаривание, в сочетании с тем фактом, что они содержат только самые широкие истины и не применимы в каждой ситуации.

KISS - Будь проще, глупо

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

Может быть сотня способов реализовать любое одно требование. KISS подразумевает, что самый простой метод часто оказывается лучшим с точки зрения сложности, скорости и стоимости.

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

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

Что с этим не так?

Темная сторона KISS заключается в том, что он может вести вас по пути минимума, который, если применять его с течением времени, в конечном итоге приводит к некачественным результатам.

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

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

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

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

ЯГНИ - Тебе это не понадобится

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

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

ЯГНИ - это мантра, которая действует как противовес на пути бесконечного «а что, если?» вопросы, которые инженеры могут решить. Это предотвращает сползание объема, возникающее из-за попыток решить проблемы неопределенного будущего, которые лучше оставить для решения, когда они действительно возникнут (если они когда-либо возникнут).

Что с этим не так?

У YAGNI есть темная сторона. Это часто используется инженерами как причина недостаточной проработки в ошибочной попытке оправдать небрежную работу туманными обещаниями непроверяемого увеличения скорости разработки.

Как узнать, применяется ли он неправильно? Когда YAGNI используется как причина, по которой что-то НЕ делать, самое время задать себе несколько вопросов:

  • Используется ли он, чтобы избежать решения проблемы, присущей домену?
  • Используется ли он, чтобы избежать разработки чего-то, что является основополагающим для продукта или программного обеспечения (например, авторизация для веб-приложений)?
  • Выигрывает ли скорость, избегая отслеживания дополнительной работы, чтобы убедиться, что она действительно приводит к более быстрой разработке?
  • Действительно ли затраты на его реализацию или внедрение столь же дороги, как предполагалось?

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

Рассказ о очень подробном проекте

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

Команда не решалась создавать классы или даже переносить код в функции. Они считали это чрезмерной инженерией и кричали «YAGNI»: зачем переносить код в функцию, если она не будет вызываться ничем другим? Зачем создавать абстракции, которые нам не нужны, когда копирование и вставка выполняется намного быстрее?

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

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

Чаще всего эти детали не имеют значения.

Альтернатива - Вам это понадобится

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

Помните - ценность плана в планировании. Заставить себя думать обо всех «а что, если?» поможет вам не загнать себя в угол, который помешает развитию кода для поддержки меняющихся требований. Это не значит, что вам нужно делать все сразу - вы все равно можете двигаться маленькими, постепенными шагами.

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

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

СУХОЙ - Не повторяйся

DRY - это не делать одно и то же снова и снова, снова, и снова, и снова, и снова. Это побуждает разработчиков думать об общих чертах, а не только о функциях автоматического копирования и вставки.

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

Что с этим не так?

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

Эта непреднамеренная глобализация ранее локализованных данных может привести к множеству негативных последствий.

Сказка о пользователе

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

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

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

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

Источники истины для этих данных должны были быть совершенно разными, но они были СУХИМИ и объединены.

Альтернатива - повторить себя

Всякий раз, когда вы храните или используете фрагмент данных или пишете код, всегда задавайте себе следующие вопросы:

  • По каким причинам этот код или данные могут измениться и применимы ли эти причины к данной ситуации?
  • Какие варианты использования используют этот код или данные, и достаточно ли универсален этот общий фрагмент, чтобы соответствовать обоим случаям, не влияя ни на один из них?
  • Какие заинтересованные стороны будут запрашивать изменения этой функциональности, и могут ли они одновременно быть правы и не согласны?

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

Урок

Будьте осторожны в применении мантр. Хотя они могут помочь направлять мышление и являются полезными практическими правилами, они никогда не задумывались как догмы.

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