Потому что код написан для людей, а выполняется только машинами.

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

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

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

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

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

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

Что пошло не так?

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

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

Во-вторых, его производительность была ужасной. По меньшей мере. Чтобы дать вам представление, реализация, которую мы в конечном итоге поставили, была примерно на 2000% быстрее, чем та чушь, которую мне удалось создать. Одна из главных причин, по которой он работал так хорошо, заключалась в том, что для начала было не так уж много кода. Поговорка «меньше кода - лучше» не всегда может быть правдой, но в данном случае так оно и было.

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

Считайте своих коллег-разработчиков

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

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

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

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

Вывод

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

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

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

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

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

Для тех, кому интересно, структура дерева хорошего поведения в этой статье - TreeSharp. Я не писал его, но он преподал мне бесценный урок.