Антипаттерналии I. О конструктивной и деструктивной лени
Yaroslav FedevychОпубликовано 17.04.2007 в Разработка, Управление проектами, статьи
…или «Не трогай то, что работает» vs «Не ремонтируй то, что не сломано»
С возрастом и временем приходит понимание того, что эффективность труда повышают обычно даже не ради непосредственных результатов труда. И не ради самого труда же. Главная цель, к которой человек стремится в своей карьере — получать как можно больше, делая как можно меньше. То, что лень двигает прогресс, является общеизвестным фактом.
Как ни странно, в то же время то, что лень является одним из смертных грехов, тоже никто не отменил. Нижеследующим я постараюсь согласовать это противоречие, равно как и показать тонкую разницу между утверждением «не трогай то, что работает» и «не ремонтируй то, что не сломано».
Одной из практик в разработке, которая показала себя с хорошей стороны, является постоянный рефакторинг. Когда в систему добавляется новый компонент, обычно он вносит некоторые коррективы в целостную картину, которая была задана предыдущим вариантом системы. Другие компоненты согласовываются с новым пониманием проекта и новыми требованиями к нему, чтобы опять-таки получить столь же целостную картину. Приятным побочным эффектом является то, что код не тухнет от старости и не превращается в священную корову, которую трогать нельзя.
В суровой практике, однако, часто мы наблюдаем совершенно другое. На каждый компонент разрабатываемой системы обычно выделен фиксированный бюджет, в результате чего после того, как он был объявлен работающим, а его квота времени исчерпана, опять лезть в его внутренности трудно. Менеджеру проекта будет трудно отчитаться перед заказчиком в том, что время ушло на «доработки» компонента, готовность которого заявлялась месяц тому назад. Списывание потраченного времени на что-либо другое ничем не лучше, потому что в результате легко попасть под обвинение в некомпетентности и неумении держать слово.
Поэтому новые компоненты внедряются в систему уже не с целью поднять всю систему, а с целью не сломать то, что уже кое-как работает. И даже если были допущены серьезные ошибки проектирования, новые компоненты будут скорее подгоняться под них, чем эти ошибки будут исправлены.
Обычно, когда разработчик объясняет менеджеру порочность данного подхода, тот ему отвечает: «Это ведь займет слишком много времени! С другой стороны, старый код ведь работает, с чего ты взял, что проблема именно в нем? Нет, лучше адаптируй новый код так, чтобы все работало. Это займет не так много времени.»
Многим из нас известен конец истории, а кое для кого эта история продолжается до сих пор. Потом, когда что-нибудь неизбежно ломается, нужно лезть в код годичной давности, анализировать огромную систему, тратить целые недели на погоню за ошибками. Нельзя также сказать, что заказчик в восторге от этого и готов оплачивать такое времяпровождение, поэтому его отношения с менеджерами начинают натягиваться, соответственно у менеджеров — с разработчиками.
Иногда источником столь порочного мышления является сам разработчик. Ведь он написал работающий (кое-как) код, зачем его исправлять? Зачем тратить время на то, на что время уже потрачено? В конце концов, стремление к извечной цели получать все, ничего не делая, берет верх. Уже потом действительность показывает, что разработчик сам себя «развел» на лишнее рабочее время.
С другой стороны, стоит подход «не ремонтировать то, что не ломалось». Казалось бы, это то же самое. Но на самом деле здесь добавляется одно условие: не ремонтировать только, если не ломалось. Это необязательно означает, что все, что не работает — сломано, а все, что работает — не сломано. Здесь другой критерий: ездить на автомобиле можно и тогда, когда покрышка лопнула, и когда под капотом стучит. В известной мере автомобиль работает. Вопрос лишь, сколько времени ему работать в таких условиях осталось и с какими последствиями.
Как соотнести наш пример с программным обеспечением?
Если слово workaround применяется в контексте компонентов, не разработанных третьей стороной, то разрабатываемое ПО сломано. Если при добавлении четвертого компонента первый перестает работать, как описано, он сломан. Если у объектов различное представление об общей модели данных, с которой все они работают, они сломаны. Если нужно поднять годичной давности собственный код, и нужно долгое время разбираться, как же он работает, то он сломан.
А сломанное нужно ремонтировать, не так ли?
А теперь сопоставим постоянный рефакторинг с описанной ситуацией. В случае с рефакторингом железо куется, пока горячо. Компоненты адаптируются друг под друга, когда их не так много, они не должны зависеть от допущенных при программировании ошибок и от ошибочных допущений о модели ПО: ее можно подстраивать в меру возрастания собственного же опыта, как глобального, так и в отношении разрабатываемой системы. Баги не нужно обзывать фичами, а исправлять тогда, когда это легко.
И этот подход работает на конструктивную лень. В конце концов, чуть больше усилий, приложенных сейчас, сэкономят уйму времени потом, если суметь посмотреть чуть дальше кончика собственного носа в будущее. Конструктивная лень на самом деле является рациональным желанием не прилагать ненужные усилия, деструктивная — желанием не прилагать усилий вообще.
P. S. Конечно же, разработчик не должен превращаться в трудоголика с подходом «Если не сломалось, ремонтируй, пока не сломается». Но это уже совсем другой способ неэффективно расходовать свое время.
Понравилась статья? Подпишись на обновления по RSS/E-mail



Очень правильно все написано. Я бы добавил, что рефакторить нужно периодически хотя бы для того, чтобы не забывать, как там все внутри устроено.
Главное перебороть страх изменений - с системой контроля версий, в случае чего, все можно отрефакторить назад в два счета 
Если кратко - “Рефакторинг полезен”
Ни одна статья, развивающая данный тезис не даст ровным счетом ничего, если именно этот тезис считают неправильным/противоречивым/неактуальным/небезопасным. “Считают” означает “считает кто-то из участников проекта, и никто другой ему не прочищает мозги по этому поводу”. И неважно кто это - разработчик, менеджер, представитель заказчика, инвестор… Важно то, что:
А. Он ошибается.
Б. Ему это разрешают делать.
Можно долго обсуждать меру полезности/эффективности конкретного рефакторинга в конкретном проекте на конкретном этапе. И даже если рефакторинг громадного куска кода на выходе дал тот же результат, никто не отнимет опыта, который получит разработчик

“Чинить пока не сломается” - это уже не разработка ПО, и за такое никто, в конце концов, денег платить не будет. Так что рано или поздно каждый разработчик/менеджер/заказчик находит для себя ту меру, которая определяет его понимание полезности/эффективности рефакторинга (опять же, в конкретных условиях). Лучше, если рано
Ну, про це можна з десяток статей написати, до речі, планується.
По-моему, это часть опыта разработчика ПО - понимать, когда следует рефакторить, а когда нет.
как же эта ситуацию знакома
Это скорее удовлетворение своего “я”. Раз я не поковырялся в коде, значит, код плохой. Исправить надо. У всех код sucks, кроме меня.
Мартин Фаулер и Джошуа Кириевски советуют приступать к рефакторингу
в том числе и тогда, когда добавление функциональности затруднено.
С этим сложно не согласиться, т.к. время потраченное на рефакторинг можно
списать, как потраченое на добавление фич.
Во всем должно быть рациональное зерно. Писать надо изначльно красиво, аккурано и гибко, чтоб потом изменения вностились с минимальной кровью. С другой стороны не всегда рефакторинг полезен - лично принимал участие в проектах, написанных мной же, но очень давно, где надо было просто поддерживать систему и ее развития в будущем не предвиделсь. Если рефакторинг и производился то локальный.
У КАЖДОГО ПРОЕКТА ЕСТЬ СВОЕ ВРЕМЯ ЖИЗНИ! После этого он навсегда умирает и ему на смену приходит абсолютно новый, более новый, навороченный и изящный.
С программистами таже беда, что и с всем извесным художником, которого не пускали на свою же собственную выставку с красками и кистью, что б он там часом ничего не подправил. Каждый менеджер должен чувствовать момент, после которого он должен сказать - “Стоп! На этом мы ставим точку.”
Зачастую например более продвинутые и изящные решения для часто-повторяемой проблемы(патерн) лучьше не вносить в написанный и работающий проект, если старый патерн работает без нареканий. Это может вообще развалить проект, т к новое решение не оттестировано к томуже не вписывается в целостную архитектуру устаревшей системы, что внесет хаус. А вот старое работает годами, вписывается в архитектуру и есть куча народу которые знают как его использовать и чинить. поэтому доля консерватизма в принячтии решений по рефакторингу должна присутсвовать. Не забывайте в конце концов что за все это комуто придется платить…
Так что