вторник, 19 июля 2011 г.

Разработка больших систем. Часть 5. Про хаки и рефакторинг.

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



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

if(“admin”.equals(username)) {

showError(“Can't delete admin”);

return;

}


Как известно, в СССР секса не было.

Аналогично, в идеальной системе нет хаков.

Потому, что в идеальном мире:

· Есть неограниченное количество времени, для проведения любого количества рефакторингов

· Не существует сроков, при нарушении которых, пропадает всякий смысл в дальнейшей разработке

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

За последние 15 лет, мне такие проекты, к сожалению, не попадались.

Поэтому, скажу крамольную вещь: в реальных проектах хаки имеют право быть.

При этом, аналогично «плохим» и «хорошим» багам, существуют «плохие» и «приемлемые» хаки. Для поддержания большой программной системы в стабильном состоянии, важно уметь отличать одни от других: стабильные системы не содержат «плохих» хаков.

Плохие и приемлемые хаки

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

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

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

Так вот приемлемым будет только такой хак, который ЯВНО СЛОМАЕТСЯ при выполнении любого из таких условий. «Явно сломается» - значит жестко упадет один из основных use-кейсов, и это не сможет пройти незамеченным для тестировщиков.

Приведенный выше пример является неприемлемым хаком, поскольку он обнаружится лишь при попытке удалить последнего администратора. Тот же самый хак можно сделать примлемым, если перед этой проверкой добавить еще одну:

if(!accountExists(“admin”)) {

throw new RuntimeException(“No admin exists”);

}


или лучше


assert(accountExists(“admin”));


Очевидно, хаки все равно не украшают код и не повышают стабильность системы. Поэтому, в любом случае их необходимо явно помечать (например тэгами //TODO или //FIXME) , и планировать их замену на качественный код в будущих релизах.

Энтропия и рефакторинг


Два факта:

1. Попытки немедленно уничтожать каждый приемлемый хак приводят к неприемлемому удорожанию проекта

2. Чрезмерное увеличение количества приемлемых хаков приводят к переусложнению кода и резкому снижению его понятности

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

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

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


Комментариев нет: