Я год просидел рядом со старшим инженером-программистом. Вот что я узнал

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

Всего через месяц я понял, что это будет не так просто; Я уже забыл то, чему научился. Они либо стали настолько внутренними, что мой разум обманом заставил меня поверить, что я всегда их знал, либо они ускользнули из моего разума [1].

Это одна из причин, по которой я начал вести человеческий журнал. Каждый день, когда я сталкивался с интересной ситуацией, я записывал ее.

Благодаря тому, что я сидел рядом со старшим инженером-программистом, я мог внимательно наблюдать, что они делают и чем это отличается от того, что я делал бы. Мы много программировали в паре, что упростило задачу.

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

Я год просидел рядом со старшим инженером-программистом. Вот что я узнал.

Написание кода - как назвать материал

Одной из первых вещей, над которыми я работал, был пользовательский интерфейс React. У нас был главный компонент, вмещающий все остальные компоненты. Мне нравится немного юмора в моем коде, и я хотел назвать его GodComponent.

Затем пришло время проверки кода, и именно тогда я понял, почему так сложно назвать вещи.

В информатике есть две сложные вещи: недействительность кеша, присвоение имен и единичные ошибки. - Леон Бамбрик

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

Если бы я назвал это LayoutComponent, я бы в будущем понял, что все, что он делает, - это назначает макет. В нем нет состояния.

Еще одно большое преимущество, которое я обнаружил, заключалось в следующем: если он кажется слишком большим, как LayoutComponent, содержащий тонны бизнес-логики, я буду знать, что пора провести рефакторинг, потому что бизнес-логика здесь неуместна. С именем GodComponent бизнес-логика не имеет значения.

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

То же самое и с функциями. doEverything() - ужасное имя, и у него много разветвлений. Если эта функция делает все, будет чертовски сложно тестировать отдельные части функции.

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

У осмысленного именования есть и обратная сторона. Что делать, если название слишком многозначительное и скрывает какой-то нюанс?

Например, закрытие сеансов не закрывает базовое соединение с базой данных, когда вы вызываете session.close() в SQLAlchemy. (Я должен был использовать RTFM и предотвратить эту ошибку - подробнее об этом в Отладка.)

В этом случае представление имен как x, y, z вместо count(), close(), insertIntoDB() предотвращает присвоение им неявного значения - и заставляет меня тщательно исследовать то, что они делают. [2]

Я никогда не думал, что могу сказать больше одной строчки о том, как называть вещи.

Устаревший код и следующий разработчик

Вы когда-нибудь смотрели на код и чувствовали, что это странно? Почему они так делают? В этом нет никакого смысла.

У меня была привилегия работать с устаревшей кодовой базой. Типа с комментариями типа «Раскомментируйте код, когда выясняется ситуация с Мохаммедом». Что ты здесь делаешь? Кто такой Мухаммед?

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

Если я забуду о коде и вернусь к нему позже, и я не смогу воссоздать контекст, я скажу: «Почему они сделали это так? В этом нет никакого смысла ... Ой, подожди, я сделал это ».

И здесь на помощь приходит документация и комментарии к коду.

Документация и комментарии к коду

Они помогают сохранить контекст и делятся знаниями.

Как выразился Ли в Как создать хорошее программное обеспечение:

«Основная ценность программного обеспечения - это не созданный код, а знания, накопленные людьми, которые его создали». - Ли

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

Что, если бы я сказал вам, что один раз в год в определенной стране 10 журналистов отправляют свои отчеты на эту конечную точку? Как это проверить? Если документации нет (ее не было), мы не сможем. Итак, мы этого не сделали.

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

Люди, знавшие продукт, покинули команду. Разумеется, теперь в коде есть комментарии, объясняющие, для чего предназначена конечная точка.

Насколько я слышал, с документацией борется каждая команда. Не только документация по коду, но и процессы, связанные с кодом.

Мы еще не придумали для этого идеального решения.

Мне понравился анализ Antirez различных типов достойных комментариев к коду.

Атомарные коммиты

Если вам нужно откатиться (а вы это сделаете. См. Тестирование), имеет ли смысл эта фиксация как единое целое?

Уверенность в удалении дерьмового кода

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

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

Я пытался обойти код, пожилые люди пытались его проработать. Удалите все это. if заявление, которое никогда не будет достигнуто? Функция, которую не следует вызывать? Ага, все пропало.

Мне? Я бы просто написал свою функцию сверху. Я не уменьшил технический долг. Если уж на то пошло, я просто увеличил сложность кода и неверное направление. Следующему человеку будет еще труднее собирать вещи воедино.

Сейчас я использую следующую эвристику:

Есть код, которого вы не понимаете, и есть код, которого вы никогда не дойдете. Удалите код, до которого никогда не дойдете, и будьте осторожны с непонятным кодом.

Обзоры кода

Кодовые обзоры великолепны для обучения. Это внешний цикл обратной связи о том, как вы пишете код, а не как они его пишут.

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

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

Моя эвристика: не одобряйте код, пока я не пойму, как он работает.

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

Я настолько полюбил тестирование, что мне неудобно писать код в базе кода без тестов.

Если все ваше приложение выполняет одну задачу (как и все мои школьные проекты), то ручное тестирование все еще приемлемо [4]. Раньше я так и делал.

Но что происходит, когда приложение выполняет 100 различных действий? Я не хочу тратить полчаса на тестирование всего и иногда забывать о том, что мне нужно протестировать. Это кошмар.

А вот и тесты и автоматизация тестирования.

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

Итак, когда я пишу тесты сейчас, я имею в виду следующее:

  1. Покажите, как использовать класс / функцию / систему, которую я тестирую.
  2. Покажи, что, по моему мнению, может пойти не так.

Следствием вышесказанного является то, что в большинстве случаев я тестирую поведение, а не реализацию. (Вот пример, который я подобрал во время перерывов в туалете в Google.)

То, чего мне не хватает в № 2, - это то, откуда берутся ошибки.

Итак, всякий раз, когда я обнаруживаю ошибку, я убеждаюсь, что исправление кода имеет соответствующий тест (называемый регрессионным тестированием) для документирования информации. Это еще один вариант, когда что-то может пойти не так. [5]

Однако простое написание этих тестов не улучшает качество моего кода, а написание кода улучшает. Но понимание, которое я получаю от чтения тестов, помогает мне писать лучший код.

Это общая картина тестирования.

Но это не единственный вид тестирования. Вот тут-то и пригодятся среды развертывания.

У вас могут быть идеальные модульные тесты, но если у вас нет системных тестов, происходит что-то вроде этого:

Это справедливо и для хорошо протестированного кода. Если на ваших машинах нет нужных библиотек, вы рухнете и сгорите.

  • Есть машины, на которых вы разрабатываете (источник всех мемов «Это работает на моей машине!»).
  • Есть машины, на которых вы тестируете (могут быть такие же, как те, на которых вы разрабатываете).
  • Наконец, есть машины, на которых вы развертываете (пожалуйста, не позволяйте им быть такими же, как машины, на которых вы разрабатываете).

Если существует несоответствие среды между тестовой машиной и машиной развертывания, у вас будут проблемы. И вот здесь на помощь приходят среды развертывания.

У нас есть локальная разработка в Docker на моей машине.

У нас есть среда разработки, в которой на машинах установлен набор библиотек (и инструментов разработки), и мы устанавливаем код, который мы пишем на них. Здесь можно проводить все испытания с другими зависимыми системами.

Затем идет среда бета / стадии, которая в точности совпадает с производственной средой. Наконец, производственная или производственная среда, то есть машины, на которых выполняется код и обслуживает реальных клиентов.

Идея состоит в том, чтобы попытаться выявить ошибки, которых не удалось бы выявить при модульном и системном тестировании. Например, несоответствие API запрашивающей и отвечающей системы.

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

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

Вы даже можете пойти еще дальше. Загрузите альтернативные образы контейнеров для других сервисов AWS и настройте локальную полноценную среду с помощью Docker Compose. Это ускоряет петли обратной связи. [6]

У меня, вероятно, будет больше опыта, когда я запустю свой побочный проект.

Derisking

Снижение рисков - это искусство снижения рисков с помощью кода, который вы развертываете.

Какие шаги вы можете предпринять, чтобы снизить риск бедствия?

Если это новое критическое изменение, как вы можете обеспечить минимальные неудобства, когда что-то пойдет не так?

«Нам не нужно выполнять развертывание всей системы со всеми этими новыми изменениями». Ой, подожди, правда? Как я об этом не подумал!

Дизайн

Почему я ставлю дизайн после написания кода и тестирования?

Что ж, дизайн может быть на первом месте, но если бы я не кодировал и не тестировал в среде, в которой я нахожусь, я, вероятно, не смог бы спроектировать систему, которая учитывает особенности среды. [7]

При проектировании системы нужно о многом подумать:

  • Каковы номера использования?
  • Сколько существует пользователей? А каков ожидаемый рост? (Это будет означать, сколько строк в БД.)
  • Какие могут быть подводные камни в будущем?

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

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

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

Вещи как:

  • Как будет работать местное развитие?
  • Как мы будем упаковывать и развертывать?
  • Как мы будем проводить сквозное тестирование?
  • Как мы будем проводить стресс-тестирование этой новой услуги?
  • Как мы будем управлять секретами?
  • Интеграция CI / CD?

Недавно мы разработали новую поисковую систему для BNEF. Работать над этим было замечательно. Мне пришлось спроектировать локальную разработку, узнать о DPKG (упаковка и развертывание) и бороться с секретным развертыванием.

Кто думал, что внедрение секретов в продакшн может оказаться таким сложным?

  1. Вы не можете поместить их в код, так как тогда их сможет увидеть любой.
  2. Поместите их как env переменную, как предлагает 12-факторное приложение? Это хорошая идея. Как вы их туда поместили? (Доступ к машинам PROD для заполнения env переменных каждый раз при запуске машины затруднен.)
  3. Развернуть как файл секретов? Откуда файл? Как он заселен?

Мы не хотим, чтобы все выполнялось вручную.

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

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

Довольно круто, насколько это упрощает вещи, но я рад, что у меня есть опыт, чтобы оценить простоту.

Проектирование с учетом обслуживания

Проектировать системы - это увлекательно. Поддерживая их? Не так много.

Мой путь к техническому обслуживанию привел меня к вопросу: «Почему и как системы деградируют?»

Первая часть не осуждает старые вещи, всегда добавляя новые. Склонность к добавлению вместо удаления. (Напоминает вам кого-то?)

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

Это подход, основанный на отступлении, а не на маневренности.

Теперь я знаю как минимум три способа снизить скорость деградации:

  1. Разделяйте бизнес-логику и инфраструктуру. Обычно деградирует инфраструктура - увеличивается использование, фреймворки устаревают, появляются уязвимости нулевого дня и т. Д.
  2. Построение процессов вокруг обслуживания. Примените те же обновления к новым и старым битам. Это предотвращает различие между новым и старым и сохраняет весь код «современным».
  3. Убедитесь, что вы продолжаете обрезать все ненужные / старые вещи.

Развертывание

Я бы предпочел объединить функции вместе или развернуть их по очереди?

В зависимости от текущих процессов, если ответ состоит в том, чтобы объединить функции вместе, возникает проблема.

Тогда возникает вопрос: «Почему вы хотите объединить функции вместе?»

  • Развертывание занимает слишком много времени?
  • Разве проверка кода не проходит легко?

Какой бы ни была причина, это узкое место, которое необходимо исправить.

Я знаю как минимум две проблемы с комплектации:

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

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

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

Когда дела идут плохо

Когда что-то пойдет не так, а они будут, золотое правило - минимизировать влияние на клиента.

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

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

Только после этого я должен посмотреть, что пошло не так, и исправить эти ошибки.

Та же идея с «закорченной» машиной в вашем кластере - отложите ее, отметьте как недоступную, прежде чем пытаться выяснить, что с машиной не так.

Мне показалось странным, как мои естественные склонности и инстинкты расходятся с оптимальным решением.

Я думаю, что этот инстинкт также ведет меня по более долгому пути к решению ошибок. Иногда я думал, что это не работает, потому что что-то не так с тем, что я написал, и я попадал в сорняки, просматривая каждую строку кода, которую я написал. Что-то вроде поиска в глубину.

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

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

  • Машина встала?
  • Установлен правильный код?
  • Конфиг на месте?
  • ‹Конфигурация кода›, например: правильная ли маршрутизация в коде?
  • Версия схемы верна?
  • Затем войдите в код.

Мы думали, что NGINX некорректно установился на машину, но оказалось, что для конфигурации было установлено значение false.

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

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

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

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

Военная история

Это танец между настройкой параметров и игрой со статистикой и устранением первопричины.

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

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

Каждый раз, когда мы получаем сообщение, мы заходим в нашу базу данных через SQLAlchemy, получаем все необходимое, трансформируем его и отправляем в наш экземпляр Solr для индексации. А теперь время для странной ошибки.

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

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

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

Быстрый просмотр кода и, конечно же, мы использовали диспетчер контекста для каждого чтения, которое вызывает session.close() на __exit__().

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

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

Session.close() в диалекте MySQL SQLAlchemy не закрывает базовое соединение с базой данных, если вы не используете NullPool. Да, это было исправление.

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

И в этом заключается еще один урок - большинство ответов на Stack Overflow (конечно, я погуглил!) Об этой ошибке заключалось в настройке либо времени ожидания сеанса, либо параметра, контролирующего количество данных, которые вы можете отправить на каждый оператор SQL.

Для меня это не имело смысла, потому что они не имели отношения к основной проблеме. Я проверил, что размер нашего запроса находится в установленных пределах, и мы закрывали сеансы (lol), чтобы не было тайм-аута.

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

Это танец между настройкой параметров и игрой со статистикой и устранением первопричины.

Мониторинг

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

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

"Что я делаю? Я даже не знаю, что что-то не так с моей системой? "

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

Вход в код, как и в человеческий журнал, - это эволюционный процесс.

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

Я думаю, вы интуитивно понимаете, что будет важно регистрировать. Между тем, что он (старший SWE) и я регистрировали в нашем сервисе, была большая разница.

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

Практически невозможно отладить что-либо без журналов - если вы не знаете, в каком состоянии находилась система, как вы вообще можете его воссоздать?

Метрики могут быть получены из журналов или отдельно в коде. (Как отправка событий в AWS CloudWatch и Grafana). Вы определяете свои метрики и отправляете числа по мере выполнения кода.

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

Количество отказов превышает определенный порог? Ага, еще одна тревога.

Я могу спокойно спать по ночам, зная, что, если что-то пойдет не так, меня разбудят. (Чего ждать?)

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

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

Заключение

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

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

В этом году я сижу рядом с двумя старшими разработчиками. Посмотрим, как это пойдет! Спасибо, команда!

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

Вещи, в которых я не уверен

Я еще не взломал код разработки программного обеспечения. Итак, этот раздел служит для меня напоминанием. Еще так много предстоит узнать!

Если я все делаю правильно, в следующем году этот список должен расшириться.

  1. Думайте в терминах абстракций или реализаций?
  2. Должен ли я иметь твердое мнение о том, как что-то делать? Может быть, из-за того, что тебя укусили раньше? Проделал ли я работу, необходимую для того, чтобы высказать свое мнение?
  3. Разработка процессов для рабочих процессов. Если вам нужно изменить то, как вы делаете что-то из-за чрезвычайной ситуации или события - нарушается ли процесс? Это что-то исправить?
  4. Утилиты (папка, в которую вы кладете случайные вещи, которые вы не знаете, куда положить) - это запах кода?
  5. Как работать с документацией по коду и рабочим процессам?
  6. Как отслеживать пользовательский интерфейс, чтобы видеть, когда что-то не так?
  7. Тратить время на разработку идеального контракта API / кода вместо его взлома и повторения снова и снова, чтобы выяснить, что работает лучше всего. Какой из них лучше?
  8. Легкий путь против правильного? Я не уверен, что правильный путь всегда лучше.
  9. Делать что-то самостоятельно или показывать тем, кто не знает, как это делать. Первое выполняется быстро, второе означает, что вам редко придется делать это снова самостоятельно.
  10. При рефакторинге и предотвращении огромных PR: «Если бы я сначала изменил все тесты, я бы увидел, что мне нужно изменить 52 файла, и это, очевидно, будет слишком большим, но я сначала возился с кодом, а не с тестами. . » Стоит ли его разбивать?
  11. Узнайте больше о снижении рисков. Какие существуют стратегии снижения рисков в проектах?
  12. Эффективные способы сбора требований?
  13. Как снизить скорость деградации системы?

В этом году я написал продолжение! Если вам это понравилось, вам тоже понравится.



Конечные заметки

[1] Это происходит со многими вещами. Ты умеешь ездить на велосипеде? Вы можете кого-нибудь научить? Расскажите им, какие именно шаги вы сделали?

[2] Это не значит писать код с именами x(), y(), z(), а просто думать о них как о x(), y(), z(). Не используйте WYSIATI.

[3] Классический забор Честертона.

[4] Но я бы больше этого не делал. Как только вы перейдете на сторону автоматизированного тестирования, вы больше никогда не вернетесь?

[5] Есть аргументы в пользу выхода из-под контроля, когда нужно провести миллион тестов на все, что может пойти не так. Судя по тому, что я видел, на самом деле это не так.

[6] Я давно этим не занимался, поэтому не уверен, насколько легко найти / создать образы Docker для AWS.

[7] Среда здесь может означать ваш технический стек.