Автор Джон Теренцио

Когда я присоединился к Airbnb осенью 2012 года, все было немного хаотично, если не сказать больше. В какой-то момент в прошлом году рост компании резко ускорился, или, как некоторые называют, гипер-рост. Наряду с увеличением посещаемости сайта и объема транзакций, команда инженеров также очень быстро расширилась. Когда я приехал, в нас было около 40 человек по сравнению с 16 годом ранее (и более 130 сегодня). Оглядываясь назад, я думаю, что мы были в разгаре переломного периода в истории Airbnb.

Развитие веб-сайта и инженерной команды так же быстро, как Airbnb, сопряжено как с техническими, так и с культурными проблемами, и во многих случаях эти проблемы взаимосвязаны. Раньше мы боролись со многими проблемами, но в целом эти проблемы были связаны с масштабированием монолитного приложения Ruby on Rails (которое не создавалось с учетом масштабирования) и масштабированием команды разработчиков таким образом, чтобы облегчить первое.

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

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

Соответствие Кодексу

Соответствие кода относится как к синтаксическому / текстовому стилю, так и к применению соглашений и передовых методов при написании кода. Об этом много раз говорилось и раньше, но если у вас есть кодовая база, в которой вы можете открыть файл и сказать, кто его написал в вашей команде, это очень плохой знак. Формулирование стандартного способа написания кода и вовлечение всех в работу было для нас очень полезным.

Компьютерный код обычно используется двумя классами сущностей: машинами и людьми. Машины обычно не заботятся о том, как выглядит ваш код (при условии, что он компилируется), но люди в вашей команде, вероятно, заботятся. Наличие большого разнообразия стилей и подходов к аналогичным проблемам в вашей кодовой базе создаст ненужную когнитивную нагрузку для всех и отнимет много времени, поскольку люди будут пытаться осваивать новую территорию. С другой стороны, если все в команде пишут код более или менее идентичным образом, каждый в команде должен иметь возможность анализировать, отлаживать и / или поддерживать код друг друга с почти одинаковым уровнем усилий. (после того, как они пройдут начальный рост). Другими словами, при разработке кода важно отдавать предпочтение читателю-человеку, а не машине, и еще важнее быть последовательным. Это не означает, что вы должны выбирать решение O (N) вместо решения O (1) для удобства чтения или простоты, но есть много шагов, которые вы можете предпринять, чтобы облегчить своим собратьям по согласованию кода.

Мы достигли большего соответствия кодексу двумя способами. Первый - это использование руководств по стилю (из которых мы создали несколько примечательных). Наши наиболее подробные руководства охватывают JavaScript и Ruby, однако у нас также есть внутренние руководства по RSpec, дизайну API, дизайну услуг и т. Д. Хотя эти руководства выросли из нашего конкретного опыта, некоторые из них теперь общедоступны и используются другими людьми и организации (которые затем часто вносят свой вклад). В зависимости от типа приложения, над которым вы работаете, они могут быть полезны, а могут и не оказаться для вас полезными, но если вы работаете с JavaScript или Ruby, я рекомендую вам проверить их, хотя бы по той или иной причине, кроме вдохновения.

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

Учитывайте длину строки. Нам нравится, чтобы строки были короткими и приятными. Более короткие строки не только более удобны для глаз других инженеров (и редакторов), но они также имеют тенденцию приводить к более чистым и простым заявлениям (особенно в сочетании с описательными именами переменных). Методы, состоящие из серии коротких простых утверждений, легче понять и изменить другим членам команды. Различия (в инструментах управления версиями, таких как Git) также более четко показывают, какое поведение было изменено между коммитами. И поскольку мы также пишем тестируемый код (см. «Тестирование» ниже), который продвигает небольшие, краткие методы, вы начинаете разрабатывать очень чистую, модульную и легкую для понимания кодовую базу.

Рассмотрим этот пример:

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

Трудно сказать, какая часть изменилась, не проанализировав строку в голове. Если бы код был написан примерно так:

Дифференциал также был бы намного чище, показывая, какое именно поведение изменилось:

Самое смешное, что те из нас, кто начал продвигать это, вначале столкнулись с серьезным сопротивлением. Однако, как и в случае с тестированием, мы проявили настойчивость и дошли до того, что это стало нашей второй натурой. Чтобы увидеть несколько ярких примеров этого менталитета, я предлагаю ознакомиться с Руководством по кодированию на C ++ для Joint Strike Fighter или Руководством по кодированию на языке JPL C. Очевидно, что эти стандарты являются излишними для большинства потребительских веб-приложений, но всегда помните, какой тип приложения и какие цели вы преследуете, устанавливая правила. Речь идет о выборе правильного баланса.

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

Экспертная оценка

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

Однако наличие подписи еще одного человека - это абсолютный минимум. Мы призываем всех, у кого есть контекст, принять участие, и в большинстве нетривиальных запросов на вытягивание всплывают хотя бы один или два предметных разговора. Иногда они могут быть довольно глубокими, и некоторые из нас в конечном итоге узнают что-то, о чем мы не знали (на ум приходят обработка кредитных карт, внутреннее устройство баз данных и криптография). Если есть важные идеи, мы также обязательно зафиксируем их в соответствующем руководстве / документации. Что наиболее важно, проверка кода не имеет авторитета на основе стажа работы или должности. Мнения каждого действительны, но лучшие практики всегда имеют тенденцию преобладать, а новые члены команды, как правило, быстро учатся.

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

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

vs.

Мы встречали множество примеров, подобных первому в нашей кодовой базе. Хотя они оба выводят одно и то же, первый пример намного дороже и может привести к катастрофе. Добавление select к прокси-объекту User.active означает, что Rails перейдет к MySQL, извлечет всех активных пользователей, создаст их экземпляры, поместит их в массив, а затем выполнит итерацию по этому массиву. и выберите пользователей со страной, равной "США". Все это просто для того, чтобы подсчитать.

Во втором примере мы начинаем с того же прокси-объекта, Users.active, но затем используем, где фильтровать этот объект. Первая строка не вызывает никаких запросов к БД! В следующей строке, когда мы вместо этого запрашиваем счетчик, Rails знает, что нужно просто выполнить запрос SELECT COUNT (*) и не беспокоиться о получении каких-либо строк или создании экземпляров каких-либо моделей. .

Очень важно хорошо знать язык и структуру, а также распространять эти знания среди всех участников. Мы в Airbnb старательно исправляем такие типичные ошибки и продвигаем передовой опыт передачи работы в БД, когда это имеет смысл. Другой пример. Сколько мы сегодня выплатили?

Плохо:

Хорошо:

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

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

Тестирование

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

Заключение

Итак, завершая этот небольшой обзор, я еще раз резюмирую три основные темы. Соответствие кодексу. В профессиональной команде любого размера важно, чтобы все писали код одинаково. Это помогает распространять передовой опыт и значительно упрощает поддержку кода других людей. Руководства по стилю - отличная отправная точка. Даже казалось бы простой выбор стиля может повлиять на качество, надежность и простоту рефакторинга кода. Активный, здоровый процесс проверки. Помимо всего прочего, важно стимулировать активный и здоровый процесс проверки. По крайней мере, один человек, помимо автора, должен просматривать каждое различие, и члены команды любого уровня должны с радостью высказывать и приветствовать предложения. Это помогает распространять мудрость. Это помогает новым членам команды учиться и развивать хорошие привычки. Это помогает более старшим членам учить и оставаться честными. В конечном итоге это может уберечь ваше приложение от серьезных сбоев. Тестирование. Важно придерживаться строгой этики тестирования, а не идти на компромисс или сокращать пути. Чем больше мы проверяем, тем больше это становится нашей второй натурой, и, возможно, со временем мы даже научимся любить ее. Это не обязательно должно начинаться по указу, но может расти органически в нескольких местах, пока не начнет прорастать повсюду.

Ознакомьтесь со всеми нашими проектами с открытым исходным кодом на airbnb.io и подпишитесь на нас в Twitter: @AirbnbEng + @AirbnbData

Первоначально опубликовано на сайте nerds.airbnb.com 18 ноября 2014 г.