Техники и принципы достижения цели

Мой ответ на этот вопрос продолжает развиваться.

Сегодня меня попросили просмотреть чью-то кодовую базу. Прежде чем углубиться в код, я почувствовал, что должен объяснить, по какому стандарту я собираюсь сравнивать код.

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

Это уравнение состоит из двух частей. Первый — это сам код (отличный код), а второй — процесс кодирования (как его написать).

Отличный код

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

Это два принципа от Amazon Principle Engineering Community, которые находят отклик у меня.

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

2. Используйте несколько парадигм

Это не объектно-ориентированное программирование против функционального программирования, используйте оба! Полиморфизм и биекция объектов так же полезны, как чистые функции и неизменность.

Есть место и для процедурного программирования. Даже в Haskell побочные эффекты выполняются в процедурном стиле. Иногда вы просто хотите контролировать поток шаг за шагом.

3. Будьте проще. Ваш код читается людьми.

Простой код легко читать, но сложнее написать. В моем текущем проекте мы используем функции AWS Lambda. Если я не понимаю, что делает функция через 15 секунд, это плохой код.

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

4. Целью функций и классов является в основном абстракция, а не возможность повторного использования.

Если в моем лямбда-обработчике 50 строк кода, я не смогу понять его за 15 секунд. Я могу добиться этого, только если использую абстракцию.

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

5. Назвать сложно. Используйте язык домена

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

Именование ваших функций и структур данных так же, как эксперт в предметной области, также упрощает преобразование ваших требований в тесты.

6. Отличный код делает то, что должен

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

7. Инфраструктура, конфигурация, конвейер и код приложения находятся в одном месте

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

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

8. Отделите предметную область и бизнес-логику от остального кода

Есть много способов структурировать код. Предстоит обсудить, следует ли структурировать по типу/слою или признаку или по различным комбинациям того и другого. Честно говоря, мне все равно.

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

Я не говорю, что этот код менее важен. Я говорю, что со всеми этими побочными эффектами нужно обращаться осторожно. Здесь все может сломаться, и мне нужно использовать try-catch или монады и проверку данных (нулевые проверки и т. д.). Если у меня есть отдельные побочные эффекты и бизнес-логика, я могу справиться со сложностями каждого из них по отдельности и, таким образом, упростить свой код.

9. Баланс между качеством, временем и стоимостью

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

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

10. Качество — это баланс производительности, отказоустойчивости, безопасности, ремонтопригодности, наблюдаемости и надежности.

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

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

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

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

Как писать код

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

11. Красно-зеленый рефакторинг

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

Зачем тратить 10 минут на вопросы, если можно потратить 3 дня на разработку не того? ;-)

12. Враг номер один продуктивности и потока — незапланированная работа.

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

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

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

13. Сделайте рефакторинг сейчас, вы не сделаете этого позже

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

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

14. Не торопитесь

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

Моей инстинктивной реакцией было бы спешить закончить его и тем самым срезать углы. Это неправильный выбор! Позволь мне объяснить.

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

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

15. Улучшение повседневной работы важнее, чем сама повседневная работа.

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

16. Планируйте ~ 4 часа в день в IDE

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

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

Однако вы должны знать это число и соответствующим образом скорректировать свои оценки. Если вы подсчитали, что на разработку определенной истории у вас уходит 2 дня, вам нужно оценить 4. Потому что для 2 дней разработки вам нужно 4 дня разработки по 4 часа в день. (То же самое относится и к историям). Я бы даже рекомендовал поделиться этим номером с вашими PO / BA для прозрачности.

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

Кто я такой, чтобы рассказывать вам об отличном коде? Я просто парень, который любит делиться своими мыслями.

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