Всё, что я добавлял, было разумным. Вместе это меня погребло.
Почти всё, что я когда-либо добавлял в этот проект, в момент добавления было совершенно разумным дополнением. У каждой функции было реальное обоснование. Каждый дополнительный случай, который я обрабатывал, был случаем, который действительно возникал. Каждое маленькое улучшение что-то улучшало. И суммой всех этих по отдельности здравых добавлений стала система настолько тяжёлая, настолько запутанная и настолько раздутая, что она едва могла сдвинуться с места.
Тревожно здесь то, что никто никогда не решал сделать её такой. Не было ни одного момента дурного суждения, на который можно было бы указать. Она просто наросла, по одному вполне оправданному решению за раз, превратившись в нечто, что никто и никогда не выбрал бы намеренно.
Каждое добавление оправдано локально
В этом и суть того, почему расползанию охвата так трудно сопротивляться: оно никогда не приходит как одно плохое решение. Оно приходит как длинная, непрерывная череда хороших. Каждая новая функция полезна. Каждый дополнительный краевой случай реален. Каждое улучшение в духе «раз уж я всё равно здесь, заодно сделаю и» имеет подлинный смысл в тот момент, когда вы его делаете. Вы ни на одном отдельном шаге не делаете того, что могли бы распознать как неправильное.
Именно это и делает процесс таким коварным. Если бы расползание охвата ощущалось как ошибка в момент, когда вы его совершаете, вы бы остановились. Но оно так не ощущается. Оно ощущается как добросовестность, как тщательность, как отзывчивость, как созидание. Каждое отдельное «да» легко защитить, и урон наносит не какое-то одно из них, а сам факт того, что вы продолжали говорить «да», разумно, очень долгое время.
Цена, которую не видно в момент добавления
Учёт подтасован, и подтасован вполне определённым образом. Когда вы что-то добавляете, выгода ярка и непосредственна — вы в точности видите, что она вам даёт. А её цена в момент решения почти невидима, потому что большая часть этой цены ещё не наступила.
Ведь каждое добавление несёт текущие издержки, которые приходят позже и тихо. Больше поверхности. Больше взаимодействий между частями. Больше того, что может сломаться. Больше того, что должен понять любой, кто прикоснётся к системе, включая вас в будущем. Больше того, что придётся поддерживать, всегда. Выгода — это разовый, видимый выигрыш. Цена — это постоянный, невидимый налог, выплачиваемый маленькими взносами ещё долго после того, как решение забыто. Поэтому в момент выбора видимая выгода почти всегда перевешивает видимую цену — не потому, что сделка хороша, а потому, что половина цены скрыта от вас в тот самый момент, когда вы делаете выбор.
Локально разумно, глобально — каша
Конечное состояние всего этого — система, в которой каждая отдельная часть оправдана, а целое представляет собой катастрофу. Это безошибочная подпись нарастания, и у него есть жестокое свойство: нет ни одной вещи, на которую можно указать как на ошибку. Ошибка — это само накопление, размазанное по сотне отдельных решений, каждое из которых, взятое в отдельности, было совершенно нормальным.
Столкнуться с этим по-настоящему дезориентирует, потому что весь ваш инстинкт решения проблем построен на том, чтобы найти плохую часть и починить её. Здесь же плохой части нет. Вы идёте искать компонент, который всё испортил, и не можете его найти, потому что ни один компонент не испортил всё — все они испортили понемногу, вместе. Невозможно «отладить» себя из проблемы, причина которой равномерно распределена по всему, что выглядит по отдельности разумным.
Дрейф всегда указывает в сторону «больше»
В основе этого лежит своего рода гравитация, которая в любом проекте устойчиво указывает в одном направлении: в сторону добавления. Добавлять — это ощущается как прогресс. Это видно, это приносит удовлетворение, это производит артефакты, которые можно увидеть и на которые можно указать. Строить больше — это ощущается как работа, потому что так оно и есть.
Вычитание ощущается противоположностью всему этому. Удалить что-то — это ощущается как потеря, как отмена усилий, как движение назад. И, что критически важно, оно никогда не ощущается срочным — ведь ничего не ломается в тот момент, когда вы не удаляете что-то. Цена невычитания невидима и отложена, ровно как и цена добавления, а значит, никогда нет принуждающей силы. Поэтому в отсутствие сознательного сопротивления система только накапливает. Дрейф однонаправлен, и итог по умолчанию, если дать ему идти своим чередом, — погребённая, неподъёмная каша.
Вычитание — это сознательная и неприятная борьба
Удалять вещи оказывается куда тяжелее, чем добавлять, и в основном по причинам, которые не имеют ничего общего с трудностью и всё имеют общее с психологией. Когда вы что-то удаляете, вы уничтожаете работу, которую кто-то проделал, — зачастую вы сами. Вы молчаливо признаёте, что этого не должно было быть. В этом нет приятного чувства творения, нет нового артефакта, которым можно полюбоваться, нет той маленькой награды, которую даёт добавление. Это чистая, негламурная, слегка болезненная отмена.
Но готовность всё равно это делать — вырезать функции, убивать компоненты, которые больше не оправдывают своё место, удалять то, что прекрасно работает, но не стоит своего веса, — одна из немногих сил, способных противостоять неумолимому дрейфу в сторону неуправляемости. Вычитание никогда не происходит само собой. Оно происходит лишь тогда, когда кто-то решает, вопреки каждому удобному инстинкту, бороться за него.
Сказать «нет» — это само по себе функция
Переосмысление, которое помогло больше всего, состояло в осознании, что некоторые из самых ценных проектных решений, которые я когда-либо принимал, были тем, что я решил не делать. Каждое разумное добавление, от которого вы отказываетесь, — это вес, который вам никогда не придётся нести, поверхность, которую вам никогда не придётся защищать, сложность, за которую вы никогда не будете платить во все последующие месяцы.
Ясное понимание того, чем проект не является, оказалось ровно настолько же важным, как и понимание того, чем он является, — и куда труднее удержать его, потому что поддержание означает раз за разом отказываться от вещей, которые звучат по-настоящему хорошо. Каждое исключение — маленький, непрерывный акт сопротивления вполне здравой на вид идее, и вам приходится совершать это сопротивление снова и снова, вечно, без какой-либо награды за него, кроме отсутствия проблемы, которую вы никогда не увидите и которой избежали. «Нет» не оставляет артефакта. Именно поэтому оно так недооценено и так необходимо.
Более глубокий урок: защищать целое от частей
Всё сводится к тому, что я оптимизировал каждое решение локально — хорошо ли это конкретное добавление? — тогда как вопросом, который на самом деле определял судьбу проекта, был глобальный: что это делает с целым? Это разные вопросы, и ответы у них различаются гораздо чаще, чем я предполагал.
Система — это не просто сумма её локально хороших частей. У неё есть собственное здоровье, собственный вес, собственная связность — свойства, которые принадлежат целому и за которые не отвечает ни одно отдельное решение, но на которые влияет каждое. Оберегать это целое от устойчивого и по-настоящему разумного потока просьб добавить ещё всего одну вещь — вот в чём, как оказалось, и состояла большая часть реальной работы. Я думал, что моя работа — принимать хорошие отдельные решения. На самом деле она состояла в том, чтобы защищать систему от накопленного веса сотни таких решений.
— Никаких сигналов, никакой доходности, не является инвестиционной рекомендацией.