Jun. 8th, 2023

amarao: (Default)
Одно из самых сложных и повреждающих действий в проекте - повышение сложности проекта без должной отдачи.

Когда человек сталкивается с новым требованием в проекте, он открывает код, ищет, куда что дописать. Находит. Дописывает. Фича готова. Если проект достаточно покрыт тестами, то старые фичи/юскейсы не сломаны. Задача сделана, можно сказать, на отлично.

... Но в глубине...

В каждом месте, где он дописал, изменение, грубо говоря, можно свести к:

* всегда делать что-то (добавлять timestamp к сообщению). Сложность не изменилась, точнее, изменилась на несколько строчек. С точки зрения необоснованной сложности вопросов нет. Могут быть вопросы по дублированию кода (если одна и та же строчка получения/форматирования времени появилась в нескольких местах).
* Делать что-то по условию (если у нас есть фичефлаг 'timestamp', добавлять timestamp). Был линейный код, теперь у нас ветвление. Маленькое или большое - но ветвление. В декартовом произведении состояний приложения всё удвоилось.
* Делать что-то по условию в ветвях условий. Если это одно и то же, то это просто дублирование кода и предыдущий случай, если же это разные действия, то мы получаем нарушение инварианта, в котором, возможно, есть не покрытые тестами ветки.
* Добавить трекинг фичефлага или "режима", или "глобальной переменной". Теперь весь (или существенная часть) кода параметризирована, и, возможно, имеет необходимость отвечать на вопрос "что делать в этой ситуации" даже там, где фича не нужна или не имеет смысла.
* Вызывать распространяющиеся изменения (например, фичефлаг - линейный код в месте использования, но новый код вызывает расползающиеся изменения в компонентах, которые зависили от старого кода, включая "накладывание" эффектов идущих по разным ветвям кода на другой код, который вынужден вместо одного "да/нет" уметь реагировать на комбинацию действий разных ветвей кода (А: да, Б: нет; А: да, Б: да, А: нет, Б: да, А: нет, Б: нет).
* Вызвать появление нескольких версий интерфейсов или нарушение контрактов интерфейсов из-за появления вариантивности из-за фичи, включая необходимость думать о ковариантности или контр-вариантности (паталогический случай: когда в код передают сущность (коллбэк, замыкание), ожидающую объект с фичей или без фичи как параметр); особо тут обстоит вопрос с контрактами для внешних потребителей.
* Вызывать нелинейные сайд-эффекты, проявляющиеся через нетипизированные изменения среды исполнения (блокировки из-за чрезмерно активной записи, переполнения, etc).


И всё это выглядит как feature done, но последствия для проекта совершенно разные.


А вот заметить это глубинное преступление очень трудно. Feature done? Ну да, пришлось добавить matrix, ну да, мы теперь с помощью if'а вычисляем зависимости вместо линейного списка, у нас появилась ещё одна переменная, которую по Глубокой Причине надо выставлять в явном виде и помнить про её существование всем остальным вокруг.

Если это всё немного обобщить, то преступления тут нескольких видов:

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


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

Profile

amarao: (Default)
amarao

August 2025

S M T W T F S
     12
345 6789
10111213141516
17181920212223
24252627282930
31      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 13th, 2025 08:29 pm
Powered by Dreamwidth Studios