Или как всё сломать, потом починить, но так ничего и не понять

Есть у нас погромист. Хороший погромист, деятельный и результативный. Но вот с коммуникациями не всегда всё в порядке. Есть куда расти, так сказать.

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

И тут среди этого потока информации проскакивает: “ну, ещё я там в модели лишние поля поудалял; теперь вот бизнес-логику пишу, пулл реквест отправил”.

Стоямба” — говорит другой бэкенд-разработчик — “Как удалил? Что удалил? Зачем??

Начинается разговор. Модель, де, сделана криво, какие-то дублирования полей, да и сущности не хватало. И вообще надо на фронт отдавать не две разных сущности на одной странице — а вообще третью, которую вот только что добавил. Теперь всё красиво, фаулероверно и природосообразно.

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

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

Допустим, но зачем тащить её на фронт? Как потом объяснять клиенту, что он в админке редактирует не основные сущности домена, а какую-то вспомогательную хрень? И зачем менять то, что работает, когда у нас сраки горят и планы уже дважды сдвинулись? Нас же за причинные места подвесят, если мы снова релиз въ***м!!

Ойвсё, отвечает, если вы так хотите — сделаю, как скажете. Всё откачу взад-назад и перепишу заново. Хотя вообще-то вы не правы.

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

Обычный, казалось бы, холивар, так любимый разработчиками.

И действительно — ну какая, нафиг, разница, как там что реализовано в базе? Функциональность же не страдает. Система может работать так — а может работать эдак. Можно точно так же развести срач по поводу того, что использовать для чатов — классические вебсокеты или socket.io, и это не будет иметь никакого особого смысла. Ну, покуда не окажется, что на проде надо балансировать нагрузку на бэке, разнеся его на несколько машин, а socket.io такой схемы развёртывания из коробки не поддерживает. В общем, холивары — они такие холивары, без дополнительных входящих данных часто смысла не имеют. А по большей части не имеют смысла вовсе.

Но почему-то меня эта тема зацепила очень серьёзно. Захотелось как-то донести до погромиста — не то, что он дурак и ничего не понимает, как это обычно происходит в срачах и холиварах — а почему конкретно его действия были в данной ситуации не вполне верными, и как бы надо было действовать по-хорошему, чтобы срача не произошло. Как и двухдневного переписывания только что написанного кода.

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

Давайте рассмотрим следующие моменты:
  1. Изменение модели в рамках рефакторинга.
  2. Изменение модели без обсуждения с командой.
  3. Изменение модели, основанной на логике домена.
  4. Создание промежуточной сущности, отсутствующей в домене.
  5. Подпихивание на фронт промежуточной сущности вместо сущностей домена.

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

Давайте же разберём их по порядку.

  1. Изменение модели в рамках рефакторинга.

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

Лично я тут никакого принципиального косяка не вижу, покуда этот пункт не отягощён другими входящими обстоятельствами.

  1. Изменение модели без обсуждения с командой.

А вот это, товарищи, залёт. Сразу же, без вдавания в подробности. Когда ты пишешь код один — без проблем, меняй что хочешь в коде, который ты контролируешь на все сто процентов. Про сто процентов — это, конечно, ирония. 😉

Но в целом отвечать ведь тоже только тебе, так что если что — сам себе злобный Буратино.

А вот когда ты работаешь в команде — ээээ, брат… Тут серьёзные изменения в структуре кода могут повлечь очень неожиданные эффекты. Куда бОльшие, чем просто баги. Если система ВНЕЗАПНО меняет свою структуру, то элементарно на осознание происшедших изменений у других разработчиков может уйти времени существенно больше, чем на сами изменения. Более того — резко возрастает вероятность, что это не окружающие — идиоты, криво спроектировавшие модель. (Хотя, безусловно, любой погромист — весь в белом, а кругом дураки, это по умолчанию так у большинства, тут даже сокрушаться по этому поводу бессмысленно.) Может оказаться, что это просто ты, дорогой, не разобрался и не понял, почему всё устроено именно так, а не иначе.

Короче, так делать нельзя. Опасно — и точка.

  1. Изменение модели, основанной на логике домена.

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

  1. Создание промежуточной сущности, отсутствующей в домене.

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

Надо сделать промежуточную сущность, которая облегчит реализацию доменной логики? Фигачь. Не забудь потом при разговоре с клиентом переводить со своего внутреннего (псевдо)доменного языка на чистый доменный язык. Чтобы у него голова не пухла от каких-то служебных таблиц и непонятных временных хреней, сделанных для твоего удобства.

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

В общем, делать это надо с большой осторожностью.

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

  1. Подпихивание на фронт промежуточной сущности вместо сущностей домена

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

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

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

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

447 451 Жизненный Опыт Николая Пасько