Лучшие практики, несмотря на термин, не всегда хороши. В программировании многие из них не оправдывают своего названия. Они распространяются не благодаря своим заслугам или доказательствам эффективности, а из-за эффекта авторитета и использования обществом. По мере их распространения теряются нюансы. А с потерей нюансов становится легче заниматься их евангелизмом. В сочетании с нехваткой опыта это может привести к возникновению культа лучших практик. Представьте команду, которая одержима их использованием — скажем, разработкой через тестирование (test-driven development) или написанием пользовательских сценариев, — до такой степени, что это уже вредит. В эту ловушку попадали многие, в том числе и я.

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

Самозваные лучшие практики


Главная причина, по которой некоторые лучшие практики в программировании приносят вред, заключается в том, что они вовсе не являются лучшими. Взгляните на официальное определение: «лучшая практика — это способ или методика, которая общепризнана лучше любой другой альтернативы, поскольку даёт более высокие результаты по сравнению с другими методиками [...]». Здесь ключевое — «общепризнана» и «лучше любой другой альтернативы».

Проблема многих лучших практик в программировании заключается в том, что они притворяются, будто соответствуют этому определению, хотя это не так. Некоторые практики не являются общепризнанными. Они происходят из различных, менее надёжных авторитетных источников. Подобным источником может быть отдельный человек или какое-то сообщество, которое представляет какую-то практику как общепринятую, хотя это лишь их собственный опыт или мнение.

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

Некоторые лучшие методики не дают наилучших результатов. Утверждается, что дают, но объективно выходит на уровне альтернативных решений. Например, функциональное программирование лучше объектно-ориентированного? Мы не можем утверждать, что одно лучше другого, хотя для каждой из парадигм найдутся те, кто будет выдавать их за лучшие практики.

Проблема превосходства заключается в том, что в большинство лучших практик в программировании не имеют доказательной базы. Программирование — слишком молодая сфера деятельности, она слишком быстро меняется и чересчур сложна для исследований ради получения доказательств стабильно более высоких результатов каких-то подходов. Мы работаем в мире мнений, ощущений и непроверенных сведений.

Некоторые лучшие практики ещё и очень изменчивы. Быстро развивающиеся языки и фреймворки предлагают какую-нибудь лучшую методику, а на следующий год превосходят её. В этом нет ничего плохого, но это показывает, как быстро меняется наше представление о лучшем, хотя понятие лучшей практики подразумевает проверку временем. Например, посмотрите на сообщество JavaScript и какого-нибудь популярного фреймворка вроде React. Поскольку React быстро развивается и люди набираются опыта в работе с ним, рекомендации его разработчиков могут стремительно устаревать и заменяться другими подходами. Вспомните, как быстро хуки заменили устаревшие API.

Другой пример лучшей практики-самозванки от сообщества React — Enzyme. Это библиотека для тестирования, разработанная в AirBnB, которая внедрила её у себя и имела хорошую репутацию в сообществе. Какое-то время Enzyme считалась лучшим решением для тестирования React-кода. Но в течение двух лет многие столкнулись с существенными ограничениями библиотеки и внедрили более совершенные разработки. Думаю, своим первоначальным успехом Enzyme была обязана репутации авторов и отсутствию более качественных альтернатив. Вряд ли её можно назвать наилучшим решением.

Конечно, не все лучшие практики в программировании не выдерживают критики. Есть и проверенные временем, общепризнанные, наиболее эффективные. Например, сегодня этому определению удовлетворяет концепция автоматизированного тестирования.

Также не все лучшие практики-самозванки плохи. То, что они не общепризнаны, может означать, что они пока ещё не общепризнаны. Отсутствие абсолютного превосходства может зависеть от точки зрения, а в каких-то ситуациях практика действительно не имеет себе равных.

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

Трудности перевода


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

Вот пример: кто-то путём проб и ошибок нашёл хороший способ решения проблемы. Благодаря процессу обучения он понимает, как и когда нужно применять этот способ. У него это решение работает, и он начинает делиться своими знаниями как лучшей практикой. Их подхватывают люди, которые не получили того же опыта и применили методику напрямую, упуская нюансы. И тоже стали распространять её, методику подхватила следующая волна людей, которые ещё больше недопоняли её и тоже продолжили делиться с другими. Вскоре понимание того, почему работает эта методика, теряется. Люди бездумно повторяют её как упрощённый лозунг. «Всегда пишите тесты до реализации».

Я не придираюсь к разработке через тестирование, просто это отличный пример полезной практики, для корректного использования которой требуется знать много нюансов, а они утеряны в процессе перевода и всё свелось к лозунгу. Своей исходной концепции Кент Бек посвятил целую книгу. Быстро распространившийся евангелизм упростил некоторые идеи. Когда я был студентом, то видел выступление перед второкурсниками, которые приравняли разработку через тестирование к циклу тестирования, программирования и рефакторинга, и выдавали это за самый лучший способ написания кода, свежайшую «лучшую практику в отрасли».

Со временем сложность может возрастать. Идея, которая сначала была простой и для своей интерпретации требовала знания многих нюансов, постепенно усложняется людьми, которые не понимают сути. Возьмём, к примеру, «agile». Изначально это был набор из 12 принципов, а сейчас он превратился в монструозные фреймворки, которые противопоставляются этим принципам консультантами, продающими корпоративное преобразование.

И когда все нюансы утеряны, возникают идеальные условия для распространения идеи. Она исходит от кого-то уважаемого, опытного и авторитетного. Благодаря своей простоте идея выглядит лёгкой в использовании. И люди, не понимающие её, подают её как панацею. В результате другие могут быстро освоить её и начать распространять. Несмотря на своё основанное на заслугах происхождение, идея становится социальным явлением.

Эффект авторитета и использование обществом


Социальный аспект распространения лучших практик помогает ответить на следующий вопрос: почему нам нравится следовать им?

Когда нам для формирования своего мнения не хватает опыта и уверенности, мы обращаемся к авторитету. Эффект авторитета — хорошо известное когнитивное искажение. Именно благодаря ему лучшие практики используются в обществе. Они дают нам то, на что мы сможем положиться по мнению других людей. Тому есть много примеров:

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

Культ


Из-за социальной природы лучших практик легко проявляется стадное мышление. Представьте команду неопытных разработчиков, в которой нет никого, на кого можно положиться. Они не могут принимать все решения обдуманно, поэтому для них лучший выход — следовать лучшим практикам. Разработчики с чем-то борются и ищут какое-то решение. Находят методику, которая выглядит просто, предназначена для решения их задачи и поддерживается кем-то известным. Ваш код полон ошибок и не надёжен? Пишите больше тестов. Ваш код трудно тестировать? Внедряйте разработку через тестирование!

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

Выход из положения


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

Затем нужно научиться на собственных ошибках. Нарушить правила и понять, что будет, если не следовать определённым методикам. Начните им следовать в качестве логического заключения и посмотрите, что будет. Вернёмся к примеру с тестированием. Мы знаем, что происходит, когда не пишешь тесты. Но попробуйте тестировать всё подряд. В какой-то момент ценность добавления новых тестов значительно снижается. Тестировать всё подряд может даже оказаться невозможно.

Или возьмём функциональное программирование. Можно сказать, что оно примерно на 80 % невероятно полезно и сильно улучшает код. Но в чисто функциональных языках эта парадигма, доведённая до абсолюта, намного усложняет разные действия вроде операций ввода-вывода по сравнению со строгими языками. Я не говорю, что в тех ситуациях один способ лучше другого, но у каждого подхода есть свои компромиссы, о которых нужно знать заранее.

Обучение на своих ошибках даёт куда более глубокие знания по сравнению с обычным следованием правилам. А совершив ошибки, можно переходить к заключительному шагу: формированию своего мнения и его распространению. Если мы поняли, откуда взялась лучшая методика, и проверили, что будет, если ей не следовать, то сможем уверенно составить своё мнение и защищать его. Мы можем помочь своим коллегам увидеть полную картину и отказаться от культа.

Идти против течения может быть трудно. Вам потребуется умение и терпение, чтобы убедить коллег в том, что их вера в какие-то подходы оказалась не оправдана. Недостаточно просто говорить об этом. Вам придётся провести их через то же обучение, через которое прошли вы. Именно так вы и стали лучше.

Чтобы сократить процесс учёбы и предотвратить формирование культа лучших методик, в вашей команде должно быть достаточное количество опытных специалистов. В каждой команде нужен достаточно опытный и уверенный человек, который может стать доверенным авторитетом для своих коллег. Кто-то, кто сможет принимать продуманные решения и объяснять необходимые нюансы.

Нам нужно поощрять открытость и независимость мышления. Необходимо тщательно изучать лучшие практики и глубоко в них разбираться. Только так мы сможем прекратить этот культ.