19. Про backend документацію. Open API. Swagger. Тести Open API. Json:API vs GraphQL vs REST.
Відео версія
(YouTube - для зворотнього зв'язку)
Посилання
- https://github.com/DarkaOnLine/L5-Swagger - OpenAPI + swagger для Laravel
- https://github.com/hotmeteor/spectator - тести OpenAPI
- https://github.com/butthurtdeveloper/OpenAPIAttributes/tree/main - Self made обгортка до zitcode OpenApi атрибутів
Документація проєкту - це дуже дорого. Саме тому на більшості проєктів її нема.
Код краще підходить для документації, ніж будь-яка мова.
Підтримка документації - це дуже дорого.
Правильно написані тести - це ще один дуже гарний шар документації.
Якщо ви все ж пишете документацію - її ніхто не прочитає. Читати документацію - це складна навичка.
Якщо розробляєте щось, від чого залежить життя або фінанси людей, - документація обов'язкова. Це також питання юридичної безпеки.
"Реальної" документації потребує не код, а бізнес-логіка. Код вже показує "як працює". Документація повинна дати підказку на питання "чому працює так".
OpenAPI (Swagger) - специфікація для опису REST вебсервісів. Він нормально конвертується в інші специфікації!
PHP8 Attributes роблять опис OpenAPI дуже компактним. Атрибути - це звичайні класи, тому їх можна вільно наслідувати або створювати свої, роблячи досвід опису ще компактнішим і більш орієнтованим до потреб проєкту.
Spectator дозволяє тестувати OpenAPI специфікацію. Це просто ідеальне рішення - розробники виконують той же самий обсяг роботи, що й для тестування, і паралельно отримують завжди актуально протестовану документацію.
OpenAPI - рішення краще, ніж Postman у кожного локально. Розробник робить той же набір дій, що й для себе локально, але одразу для всієї команди (QA, frontend devs, інші розробники).
Swagger дуже зручний у випадку "чистих" backend розробників. Він дозволяє швидко тестувати виконану роботу і мінімізувати втрати на комунікацію з розробниками клієнта.
REST або Json:API обирайте самі. Ви повинні знати про специфікації API.
GraphQL - специфічне рішення з купою проблем. Добре подумайте, чи дійсно воно вам потрібне.
#[BaseScheme(
resource: CurrentUserInfoResource::class,
properties: [
new PropertyString(property: 'name'),
new PropertySlug(),
]
)]
#[BaseScheme(
resource: LoginUserResource::class,
properties: [
new PropertyString(property: 'token'),
]
)]
#[BaseScheme(
resource: LoginRequest::class,
properties: [
new PropertyString(
property: 'email',
example: 'example@example.com'
),
new PropertyString(
property: 'password',
example: 'Pas$word1'
),
]
)]
#[ApiGet(
path: '/api/v1/me',
tags: ['Auth'],
description: 'Get current user info',
auth: true
)]
#[ResponseJsonSuccess(CurrentUserInfoResource::class)]
#[ApiPost(
path: '/api/v1/login',
tags: ['Auth'],
description: 'Login user'
)]
#[ResponseUnauthorized]
#[ResponseJsonSuccess(LoginUserResource::class)]
#[RequestJson(LoginRequest::class)]
#[ApiGet(
path: '/api/v1/me',
tags: ['Auth'],
description: 'Get current user info',
auth: true
)]
#[ResponseJsonSuccess(CurrentUserInfoResource::class)]