Год назад я стал разработчиком в Foxintelligence, стартапе в Париже. До этого я работал в двух компаниях в качестве администратора проектов в отделах информационных технологий. Поэтому я примерно понимал, как разрабатываются приложения. Но став разработчиком, я узнал много нового. И сейчас я хочу поделиться этим с вами.
Писать рабочий код просто
Перед тем как впервые подать резюме на вакансию разработчика, я прошел несколько онлайн-тренингов. Я хотел показать свою мотивацию, а также чему я смог научиться за пару недель.
На новой работе моей первой задачей стало написать рабочий код. То есть код, который действительно делает то, что написано в техническом задании. Почти всё было для меня новым. Я узнал о JWT, как привязать базу данных с помощью Node.js, как работает Vue.js и другие технические моменты.
Но через пару месяцев я понял, что писать рабочий код — это не самая сложная часть работы. Намного сложнее писать код, который поймут другие люди.
Любой дурак напишет код, который может понять компьютер. Хорошие программисты пишут код, который могут понять люди.
МАРТИН ФАУЛЕР, 2008
Так что следующей моей задачей стало написать читаемый и удобный в поддержке код! В это же время в проект, который я начинал в одиночку, пришел ещё один разработчик. Мне пришлось объяснять и подчищать все моменты, который понимал только я.
Писать хороший код сложнее
Так как же писать хороший код, который не просто работает, но и соответствует нормам?
Первое, что такое хороший код? Вот несколько пунктов, которые помогают мне определить хороший код.
Он понятен
Хороший код будет понятен вашим коллегам (нынешним и будущим) и вам в будущем.
Для начала стоит потратить время на названия переменных, функций и ошибок. Вам нужно дать наиболее ясные названия. Звучит просто, но правильное название функций сэкономит очень много времени (забудьте про get, data, id). Ладно, если названия слишком общие, хуже, если функция делает не то, что сказано в названии. Если функция getSomething не только возвращает какое-то значение, а также вводит что-то новое, то получается, что она имеет побочный эффект. Это плохо.
Еще один важный момент — эффективная архитектура. Она должна быть такой, чтобы люди могли найти то, что им нужно. Также, если функции разделены, их можно тестировать отдельно, что облегчает работу.
Ошибки устраняются
Ваш код хорош, если он не прекращают работу в случае ошибки. Это означает, что происходит обработка ошибок. Действительно, ошибки — это часть программ, они могут происходить по разным причинам. Пользователь использует программу не так, как нужно. Формат данных отличается от нужного вам (пользователь ввел не те данные, изменился API, и т.д.). Количество одновременных пользователей превышает количество, которое было в режиме разработки. Возможны даже ошибки сети.
Пусть вы не можете продумать решение каждой возможной проблемы, у вас должна быть общая стратегия устранения ошибок для любой неожиданной ситуации. Например, для каждого маршрута API вы можете формировать пакет данных с помощью try catch, который позволит документировать все ошибки и отправлять общее сообщение об ошибке пользователю. Вы не можете предвидеть все ошибки, но это поможет вам:
- Вести журнал ошибок
- Возвращать пользователю ответ, которого он ждет (не сообщая при этом о внутренних ошибках API)
Однако не стоит постоянно стараться устранить все ошибки. Уделяйте внимание важным ошибкам и не забывайте находить реальную причину проблемы.
Он документируется
Вы ведь не будете заниматься одним проектом всю свою жизнь. Также это позволит сэкономить ваше время, не тратя его на ответы на одни и те же вопросы. Лучше потратить время один раз, написав, как всё работает. Для начала неплохо постоянно обновлять readme-файл, схему архитектуры и комментировать код в непонятных местах (желательно объяснять почему, а не как).
Его удобно поддерживать
Это означает, что продукт можно развивать, добавлять ему новые функции или улучшать отдельные части, не ломая программу и не тратя кучу времени на рефакторинг. Это тонкое искусство быстрого выполнения работы (что влечет за собой технический долг) и развития умения думать о будущем, чтобы иметь возможность расти дальше.
Как писать хороший код?
Мы разобрались, как выглядит хороший код. Как помочь людям применять указанные принципы?
Я считаю, что здесь важны 2 вещи (не считая желания и знаний разработчиков): понимание и проверки кода.
Понимание
Моей главной обязанностью в качестве администратора проектов было определить рамки проекта, над которым мы работаем. Нужно, чтобы всех эти рамки устраивали, так как от них зависит всё остальное. Вы не можете обсуждать бюджет, планирование, риски и ресурсы проекта, если ещё не ясны рамки.
У разработчика то же самое: перед тем, как начать думать о техническом понимании, нужно определить рамки функции, над которой вы работаете. В хорошей организации вы решаете это с администратором или владельцем проекта.
Это часть спринта или нет? Стоит ли нам уменьшить рамки, чтобы в конце спринта что-то работало (пусть и не идеально)? Это ключевая часть программы или она просто не помешает?
Когда вы определились с рамками, можно переходить к техническому пониманию. Вы можете обсудить названия компонентов, маршруты API, формат данных или, например, над какой частью кода следует работать. Вам не нужно обсуждать каждую деталь или тратить часы в спорах о названии функции. Лучше обдумайте архитектуру в целом, как будут связаны разные части вашего приложения. Тогда программисты будут принимать меньше субъективных решений в одиночку. Повысится читабельность и качество кода.
Проверки кода
В классическом git flow, каждая новая функция разрабатывается в отдельной ветви функции. И перед включением работы в одну из главных ветвей, осуществляется запрос на включение кода. Проверка кода — это процесс проверки каждого сделанного изменения в коде (они называются git diffs). В будущем, если что-то будет непонятно или не оптимизировано (в плане читабельности), это можно будет обсудить. По началу это сложно и занимает много времени, но это сэкономит гораздо больше времени в долгосрочной перспективе.
Нельзя добиться абсолютно ясного, чистого и удобного в поддержке кода. Я не думаю, что даже самые крутые программисты 24/7 пишут идеальный код. Но проверка кода вами или кем-то другим очень помогает на старте карьеры.
Ну, а что дальше? Что может быть сложнее, чем писать хороший код?
Эффективно работать в команде разработчиков может быть сложно
Возьмём одного разработчика, который умеет писать чистый и удобный в поддержке код. Возьмём другого, такого же. Теперь скажем им работать вместе над одним проектом. Совсем не факт, что получится хорошая команда разработчиков.
Как организовать и разделить работу? Как избежать конфликтов слияния? Как избежать ситуации, когда разработчики мешают друг другу?
Эти вопросы вы задаёте себе, начиная работать в команде. Я видел развитие команд (до 5 разработчиков), и знаю, что эти проблемы должны решаться как можно быстрее. Когда над проектом работают 5 человек, нельзя терять драгоценное время. Скажем, вы потратили 1,5 часа на бесполезное собрание с командой, и день вашей работы пропал впустую. Вот такие принципы мы разработали в команде, чтобы избежать разногласий и работать продуктивно:
- Делите фронт работы. Во время работы, каждый программист будет сконцентрирован на своей части работы. Он может работать над компонентом во front-end или с маршрутом API. Не обязательно делить именно на front-end и back-end, нужно предоставить каждому свои файлы, в которые остальные лезть не будут. Лучше всего, чтобы программисты время от времени менялись своими обязанностями. Плюсы: каждый программист сможет работать над любой частью приложения (ограничивает фактор автобуса), другие программисты смогут проверить каждую строчку, и люди будут учиться новым и интересным вещам.
- Понимание (опять). Чтобы быть уверенными, что новая функция не изменяет все остальные файлы. А также понимать влияние каждой модификации.
- Быстрая работа. Все стараются развиваться свою ветвь функции и разрабатывать всё быстрее. Это сокращает время, когда одна ветвь существует отдельно от других и уменьшает вероятность конфликтов слияния. А ещё проверка кода происходит максимально быстро.
- Придумай, и это появится. Например, для API вызовов, человеку, который работает с компонентом front-end, для начала работы не нужны реальные данные. Если маршрут APi возвращает придуманные данные в правильном формате, никто не блокируется. То же самое касается данных, используемых разными компонентами через хранилище в интерфейсе React или Vue.
Перевод статьи Clément Bataille: What I learned in my first year as a Software Engineer in a startup