Для бэкэнд-веб-разработчиков.

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

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

Требования

1. Реализует ли код все функциональные требования, описанные в пользовательской истории?

2. Удовлетворяет ли код нефункциональным требованиям, таким как производительность или безопасность? Нефункциональные требования в рассказе вообще не упоминаются? В таком случае они уточняются у архитектора или у заказчика?

Ремонтопригодность

3. Все ли интерфейсы, классы и другие типы размещены на соответствующем уровне приложения в соответствии с архитектурой Onion/Clean?

4. Является ли код повторной реализацией колеса? Должен ли он быть заменен некоторой существующей логикой, предоставляемой какой-либо сторонней библиотекой?

5. Реализованная логика или некоторые ее части уже существуют где-то в кодовой базе?

6. Правильно ли выбрана область действия для интерфейса и реализации в контейнере внедрения зависимостей?

7. Будут ли реализованные функции вести себя детерминировано (всегда возвращать одни и те же выходные данные для одних и тех же входных данных)?

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

9. Существует ли тесная связь между классами, которая затруднит повторное использование кода?

10. Используются ли объекты-значения вместо примитивных типов данных, чтобы избежать проблемы одержимости примитивами?

11. Соответствует ли каждый реализованный компонент, такой как функция, класс, интерфейс или модуль, принципу единой ответственности?

12. Расширяется ли существующая функциональность с помощью декораторов, методов аспектно-ориентированного программирования (принцип открытого-закрытого) или модифицируется на месте?

13. Правильно ли реализованы механизмы синхронизации потоков при доступе к одноэлементным объектам в веб-приложениях?

14. Используются ли неизменяемые типы данных вместо изменяемых, когда это возможно, чтобы избежать побочных эффектов?

15. Добавлено ли ведение журнала с правильными уровнями ведения журнала в важные места кода, которые следует отслеживать?

Производительность

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

17. Распараллелены ли длительные операции между всеми доступными ядрами для эффективного использования ресурсов машины?

18. Выполняет ли код много распределений объектов в куче, оказывая давление на сборщик мусора?

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

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

21. Выполняет ли код все вызовы базы данных, ввод-вывод или другие блокирующие вызовы асинхронно?

22. Использует ли код большую часть пула потоков вместо создания новых потоков?

23. Правильно ли выбран баланс между нормализацией и денормализацией при реализации дополнительных таблиц базы данных?

24. Правильно ли добавляются или перерабатываются индексы, если запрос на вытягивание содержит новые SQL-запросы?

25. Возникает ли проблема N+1 при извлечении данных из базы данных с использованием фреймворков ORM?

26. Установлен ли в хранимых процедурах правильный уровень изоляции транзакций?

27. Возвращают ли запросы SQL избыточные данные из базы данных, которые не нужны коду приложения? Используются ли такие вещи, как SELECT * или около того?

Модульное и интеграционное тестирование

28. Полностью ли добавленная логика покрыта модульными тестами?

29. Когда есть исправление в логике, есть ли изменения в соответствующем модульном тесте?

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

31. Реализован ли каждый модульный тест в соответствии с принципами FIRST?

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

33. Был ли добавлен интеграционный тест, по крайней мере, для сценария счастливого пути реализованной функции?

34. Все ли зависимости объекта SUT (sсистемы under test) имитируются, чтобы модульный тест случайно не стал интеграционным тестом? и быстро бегает?

35. Изолированы ли модульные или интеграционные тесты друг от друга?

Конечные точки API

36. Выбираются ли HTTP-глаголы, такие как GET, POST, PUT, DELETE, в зависимости от того, что на самом деле делает конечная точка?

37. Отвечает ли каждая конечная точка API только за выполнение одной бизнес-операции, а не нескольких?

38. Возвращает ли конечная точка API правильный код состояния? Например, возвращает ли он 401 вместо 500 для несанкционированного запроса?

39. Сжимаются ли большие ответы перед возвратом их вызывающему абоненту?

40. Защищена ли каждая конечная точка API политиками аутентификации и авторизации?

41. Позволяет ли API, возвращающий большой список объектов, фильтровать и разбивать на страницы?

42. Является ли конечная точка GET API идемпотентной?

43. Используются ли существительные вместо глаголов в именах конечных точек API?

Критические изменения

44. Есть ли в конечной точке API критические изменения, такие как переименование API, удаление или переименование его параметров?

45. Есть ли критическое изменение полезной нагрузки сообщения (в случае использования брокеров сообщений), например удаление или переименование его свойств?

46. ​​Повлияют ли изменения в схеме базы данных, такие как удаление столбцов или таблиц, на другие службы системы?

Окружающая среда

47. Сколько ЦП и ОЗУ потребляет код в запросе на вытягивание во время его выполнения? Будет ли в средах, в которых будет развернут код (QA, UAT, Production), достаточно ЦП и ОЗУ для эффективного выполнения кода?

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

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

49. Была ли документация обновлена, чтобы отразить новые изменения кода (документация API, документация по архитектуре или дизайну и т. д.)?

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

Заключение

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

Спасибо за прочтение. Если вам понравилось то, что вы прочитали, ознакомьтесь с этой историей ниже:



Также подумайте о том, чтобы стать участником Medium.

Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу