Development

Мины замедленного действия

(В оригинале – The Road to Performance Is Littered with Dirty Code Bombs)

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

Предположим, вы нашли «узкое место» в коде. И для оптимизации решили заменить алгоритм нижележащего уровня. И допустим, вы оценили необходимое время часа в 3-4, о чем и доложили менеджеру. Однако после успешной замены алгоритма вы вдруг обнаруживаете, что перестала работать другая часть системы, зависящая от измененной. Возможно, вы предвидели и это (связность блоков на один шаг вполне можно предвидеть), но что, если после исправления этой части сломается что-нибудь еще? И чем далее от первоначального места будет продолжаться эта связность, тем ниже шансы, что вы ее обнаружите и учтете в оценке требуемого времени. И внезапно может оказаться, что реально вы потратите не 3-4 часа согласно первоначальной оценке, а 3-4 недели. Не такая уж и редкость наблюдать, как для завершения «быстрого» изменения в результате требуется несколько месяцев. И такая ситуация легко может сильно подорвать доверие к команде. Этого можно было бы избежать, будь у нас в руках инструмент, позволяющий оценить риск такого развития дел.

К счастью, существует множество способов контролировать степень и глубину связности и сложности кода. Метрики кода используются для подсчета тех или иных свойств кода. Значение этих метрик коррелирует с качеством кода. Для измерения связности применяются две метрики: fan-in и fan-out. Рассмотрим fan-out для отдельно взятого класса: эта метрика является количеством классов, на которые явно или неявно ссылается выбранный класс. Иными словами, это количество классов, которые должны быть откомпилированы прежде, чем откомпилируется ваш класс. Метрика fan-in, наоборот, показывает, сколько классов зависит от выбранного класса. Зная обе метрики, fan-in и fan-out, мы можем вычислить коэффициент нестабильности: I = fo / (fi + fo).

Чем ближе значение этого коэффициента к 0, тем стабильнее код. Чем ближе значение к 1, тем код нестабильнее. Чем стабильнее код, тем проще его менять, и наоборот, чем код нестабильнее, тем больше в нем «мин замедленного действия». И цель рефакторинга – это уменьшение значения коэффициента нестабильности.

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

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

Автор оригинала – Kirk Pepperdine