Чистота та лаконічність — чи не найголовніші складові філософії написання коду. Цей підхід може значно спростити та покращити роботу розробників і, як результат — підвищити якість кінцевого продукту. Досягти цього допоможе правильне коментування коду та підготовка його документації.
У цій статті я поясню, як легко виконати документування коду. Матеріал неодмінно стане в нагоді тим, хто нещодавно почав практикувати програмування на Python. Більш досвідчені фахівці згадають деякі важливі моменти в організації своєї роботи.
Навіщо вам документувати код
Будь-який проєкт стартує з отримання від продакт-команди реквайроментів. Спочатку вони досить незрозумілі. Перше завдання — перетворити ці продакт-реквайроменти на документацію бізнес-флоу, яка в кінцевому результаті стане основою реальних задач девелоперів.
Для конкретизації вимог потрібно поспілкуватися з продакт-командою, запитати стосовно кожного пункту реквайроментів, уточнити різні деталі. Саме так у вас з’явиться база для написання коду.
Тепер уявімо, що до проєкту потрапила нова людина, якій все виглядає незнайомим та незрозумілим. Бізнес-логіка, технології, конкретні кроки — все це викликає у фахівця багато питань та потребує від вас чимало зусиль для пояснень. Але цей час на роз’яснення можна заощадити завдяки задокументованому коду. Новий спеціаліст зможе сам почитати код, спробує самостійно зрозуміти його та перейти до написання фіч.
Коли треба починати коментувати код
Найефективніше та найпростіше документування коду — під час його імплементації.
Коли у вас сформовані більш-менш чіткі бізнес-реквайроменти і ви переходите до створення фактично Proof of Concept, одразу починайте документувати код.
Адже ви тільки-но обговорювали з продакт-командою деталі проєкту та створювали фрагменти майбутньої реалізації. Сформоване розуміння продукту легше додавати до коду. Так вже на ранніх стадіях проєкту ви зробите його зрозумілим для всіх залучених розробників.
Батько Python Гвідо ван Россум казав: «Код набагато частіше читається, аніж пишеться». Ми всі це прекрасно знаємо, але ж наскільки це дійсно важливо! Інколи розробники забувають про це, бо не бачать вигоди від цього саме в момент створення продукту. І дарма.
Це дещо схоже на написання тестів. Вони не допомагають покращити продукт прямо зараз, але значною мірою впливають на подальші процеси і набувають все більшої цінності з розвитком та масштабуванням проєкту.
Основні кроки в документації коду
- Додавання док-стрінгів
Це можна робити у функціях, класах, методах, змінних. Так ви зможете пояснити, що виконують конкретні елементи коду. Зробити це можна по-різному. Я, наприклад, після отримання документації та коментарів від продакт-команди часто додаю їх фрагменти у моделі чи класи — так зручніше.
- Коментарі до будь-яких незрозумілих частин коду
Інколи певний фрагмент може відпрацьовувати лише одну маленьку бізнес-логіку, яка незнайома сторонньому розробнику. Коментарі допоможуть зрозуміти, чому все зроблено саме так. Ці пояснення слід вписувати одразу після коду.
- Анотації типів
Допомагає зробити код більш зрозумілим та лаконічним. При знайомстві з функцією із задекларованими типами стає очевидно, що вона являє собою та які типи аргументів варто додавати.
- Опис бізнес-логіки
Писати варто не лише про те, що робить конкретна функція, але й про те, як вона працює у реальному флоу проєкту, яку частину виконує ця функція у наявному флоу.
- Додавання Unit-тестів
Тести самі по собі можуть слугувати видом документації. Розробник зрозуміє функціонал проєкту, просто читаючи гарно написані тести. Тим паче, коли кожний тест-кейс задокументовано.
І ще одна порада: якщо ви використовуєте Django-аплікації та Django REST Framework, то обов’язково застосовуйте Swagger.
Детальніше про це я розповім трохи згодом.
Перейдемо до прикладів
Чимало розробників не знають, де шукати методи документування коду, style guide та best practices по цій темі. Google допоможе! Вбиваємо у пошуковик google python style guide example — й отримуємо чіткі рекомендації.
Один із прикладів документування коду ви можете побачити на ілюстрації нижче. На початку модуля є multiline string. Перший рядок — це короткий опис самого документу. Потім маємо детальне пояснення, приклади запуску модулю, якщо це скрипт, а також можливі описання атрибутів та змінних в модулі.
На наступній ілюстрації зображена документація до функцій. Зверніть увагу: тут не використовується анотація типів, хоча всередині функції є їхній опис. Я би робив його саме у декларації аргументів:
А ще важливо, що серед докстрінг-форматів у PyCharm один — саме від Google. Особисто я обрав його за замовчуванням. При написанні функції достатньо натиснути Ctrl+Enter — й отримати автозаповнення у стилі Google:
Django REST Framework та drf-spectacular
І ось тепер піде мова про Swagger. У цьому випадку вам знадобиться drf-spectacular. Це відносно свіжий пекедж, він постійно оновлюється та обслуговується. Саме на нього ми в нашій команді замінюємо більшість застарілих аналогів. У drf-spectacular є декілька основних функцій, які побудовані навколо трьох цілей:
- Максимум даних
Завдяки drf-spectacular можна діставати якомога більше інформації з наявних функцій та класів. Щоправда, це стосується тільки Django REST Framework.
- Додавання функціоналу при кастомізації
Маючи drf-spectacular, у вас є додаткові можливості для більш елегантного та розширеного документування. Дуже корисно для кастомізованих елементів, наприклад, серіалайзеру. Якщо ви змінюєте його, припустимо, через використання методу to representation, то drf-spectacular може не підхопити ці зміни автоматично. Тоді з’являється помилка про відсутність полів цього серіалайзеру. В такому разі ви повинні задекларувати в API view або ViewSet інший серіалайзер, а той, що з методом to representation, використовувати саме у коді:
Завдяки цьому у ViewSet не буде серіалайзеру з методом to representation. Ви зможете декларувати всі філди, які використовуєте в цьому методі для повернення даних:
- Генерація схеми для популярних клієнт-генераторів
Пекедж drf-spectacular використовує всі закони OpenAPI. Це набір правил, які описують створення будь-якого RESTful-сервісу. Для цього використовується Swagger UI.
Щодо технічних особливостей drf-spectacular, то він підтримує багато пекеджів, перелік яких наведено на наступній ілюстрації. Також він вимагає Python не раніше версії 3.6 та одну з декількох версій Django та Django REST Framework.
Корисний функціонал drf-spectacular
- @extend_schema
Цей декоратор дозволяє кастомізувати багато чого в ендпоінтах. Уявімо лістінг фільмів, де ви додаєте у методі get queryset певні фільтри. Якщо клієнт надасть у query-параметрах додаткові значення, наприклад, для вибірки знятих після 1986 року фільмів, то drf-spectacular не знайде інформацію в коді про можливість такої фільтрації. Однак через аргумент ви можете додати необхідні API-параметри з цього ендпоінту. Можна вказати назву параметру, тип, локації, описи, приклади та формат використання цього query-параметру. До того ж тут є description для документування методів із ViewSet чи View.
- @extend_schema_view
Здебільшого за наявності ViewSet не потрібно змінювати метод list, як це зроблено в попередньому прикладі. Ви просто викликаєте цей метод зверху рядка. Проте можна зробити це іншим чином — із використанням extend_schema_view, яка буде кріпитися до ViewSet. Так можна вказувати аргумент, який метод потрібно декорувати. По суті, це те саме, але перший приклад стосувався методу, а цей — самої View.
- @extend_schema_field
Цей функціонал потрібен для кастомізації філдів серіалайзеру. Сам по собі drf-spectacular не знає, який тип об’єкту повертається та які маніпуляції є у цьому методі. Однак ми можемо декорувати серіалайзер метод field, скажімо, для вказання типу, котрий буде виводитися, наступним чином:
- @extend_schema_serializer
Дозволяє заексклюдити філди і додати екземпли. В прикладі я це не використовував, але функціонал вважається основним для drf-spectacular.
- extensions
При модифікаціях аутентифікації та авторизації потрібно додавати до проєкту extensions. Таким чином drf-spectacular побачить зміни у цих процесах, що про поговоримо далі.
Модифікація аутентифікації
Щоб показати цей процес, розглянемо приклад із реальної практики. Зауважте, тут є повний опис причин додавання цього файлу. Це допоможе новому розробнику одразу розібратися в ситуації.
У наведеному проєкті extension аутентифікації побудований так: є замодіфаєна та кастомізована JSONWebTokenAuthentication, вказано, як виглядає аутентифікація.
Це навіть не потрібно використовувати у сеттінгах drf-spectacular. Коли Python-інтерпретатор «бачить» клас із наслідуванням від OpenAPI від extension, він замінює базовий за замовчування extension на задекларований у коді.
Підключення drf-spectacular
Пекедж drf-spectacular підключається дуже просто і швидко та вже «з коробки» надає вичерпну інформацію. До речі, ви можете зайти на сторінку Swagger, і я покажу, як це виглядає на прикладі.
Перед вами — API календаря проєкту. Тут є кілька ендпоінтів, серед яких, наприклад, event-exclusions. У ньому зібрано повний лістінг усіх exclusions цього типу.
У першому пункті є документація з описом бізнес-логіки. Кожен event-exclusion — це сутність, яка містить функціонал та керує тим, як можуть бути переглянуті віжуал-івенти. Вказано і те, що кожен event-exclusion підключений до конкретного віжуал-івенту.
Також маємо параметри, які клієнт може додавати до Query для отримання конкретних event-exclusions. Наприклад, можна знайти event-exclusions, де закенселений Event Template.
Ще є респонси з кодами по кожній відповіді. Наприклад, із кодом 200 приходить відповідь такого формату:
Так виглядає респонс серіалайзеру EventExclusionViewSet. При цьому всередині ViewSet немає методу list. Тому я задекорував extend_schema_view, додав їй аргумент list та функцію extend_schema, яка працює так само, як би я це зробив до метода.
Далі видно той же параметр is_cancelled, який описано вище. У нього є опис, тип, локація та приклад. Це все було зроблено за наявності методу get_queryset, в якому виконується фільтрація queryset відповідно до вхідних query-параметрів.
Я вбачаю прямий зв’язок між кількістю розробників на проєкті та користю від документації. Чим більше девелоперів з’являється в команді, тим більше ви витрачаєте часу на пояснення деталей. Звичайно, на початку від вас знадобиться деяка допомога. Але маючи задокументований код, вам не потрібно разом з новоприбулими розробниками сидіти й читати його, розбираючи всі деталі бізнес-логіки продукту. Лаконічно написаний та добре задокументований код прискорить швидкість навчання новачка на проєкті.
Мені зустрічались чимало погано продуманих із цієї точки зору Django-проєктів. Інколи там було стільки незрозумілого! Наприклад, одного разу я знайшов у файлі serializer.py кастомізовані серіалайзери з кастомними методами типу retrieve, які викликаються у самій View. Усе працює, як із to representation, але без використання стилю Django REST Framework. Спеціаліст, добре знайомий із Django та DRF, взагалі не розуміє причин такої логіки. Це подібно до того, як писати у Django-застосунку FastAPI-код…
До чого я веду: будьте відповідальними і під час написання коду обов’язково детально документуйте його. Ці зусилля у майбутньому збережуть час та нерви вам і вашим колегам та покращать якість кінцевого продукту.
Цей матеріал – не редакційний, це – особиста думка його автора. Редакція може не поділяти цю думку.
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: