[Перевод] Матёрый программист
1. Матёрый программист
Матёрый программист хорошо распоряжается своим временем и продуктивностью. Матёрый программист знает, что обслуживание — это такая же работа, как и первоначальное написание, а код всегда занимает больше времени, чем вы думаете. Матёрый программист знает, что любые изменения в коде могут привести к ошибкам, какими бы незначительными они ни казались. Матёрый программист знает, что преждевременная оптимизация — это глупо и опасно. Матёрый программист знает, что sexy coding, такое как написание больших сложных систем с нуля, редко бывает лучшим выходом. Матёрый программист не участвует в соревнованиях на самый красивый код. Матёрый программист добивается наилучшего финального результата за минимальное время.
Когда я начинал в Oddworld, я наблюдал, как многие игровые компании устраивают соревнования у кого лучший домашний графический движок, и я также наблюдал, как многие инди-разработчики тратят огромное количество времени на свой «единственный настоящий» продукт и никогда не запускают его. Я решил, что мы не попадем в эти ловушки — мы будем скромными и не будем заходить слишком далеко, мы не позволим нашему эго помешать нам лицензировать код или использовать старомодные решения проблем, мы будем сосредоточены на конечном продукте — любой sexy code, который не давал видимых преимуществ в запуске реальной игры, был исключен. По большей части, я думаю, нам это удалось (было несколько отступлений, в основном из-за меня).
Но путь матёрого программиста может оказаться ловушкой, в которую можно попасться.
Проблема в том, что писать код таким образом не очень весело. Несомненно, создавать продукт — это удовольствие — и если вы работаете над игрой и верите в игру и команду, то простое наблюдение за выпуском хорошего продукта может дать вам мотивацию. Но если у вас ее нет, это может стать настоящим утомительным занятием.
Большинство из нас занялись программированием не ради конечных продуктов, которые мы создаем, а потому, что само программирование доставляет удовольствие. Код может быть красивым. Код может быть умным, артистичным, захватывающим творением, как хорошее математическое доказательство. Матёрый программист сказал бы, что «умный код почти всегда опасен». Но к черту его. Проблема в том, что когда вы увлекаетесь «матёростью», вы теряете радость от программирования.
Вы должны позволить себе быть в какой-то степени неосоторожным, чтобы оставаться довольным своим кодом. Конечно, эти шаблоны могут быть не очень хорошей идеей, но вам нравится писать код таким образом — хорошо, сделайте это. Да, вы занимаетесь оптимизацией на раннем этапе, и это только усложняет сопровождение кода, затрудняет чтение и делает его более ошибочным —, но вы любите это делать, хорошо, делайте это.
Очевидно, с этим нельзя перебарщивать, но я думаю, что я (и многие другие) переборщили со своей матёростью. По сути, за последние десять лет моей эволюции как кодера я стал не столько «громким случаем», сколько менеджером по продуктивности, эффективным анализатором задач и проактивным координатором решений по актуализации кода. Это похоже на управленческую бюрократию одного человека в моей голове. Это ужасно.
Я думаю, что нужно учитывать два фактора: во-первых, «матёрость» и продуктивность может вызвать выгорание, что в конечном итоге сказывается на вашей производительности, или это может просто сделать кодинг неприятным, так что вы будете тратить на него меньше часов. Большинство «матёрых» программистов хвастаются тем фактом, что они могут сделать столько же за 6 часов, сколько они делали за 14 часов. Но эти 14 часов были ВЕСЕЛЫМИ, вы так долго кодили, потому что вам это нравилось, вы не могли заснуть ночью, потому что вы хотели больше писать код; теперь эти 6 часов неприятны, потому что вместо того, чтобы разворачивать собственное решение, вы просто связываете вместе несколько пакетов java и perl. Во-вторых, продуктивность — не единственная цель. Мы пишем код, чтобы выполнить какую-то задачу и заработать деньги, но мы также пишем код, потому что нам это нравится, и на самом деле быть менее продуктивным, но получать большее удовольствие от кодинга может быть чистым + EV. (EV в покере — это сокращение от expected value означающего математическое ожидание от розыгрыша руки или определенного действия.)
2. Здоровое противодействие продюсера
Многие программисты, выполняющие обычную работу по кодингу, ненавидят вмешательство продюсера (или корпоративного руководства, или издателя, или кого-то еще). Этот человек навязывает глупые графики и не позволяет нам выполнять функции, которые мы хотим выполнять, и мы их ненавидим! Эти кодеры хотят иметь возможность составлять свое собственное расписание, выбирать свои собственные задачи и быть свободными.
На самом деле это противодействие во многих отношениях очень полезно и гораздо больше расслабляет. Когда вам приходится составлять расписание или принимать собственные решения относительно задач, вы берете на себя ответственность как за творческую сторону «стремления к высотам», так и за ответственную сторону «сохранения бюджета». Практически невозможно хорошо проработать обе стороны. Это может произойти, если вы инди или даже если у вас сильный лидер со слабым продюсером.
Большинство творческих индустрий знают, что есть здоровое противодействие между безудержным творческим мечтателем и продюсером, следящему за бюджетом. Вы не хотите, чтобы мечтатель слишком беспокоился о расписании или, возможно, вы просто хотите, чтобы он выдвигал идеи и упорно старался получить из этого больше.
Когда вам нужно вырезать черты, или выполнить числовые расчеты, или что-то еще, приятно, когда это приходит извне — вас заставляет делать это какая-то другая сила, и вы можете ненавидеть их и продолжать. Приятно иметь виноватую внешнюю силу, которая не в вашей команде; это дает вам цель для вашего разочарования, помогает сблизиться, а также дает вам повод выполнить работу (потому что они сказали вам).
Когда вам приходится самостоятельно находить баланс между мечтами и расписанием, это добавляет интеллектуального бремени к каждой задаче — поскольку вы выполняете каждую задачу, которую должны учитывать, «Стоит ли это потраченного времени? Правильно ли выполнять эту задачу сейчас? Нужно ли мне это упростить?» что значительно снижает вашу способность сосредоточиться только на самой задаче.
3. Стандарты кодинга
Для меня просто поразительно, сколько опытных программистов до сих пор не понимают программирования. Большая сложность в программировании состоит в том, что количество способов написать что-то слишком велико. Мы можем потеряться в этом пространстве.
Одна из проблем — просто интеллектуальная перегрузка. Умные кодеры могут ошибочно полагать, что они справятся с этим, но это бремя для всех. Каждый раз, когда вы пишете строку кода, если вы должны думать: «Следует ли мне использовать строчные или смешанные заглавные буквы?», или «Мне сделать это функцией или просто написать в строке?» ваш мозг тратит массу энергии на синтаксические решения и не имеет полной мощности для выполнения функций. Строгие стандарты кодинга на самом деле являются интеллектуальным облегчением, потому что они устраняют все эти решения и дают вам определенный способ выполнения синтаксиса. (То же самое, конечно, относится к чтению чужого кода — ваши глаза могут сразу начать смотреть на функциональность, а не пытаться выяснить текущий синтаксис).
Другим большим преимуществом стандартов кодинга является создание «метаязыка», который меньше, чем базовый язык, и обеспечивает соблюдение определенных инвариантов. Поступая так, вы снова уменьшаете пространство, которое мозг должен учитывать. Например, вы можете потребовать, чтобы все макросы C вели себя как функции (например, не использовали области видимости и не объявляли переменные). Теперь, когда я вижу одного, я знаю, что мне не нужно беспокоиться об этих вещах. Или вы можете потребовать, чтобы глобальные переменные никогда не извлекались из внешнего источника и были доступны только через функции, называемые «GetGlobal_blah». На самом деле не имеет значения, что они собой представляют, если они просты, ясны, единообразны и строго соблюдаются, потому что, только если они полностью надежны, вы можете перестать думать о них.
4. Ловушка «перезрелого программиста»
Многие великие кодеры моего поколения прошли этап программирования со строгим соблюдением правил и перешли на этап «пост». «Перезрелый программист» знает, как важно следовать строгим правилам стиля программирования или не слишком увлекаться собой, но также видит выгоду от изменения этих правил и считает, что они могут быть немного более свободными в принятии решений о том, что делать для каждой из ситуаций.
Я считаю, что они/мы в основном ошибаются.
Лучшая аналогия, которую я могу придумать, — это покер. Самые успешные игроки в покер проходят несколько этапов. Сначала вы думаете, что вы настолько умны, что можете блефовать, заманивать людей в ловушку и разыгрывать всевозможные странные линии игры. Как только вы подниметесь на уровень выше и начнете серьезно играть в покер, это заблуждение быстро исчезнет, и вы поймете, что вам нужно вернуться к истокам. Таким образом, большинство людей пройдут через фазу «линии стандарта», где они узнают, что правильно делать в каждой ситуации, и стандартному способу анализа рук, и они будут весьма успешны в этом (обратите внимание, что «линия стандарта» не означает нит, она включает в себя такие вещи, как сквиз и даже чек-пуш блефы на ривере, но она основана на игре со сбалансированным диапазоном и изучении средней выгоды). Но затем они настолько успешны в своей твердой игре, что начинают думать, что им сойдет с рук «смешивание», разыгрывание руками, которые почти наверняка не принесут пользы, потому что они думают, что они достаточно хороши на постфлопе, чтобы компенсировать это (например, стиль Durrr), или воображая, что, играя несколько раздач с минусом в средней выгоде помогает их имиджу и окупается позже.
Это почти всегда неправильно. Лимпить АА почти всегда неправильно, открытие 72o с UTG почти всегда неверно — возможно, вы провели некоторый анализ и решили, что это правильно за этим столом в данный момент (например, лимпить АА, потому что люди, стоящие за вами, атакуют лимперов слишком много, и они думают, что вы никогда не будете лимпить АА, поэтому они легко застрянут). Это не правильно.
(говоря себе, что ваша нынешняя плохая игра компенсируется более поздней «ценностью», — это один из замечательных аргументов в пользу того, что игроки в покер используют для оправдания своей плохой игры. на самом деле просто рационализаторские оправдания своих плохих практик; в покере средняя ценность в руке стоит больше, чем средняя ценность на поле игры; то есть более поздняя ценность, которую вы можете получить, настолько мала и сомнительна и зависит от различных вещей, которые работают правильно, что почти всегда неверно отдавать известную текущую ценность в пользу возможной будущей (особенно простой случай — это «подразумеваемые шансы», которые плохие игроки используют как предлог, чтобы использовать руки так, как не следует))
Проблема в том, что, когда вы открываете себя для любой возможный ход в любой момент, появляется много того, над чем стоит поразмыслить. Вы не сможете принять все эти решения, исходя из изначальных принципов, и сделать правильный выбор при этом. Даже если бы вы могли, вы не сможете отследить тысячи рук. Вы будете делать ошибки.
То же самое и в кодинге. Перезрелый программист знает ценность инкапсуляции некоторой функциональности в структуру + помощники (или класс), но они думают, что достаточно умны, могут решить не делать этого в данном конкретном случае. Нет! Неправильно. Я имею в виду, что, может быть, вы действительно правы в данном конкретном случае, но для принятия этого решения не следует использовать энергию вашего мозга, и вы будете делать это несколько раз неправильно.
Простые правила очень ценны. Например, «каждый раз, когда я вступаю в розыгрыш банка на префлопе, я делаю рейз». Возможно, это не всегда лучший выход, но это неплохо, и это избавляет вас от возможных серьезных ошибок и, что наиболее важно, освобождает ваш мозг для других дел.
То же самое происходит с принятием жизненных решений. Стандартный набор клише:
Не выходите замуж за первого человека, с которым вы спите
Не вступайте в серьезные отношения, чтобы забыть бывшего патнера
Не покупайте ничего, если продавец сильно настаивает
Выделите день, чтобы поспать перед любым важным решением
Не одалживай деньги бедным друзьям
и т.п.
Вы можете подумать: «Я умный, я матёрый, мне не нужны эти правила, я могу принять собственное решение правильно, исходя из специфики текущей ситуации». Но вы ошибаетесь. Конечно, следуя правилам, вы можете время от времени упускать по-настоящему оптимальное решение. Но глупо высокомерно думать, что ваш ум настолько силен, что вам не нужна защита и простота, которые обеспечивают правила.
В покере после стадии уверенного игрока правильная правильная корректировка крайне мала. Вы не идете все время на дикие игры, это чрезмерная уверенность в своих силах и просто «spew». Правильно развитый игрок в основном придерживается сплошной линии и стандартного способа оценки, но знает, как определять ситуации, в которых правильна очень небольшая корректировка. Возможно, стол играет слишком тайтово на префлопе, поэтому в позиции с угоном вы начинаете открывать первые 35% рук вместо 25% лучших рук. Вы не просто начинаете открывать каждую руку. Вы остаетесь в рамках хорошей игры, которую понимаете и можете обойтись без переосмысления всего своего подхода.
Я считаю, что то же самое и в программировании. Правильная корректировка для перезрелого кодинга очень мала; вам не нужно быть полностью догматичным в отношении того, чтобы сделать каждую переменную приватной, но вы также не просто перестаете инкапсулировать классы вообще.