中文版 | 日本語版 | 한국어 | English | Português
Тогда как для некоторых разработка нового проекта - это прогулка по парку, то для других поддержка этого проекта - полнейший кошмар. Здесь представлен список советов, которые мы нашли, написали, собрали и которые, как мы думаем, прекрасно подходят к большинству JavaScript проектов в elsewhen. Если вы хотите поделиться лучшей практикой или считаете, что какой-нибудь из советов стоит убрать, можете спокойно сообщить нам об этом.
🔥 Попробуйте наш минималистичный react redux проект на Flow с горячей заменой кода (hot reloading) и серверным рендерингом (SSR, server-side rendering).
- Git
- Документация
- Окружения
- Зависимости
- Тестирование
- Структура и Именование
- Оформление кода
- Логирование
- API
- Лицензирование
Набор правил, которые следует иметь ввиду:
-
Разрабатывайте в
feature/*
ветке.Зачем:
Таким образом вся работа выполняется изолированно в отдельной ветке, а не в главной. Это позволит создать множество запросов на слияние (pull requests) без путаницы. Вы можете продолжить разработку без загрязнения
master
ветки потенциально нестабильным и незаконченным кодом. узнать больше... -
Откалывайте ветку от
develop
Зачем:
Чтобы быть уверенным, что код в
master
ветке практически всегда собирается без проблем, и, в основном, может быть использован для релизов (это может быть излишним для некоторых проектов). -
Никогда не выкладывайте (push) коммиты напрямую в
develop
илиmaster
ветки. Создавайте Запрос на Слияние (Pull Request).Зачем:
Так члены команды получат оповещение, что работа над новой функцией (feature) завершена. Также это облегчит процесс рецензирования кода (code review) и предоставит площадку для обсуждения предложенной функции.
-
Обновляйте вашу локальную
develop
ветку и делайте интерактивное перебазирование (rebase) перед тем как выкладывать (push) свою новую функцию и создавать Запрос на Слияние (Pull Request).Почему:
Перебазирование сольет (merge) коммиты из запрошенной ветки (
master
илиdevelop
) в текущую и вставит те, которые вы сделали локально, в самый конец истории без создания коммита слияния (merge commit), если не возникнут конфликты. В результате чего получим линейную и чистую историю изменений. узнать больше... -
Разрешите потенциальные конфликты в процессе перебазирования (rebase) перед тем как создавать Запрос на Слияние (Pull Request).
-
Удалите локальные и удаленные (remote) ветки после сливания (merge).
Зачем:
Чтобы не загромождать ваш список веток мертвыми ветками. Это гарантирует, что вы сольете (merge) вашу ветку обратно (
master
илиdevelop
) только один раз.feature/*
ветки должны существовать пока не будет завершена разработка. -
Перед созданием Запроса на Слияние (Pull Request) убедитесь, что ваша
feature/*
ветка успешно собирается и все тесты проходят успешно, включая проверки на оформление кода.Зачем:
Вы собираетесь добавить ваш код в стабильную ветку. Если тесты в вашей
feature/*
ветке не проходят, то с большой долей вероятности стабильная ветка тоже не сможет собраться. Дополнительно надо будет запустить проверку на оформление кода перед созданием Запроса на Слияние (Pull Request). Это улучшит читаемость кода и уменьшит шанс, что изменения в оформлении смешаются с реальными изменениями. -
Используйте этот
.gitignore
файл.Почему:
Он уже включает в себя список системных файлов, которые не надо посылать вместе с вашим кодом в удаленный репозиторий. К тому же он исключает не только файлы и папки с настройками для большинства используемых редакторов кода, но и самые распространенные папки с зависимостями.
-
Обезопасьте ваши
develop
иmaster
ветки.Зачем:
Это защитит ваши готовые для релиза ветки от получения неожиданных и необратимых изменений. Узнать больше: Github, Bitbucket и GitLab
Исходя из большинства причин, описанных выше, стоит использовать Рабочий процесс с использованием feature/*
ветки с Интерактивным Перебазированием (rebase) и некоторые элементы Gitflow (наименования и использование develop ветки). Основные шаги следующие:
-
Для нового проекта инициализируем git репозиторий в папке с проектом. Для последующих новых функций/изменений этот шаг нужно игнорировать.
cd <project directory> git init
-
Создаем новую
feature/bug-fix
ветку.git checkout -b <branchname>
-
Делаем изменения.
git add <file1> <file2> ... git commit
Пояснение:
git add <file1> <file2> ...
- необходимо добавлять только те файлы, которые вносят небольшие и последовательные изменения.git commit
запустит редактор, который позволит разделить в сообщении коммита краткое описание от полного.Больше об этом в разделе 1.3.
Совет:
Также вместо
git add
вы можете использоватьgit add -p
, который позволит последовательно просмотреть изменения, представленные в коммите, и решить - включать их в коммит или нет. -
Синхронизируйтесь с удаленным репозиторием, чтобы получить изменения, которые вы пропустили.
git checkout develop git pull
Зачем:
Это даст вам шанс решить конфликты на вашей локальной машине во время перебазирования (rebase) перед созданием Запроса на Слияние (Pull Request), содержащего конфликты.
-
Вливайте в вашу
feature/*
ветку последние изменения изdevelop
ветки, используя интерактивное перебазирование (rebase).git checkout <branchname> git rebase -i --autosquash develop
Пояснение:
Вы можете использовать
--autosquash
, чтобы объединить ваши коммиты в один. Никто не хочет создавать множество коммитов ради одной новой функции вdevelop
ветке. узнать больше... -
Если у вас нет конфликтов, пропустите этот шаг. Если же они возникли, решите их и продолжайте перебазирование (rebase).
git add <file1> <file2> ... git rebase --continue
-
Отправьте (push) вашу ветку в удаленный репозиторий. Перебазирование (rebase) меняет историю коммитов, поэтому вам придется использовать
-f
, чтобы форсировать изменения в удаленную ветку. Если кто-то еще работает в вашей ветке, используйте менее деструктивный флаг--force-with-lease
.git push -f
Почему:
Когда вы делаете перебазирование (rebase), вы меняете историю вашей
feature/*
ветки. Как результат, Git отклонит обычныйgit push
. Поэтому вам надо использовать флаг-f
или--force
. узнать больше... -
Создайте Запрос на Слияние (Pull Request).
-
Запрос на Слияние (Pull Request) будет принят, слит (merge) и закрыт рецензентом.
-
Удалите вашу локальную
feature/*
ветку, если работа в ней завершена.git branch -d <branchname>
Удалите все локальные ветки, которых больше нет в удаленном репозитории.
git fetch -p && for branch in `git branch -vv --no-color | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
Хороший гайдлайн по создании коммитов и следование ему облегчит работу с Git и сотрудничество с другими разработчиками. Вот несколько правил большого пальца (источник):
-
Разделите краткое описание коммита от основного, используя разрыв строки между ними.
Зачем:
Git достаточно умный, чтобы распознавать первую строку вашего сообщения коммита, как краткое описание. По факту, если вы попробуете
git shortlog
вместоgit log
, вы увидите длинный список сообщений коммитов, состоящий только из идентификатора (id) коммита и краткого описания. -
Ограничьте краткое описание 50 символами, а основное описание - 72 символами.
Зачем:
Коммиты должны быть краткими и максимально сфокусированными; это не место для многословия. узнать больше...
-
Начните краткое описание с заглавной буквы.
-
Не заканчивайте краткое описание точкой.
-
В кратком описании используйте повелительное наклонение.
Почему:
Вместо того, чтобы писать в сообщениях что сделал разработчик, лучше относиться к этим сообщениям, как к инструкциям что произойдет после того, как коммит попадет в ветку. узнать больше...
-
Используйте основное описание, чтобы объяснить что и почему вместо как.
- Используйте этот шаблон для
README.md
, свободно добавляйте отсутствующие разделы. - Для проектов с множеством репозиториев укажите ссылки на них в соответствующих
README.md
файлах. - Постоянно обновляйте
README.md
по мере развития проекта. - Пишите комментарии в коде. Старайтесь сделать код максимально прозрачным, чтобы было понимание что именно задумывалось в каждом основном фрагменте.
- Если открыта дискуссия на github или stackoverflow по поводу кода или подхода, который вы используете, оставьте ссылку на эту дискуссию в вашем комментарии.
- Не используйте комментарии в качестве оправдания плохого кода. Сохраняйте ваш код в чистоте.
- Не используйте чистый код в качестве оправдания полного отсутствия комментариев.
- Обновляйте ваши комментарии по мере развития проекта.
-
Определите отдельные
development
,test
иproduction
окружения, если есть такая необходимость.Зачем:
Различные данные, токены, API, порты и т.п. могут быть использованы в разных окружениях. Например, вам может понадобиться изолированный
development
режим, для того чтобы вызывать тестовое API, которое будет возвращать предсказуемые данные, делая автоматическое и ручное тестирование в разы проще. Или вам нужна Google аналитика (Google Analytics) только вproduction
окружении и т.д. узнать больше... -
Загружайте ваши специфичные для развертывания конфигурации из переменных окружения и никогда не добавляйте их, как константы, в код проекта. Пример файла.
Почему:
Вы храните токены, пароли и другую важную информацию в конфигурации. Ваша конфигурация должна быть корректно отделена от основной части приложения, как будто ваш код может стать публичным в любое время.
Как:
Используйте
.env
файлы для хранения важных данных. Обязательно добавьте их в.gitignore
, чтобы исключить попадание в Git, взамен создайте коммит с.env.example
файлом, который будет служить как шаблон для разработчиков. Для релизного стенда вы должны устанавливать переменные окружения стандартным методом. узнать больше... -
Рекомендуется валидировать переменные окружения перед запуском приложения. Данный пример использует
joi
для валидации представленных параметров.Зачем:
Это поможет сэкономить другим часы поиска проблемы.
-
Установите вашу версию Node.js в
engines
в файлеpackage.json
.Зачем:
Это позволит другим разработчикам узнать, какая версия Node.js используется в проекте. узнать больше...
-
Дополнительно используйте
nvm
и создайте.nvmrc
в корне вашего проекта. Не забудьте упомянуть это в документации.Зачем:
Любой, кто использует
nvm
, сможет спокойно вызватьnvm use
, чтобы переключиться на подходящую версию Node.js. узнать больше... -
Хорошей идеей будет настроить
preinstall
скрипт, который будет проверять версии Node.js и npm.Почему:
Некоторые зависимости могут не установиться при использовании новых версий npm.
-
Используйте Docker образ, если можете.
Зачем:
Это даст вам консистентное окружение во всем рабочем процессе. Без необходимости копаться с зависимостями и конфигами. узнать больше...
-
Используйте локальный модули вместо глобально установленных.
Почему:
Если вы будете использовать глобальные модули, то вам будет сложно поделиться вашим инструментом с коллегами, так как на их системах должны будут установлены эти же модули. Локально модули решают эту задачу путем автоматического добавления всех необходимых зависимостей при установке инструмента.
-
Убедитесь, что ваши коллеги получат точно такие же зависимости, что и вы.
Почему:
Потому что код должен вести себя предсказуемо и идентично тому, как он выполняется на машине разработчика. узнать больше...
Как:
Используйте
package-lock.json
вnpm@5
или версией выше.Если нет npm@5:
То вы можете использовать
Yarn
, но не забудьте упомянуть об этом вREADME.md
. Файлыyarn.lock
иpackage.json
должны содержать одни и те же версии после каждого обновления зависимостей. узнать больше...Если вам не нравится
Yarn
:Печально. Для старших версий
npm
используйте—save --save-exact
при установке новых зависимостей и создайтеnpm-shrinkwrap.json
перед публикованием пакета. узнать больше...
-
Следите за вашими текущими пакетами:
npm ls --depth=0
. узнать больше... -
Проверьте ваши пакеты на наличие неиспользуемых или ненужных:
depcheck
. узнать больше...Зачем:
Вы могли добавить неиспользуемую библиотеку в ваш код и, тем самым, увеличить итоговый размер релизной сборки. Найдите неиспользуемые зависимости и избавьтесь от них.
-
Перед использованием зависимости проверьте её статистику скачиваний, чтобы узнать как часто она используется в сообществе:
npm-stat
. узнать больше...Зачем:
Частое использование подразумевает большое количество соавторов, что обычно означает лучшую поддержку и все это, в итоге, приводит к быстрому нахождению и исправлению багов.
-
Перед использованием зависимости проверьте, есть ли у нее хороший, зрелый релизный цикл с большим числом людей, ведущих разработку пакета:
npm view async
. узнать больше...Зачем:
От большого количества соавторов не будет пользы, если люди, ведущие разработку пакета, не будут сливать (merge) исправления и патчи вовремя.
-
Если есть необходимость в малоизвестной зависимости, обсудите это с командой перед использованием.
-
Всегда проверяйте, что ваше приложение работает с последними версиями зависимостей без поломок:
npm outdated
. узнать больше...Зачем:
Обновления зависимости иногда могут содержать переломные изменения (breaking changes). Всегда проверяйте релизные примечания (release notes), когда появляется новое обновление. Обновляйте ваши зависимости по очереди, это сделает процесс поиска потенциальных проблем проще. Используйте такой крутой инструмент, как npm-check-updates.
-
Проверьте, есть ли у пакета известные уязвимости безопасности инструментом Snyk.
-
Используйте
test
окружение, если есть необходимость.Почему:
Хотя в некоторых случаях сквозного (end-to-end) тестирования в
production
окружении будет достаточно, есть несколько исключений. Например, при тестировании вам не нужно отправлять аналитические данные, чтобы не забить тестовыми данными чью-нибудь панель управления (dashboard). Другой пример: у вашего API может быть ограничение на количество запросов вproduction
окружении и ваши тестовые запросы могут заблокироваться, если лимит будет превышен. -
Размещайте ваши файлы с тестами рядом с тестируемыми модулями, используя следующее соглашение о наименовании:
*.test.js
или*.spec.js
, напримерmoduleName.spec.js
.Зачем:
Вам не придется копаться в структуре папок, чтобы найти файл модульного тестирования (unit test). узнать больше...
-
Размещайте дополнительные файлы с тестами в отдельной папке, чтобы исключить путаницу.
Почему:
Некоторые файлы с тестами невозможно отнести к какому-либо файлу с реализацией. Такие тесты надо размещать в папке, где другие разработчики смогут легко их найти: папка
__test__
. Имя папки__test__
теперь является стандартом и многие JavaScript фреймворки для тестирования его используют. -
Пишите тестируемый код, избегайте побочных эффектов, выносите побочные эффекты, пишите чистые функции.
Зачем:
Бизнес-логику лучше тестировать как отдельные единицы. Вам надо "минимизировать влияние случайных факторов и недетерминированных процессов на надежность вашего кода". узнать больше...
Пояснение:
Чистая функция - это функция, которая всегда возвращает одинаковый результат, когда она вызывается с тем же набором аргументов. И, наоборот, нечистая функция - это функция, у которой есть побочные эффекты, и/или которая зависит от внешних условий, чтобы вернуть значение. Это делает их менее предсказуемыми. узнать больше...
-
Используйте статическую проверку типов.
Зачем:
Иногда вам может понадобиться Статическая проверка типов. Она привнесет некоторый уровень надежности вашему коду. узнать больше...
-
Запускайте тесты локально перед тем как создавать Запрос на Слияние (Pull Request) в
develop
ветку.Зачем:
Вам не захочется оказаться тем человеком, который сломал сборку в ветке, готовой для релиза. Запускайте тесты после перебазирования
rebase
и перед отправкой (push)feature/*
ветки в удаленный репозиторий. -
Задокументируйте инструкцию по работе с тестами в соответствующем разделе вашего
README.md
файла.Зачем:
Вы оставите полезное примечание для других разработчиков, DevOps экспертов, тестировщиков или кого-либо еще, кому повезет работать с вашим кодом.
-
Структурируйте ваши файлы вокруг продуктовых функций / страниц / компонентов, а не ролей. Также размещайте файлы с тестами рядом с файлами, к которым они относятся.
Плохо
. ├── controllers | ├── product.js | └── user.js ├── models | ├── product.js | └── user.js
Хорошо
. ├── product | ├── index.js | ├── product.js | └── product.test.js ├── user | ├── index.js | ├── user.js | └── user.test.js
Почему:
Вместо длинных списков файлов вы получите небольшие модули, которые инкапсулируют только одну обязанность и включают в себя тесты и прочие связанные файлы. Навигация в проекте станет гораздо легче, так как нужные файлы будут находиться рядом, сгруппированные по модулям.
-
Размещайте дополнительные файлы с тестами в отдельной папке, чтобы избежать путаницы.
Почему:
Это сэкономит время другим разработчикам или DevOps экспертам в вашей команде.
-
Используйте папку
./config
и не создавайте разные файлы с конфигурациями для разных окружений.Почему:
Когда вы разбиваете общий файл конфигурации на отдельные файлы (база данных, API и т.п.), то размещение этих файлов в папке с прозрачным именованием, как
config
, имеет смысл. Просто запомните: не создавайте файлы с конфигурациями для разных окружений. Это сложно масштабировать, так как, чем больше создается разных стендов для развертывания (deploys) приложения, тем сложнее будет придумывать новые имена для окружений, чтобы создать файл конфигурации. Для файлов конфигурации нужно использовать значения из переменных окружения. узнать больше... -
Размещайте ваши скрипты в папке
./scripts
. Это включаетbash
иnode
скрипты.Зачем:
Скорее всего у вас будет больше, чем один скрипт в проекте: для релизной сборки, сборка для разработки, наполнение базы данных, синхронизация базы данных и т.д.
-
Размещайте выходные файлы сборки в папке
./build
. Добавьтеbuild/
в.gitignore
.Почему:
Именуйте папку как хотите,
dist
тоже подойдет. Но стоит убедиться, чтобы имя было консистентно для всей команды. В эту папку будут попадать в основном сгенерированные файлы (упакованные, компилированные, транслированные) или просто перемещенные. То, что вы сможете сгенерировать, должно генерироваться и у ваших коллег, поэтому нет смысла добавлять эти файлы к кодовой базе (коммитить) и отправлять в удаленный репозиторий. Если вам это не нужно.
-
Используйте stage-2 и выше (современный) синтаксис JavaScript для новых проектов. Для старых проектов стоит придерживаться синтаксиса проекта, если вы не собираетесь его модернизировать.
Почему:
Stage-2 в скором времени станет частью официального стандарта с небольшими изменениями. В разработке можно задействовать транспилеры, чтобы уже сейчас использовать преимущества нового синтаксиса. Но решать вам.
-
Включите проверку на оформление кода в процесс сборки.
Зачем:
Поломка сборки - это один из инструментов, чтобы заставить вас оформлять код в определенном стиле. Это не позволит вам относиться к оформлению кода несерьезно. Сделайте это не только для клиентского кода, но и для серверного. узнать больше...
-
Вы можете использовать ESLint - JavaScript linter, чтобы обеспечить соблюдение определенного стиля кода.
Почему:
Многие предпочитают
eslint
, но выбор за вами.eslint
поддерживает множество правил, возможность конфигурировать их и добавлять свои. -
Вы можете использовать уже готовый набор правил оформления кода. Например, руководство по оформлению кода от Airbnb для JavaScript. узнать больше...
-
Если вы пишите на FlowType, то можно использовать правила оформления кода на FlowType для ESLint.
Зачем:
Flow вводит немного новый синтаксис, который нужно обязать следовать определенным правилам оформления кода.
-
Используйте
.eslintignore
, чтобы исключить файлы и папки из проверки на оформление кода.Зачем:
Чтобы не загрязнять ваш код
eslint-disable
комментариями каждый раз, когда вам надо исключить файл из проверки. -
Удалите
eslint-disable
комментарии перед тем как создавать Запрос на Слияние (Pull Request).Почему:
В процессе разработки можно выключать проверку на оформление кода, чтобы больше сосредотачиваться на бизнес-логике. Просто не забывайте удалять
eslint-disable
комментарии, когда логика уже написана, чтобы следовать правилам оформления. -
В зависимости от размера задачи, используйте
// TODO:
комментарии или открывайте тикет.Зачем:
Чтобы напомнить себе и другим о небольших задачах (например, рефакторинг функции или обновление комментария). Для больших задач используйте
// TODO(#3456)
, номер в скобках - это номер открытого тикета. -
Всегда пишите комментарии и актуализируйте их с обновлением кода. Удаляйте закомментированные части кода.
Зачем:
Ваш код должен быть максимально читабельным, вы должны избавиться от всего лишнего. Если вы сделали рефакторинг функции, не комментируйте старую, удалите ее.
-
Избегайте неуместных и шуточных комментариев, логов и наименований.
Почему:
Хотя во время сборки можно/нужно удалить их, иногда ваш исходный код может быть передан в другую компанию/клиенту, и они могут не разделить вашего чувства юмора.
-
Используйте имена со смыслом, не сокращайте их, чтобы потом было легко их искать. Для функций используйте длинные и наглядные имена. Имя функции должно быть глаголом или глагольной фразой, и должно сообщать нам что делает функция.
Зачем:
Это облегчит чтение исходного кода и сделает его более естественным.
-
Располагайте функции в файле в соответствии с правилом понижения (step-down rule). Сложные составные функции располагаются в начале файла, а затем идут простые функции.
Зачем:
Это облегчит чтение исходного кода и сделает его более естественным.
-
Используйте файл .editorconfig, который помогает разработчикам определять и поддерживать одинаковые стили оформления кода между разными текстовыми редакторами и средами разработки (IDE) в проекте.
Пояснение:
Проект EditorConfig состоит из файла, в котором указываются определенные стили оформления кода, и набора плагинов для текстового редактора, которые позволяют редактору прочитать файл и придерживаться стилям кода, определенным в этом файле. Файлы EditorConfig легко читаются и прекрасно работают с системами контроля версий.
-
Ваш редактор оповещает вас об ошибках оформления кода? Используйте eslint-plugin-prettier и eslint-config-prettier с вашим текущими настройками ESLint. узнать больше...
-
Рассмотрите использование Git hooks.
Зачем:
Git hooks в разы увеличивают продуктивность разработчика. Добавляйте изменения, создавайте коммит и отправляйте (push) на тестовое или релизное окружение без страха, что сломается сборка. узнать больше...
-
Используйте Prettier с precommit hook.
Зачем:
Хотя
prettier
сам по себе достаточно мощный инструмент, запускать его каждый раз как отдельнуюnpm
задачу, чтобы отформатировать код, не очень продуктивно. Здесь в игру вступаетlint-staged
иhusky
. Узнать больше о настройкеlint-staged
можно здесь, а про настройкуhusky
здесь.
-
Избегайте логов в консоли разработчика на клиенте в релизном окружении
Совет:
Хотя в процессе сборки вы можете/должны удалять их, убедитесь, что ваш линтер оформления кода предупреждает вас об оставшихся логах консоли.
-
Создавайте читабельные логи релизного окружения. В идеале, в релизном окружении используйте библиотеки для логирования. Например, winston или node-bunyan.
Зачем:
Это сделает процесс поиска проблем более приятным: раскрашивание в разные цвета, метки времени, логирование в файл в дополнение к консоли или даже логирование в файлы, которые разбиваются по дням. узнать больше...
Зачем:
Чтобы разработчики создавали качественные RESTful интерфейсы, которые можно легко и консистентно использовать как членам команды, так и клиентам.
Почему:
Отсутствие консистентности и простоты может в разы усложнить интеграцию и поддержку. Поэтому раздел
Дизайн API
включен в этот документ.
-
В основном вы можете следовать ресурсо-ориентированному дизайну. Три основных фактора: ресурсы, коллекции и URLы.
- Ресурсы состоят из данных, могут быть вложены и имеют методы для работы с данными.
- Группы ресурсов называются коллекциями.
- URL идентифицирует онлайновое местоположение ресурса или коллекции.
Почему:
Этот дизайн хорошо известен разработчикам (вашим главным потребителям API). Он не только читабельный и легкий в использовании, но еще и позволяет писать универсальные библиотеки и коннекторы, не зная, как будет выглядеть API.
-
Для URL'ов используйте kebab-case.
-
Для параметров в поисковой строке или полях ресурса используйте camelCase.
-
Для имен ресурсов в URL'ах используйте kebab-case во множественном числе.
-
Всегда используйте существительные во множественном числе для именования URL'ов, указывающих на коллекцию:
/users
.Почему:
Лучше читается и сохраняет консистентность URL'ов. узнать больше...
-
В исходном коде замените множественное число на переменные и свойства с суффиксом
List
.Почему:
Использовать множественное число в URL'е удобно, а в исходном коде недостаточно прозрачно и может привести к ошибкам.
-
Всегда используйте уникальное представление URL'а, которое начинается с коллекции и заканчивается идентификатором:
/students/245743 /airports/kjfk
-
Не используйте URL'ы наподобие:
GET /blogs/:blogId/posts/:postId/summary
Почему:
Этот URL указывает не на ресурс, а на свойство ресурса. Вы можете передать его как параметр запроса.
-
Не используйте глаголы в URL'ах, указывающих на ресурсы.
Почему:
Потому что, если использовать глаголы в каждой операции над ресурсом, в скором времени у вас получится огромный список URL'ов и не будет консистентного шаблона, что усложнит изучение API для разработчиков. К тому же глаголы используются для других целей.
-
Используйте глаголы в URL'ах, не указывающих на ресурсы. В этом случае ваше API не возвращает ресурсы, оно запускает операцию и возвращает результат выполнения. Это не CRUD (create, retrieve, update и delete) операции:
/translate?text=Hallo
Почему:
Потому что для CRUD используются HTTP методы с URL'ами
ресурса
иликоллекции
. Глаголы же на самом деле являютсяКонтроллерами
. Обычно их не так часто разрабатывают. узнать больше... -
Если в теле запроса или ответа возвращается
JSON
объект, то именуйте свойства объекта вcamelCase
, чтобы поддерживать консистентность.Почему:
Это советы для JavaScript проекта, где подразумевается, что язык программирования для генерации и парсинга
JSON
- это JavaScript. -
Хотя ресурс и является уникальной сущностью, как экземпляр объекта или запись базы данных, вы не должны использовать
table_name
как имя ресурса иcolumn_name
как свойство ресурса.Почему:
Потому что вы намереваетесь показать Ресурс, а не схему таблицы из базы данных.
-
И снова, при именовании ресурсов в URL'ах используйте только существительные, не указывайте в имени ресурса действие.
Совет:
Используйте только существительные в URL'ах ресурса, избегайте подобных URL'ов:
/addNewUser
или/updateUser
. Также не стоит посылать операцию над ресурсом как параметр запроса. -
Объяснение функциональных возможностей CRUD с использованием HTTP методов:
GET
: Получить представление ресурса.POST
: Создать новые ресурсы или под-ресурсы.PUT
: Обновить существующие ресурсы.PATCH
: Обновить существующие ресурсы. Обновляет только переданные поля, остальные не трогает.DELETE
: Удалить существующие ресурсы. -
Для вложенных ресурсов используйте связь между ними в URL'е. Например, используйте
id
для связи сотрудника с компанией.Почему:
Это естественный метод, чтобы добраться до ресурсов.
Как:
GET /schools/2/students
, должен получить список всех студентов из школы сid
2.GET /schools/2/students/31
, должен получить данные о студенте сid
31, который учится в школе сid
2.DELETE /schools/2/students/31
, должен удалить студента сid
31, который учится в школе сid
2.PUT /schools/2/students/31
, должен обновить данные о студенте сid
31. ИспользуйтеPUT
только на URL'е ресурса, а не коллекции.POST /schools
, должен создать новую школу и вернуть данные по ней. ИспользуйтеPOST
на URL'е коллекции. -
Для версионности используйте обычный порядковый номер с префиксом
v
(v1, v2). Разместите его в начале URL'а, чтобы у него был самый широкий охват:http://api.domain.com/v1/schools/3/students
Зачем:
Когда ваше API публично и предназначено для третьих лиц, его обновление может вносить переломные изменения (breaking changes), которые могут привести к поломке существующих продуктов и сервисов, использующих ваше API. Использование версионности не позволит этому случиться. узнать больше...
-
Ответное сообщение не должно требовать дополнительного описания. Например, корректное сообщение об ошибке может выглядеть вот так:
{ "code": 1234, "message" : "Something bad happened", "description" : "More details" }
или сообщение с ошибками валидации:
{ "code" : 2314, "message" : "Validation Failed", "errors" : [ { "code" : 1233, "field" : "email", "message" : "Invalid email" }, { "code" : 1234, "field" : "password", "message" : "No password provided" } ] }
Почему:
В критические моменты разработчики надеются на качественно сформулированные ошибки, когда ищут проблему или решают вопросы после того, как приложение, использующее ваше API, попало в руки к пользователям.
Замечание: Сообщения об ошибках безопасности должны быть как можно более обобщенными. Например, вместо того чтобы говорить
неверный пароль
, стоит отвечатьневерное имя пользователя или пароль
, чтобы мы, не осознавая того, не сообщали, что имя пользователя верное, а пароль нет. -
Используйте следующие коды статусов в вашем ответном сообщении, чтобы описать что все нормально, клиентское приложение сделало что-то не так или API сломалось.
Коды статусов:
200 OK
означает успешное выполнениеGET
,PUT
илиPOST
запросов.201 Created
означает, что создан новый объект. Создание новых объектов, использую методPOST
, возвращает201
код статуса.204 No Content
означает успешно обработанный запрос, но отправить обратно нечего. Используйте его, когда операцияDELETE
прошла успешно.304 Not Modified
означает, что запрошенный ресурс уже есть в кэше у получателя и можно сэкономить на передаче данных.400 Bad Request
для необработанных запросов, так как сервер не понимает, что именно запрашивает клиент.401 Unauthorized
для запросов с невалидными учетными данными. При данном ответе надо сделать повторный запрос с валидными данными.403 Forbidden
означает, что сервер понял запрос, но отказывается авторизовать его.404 Not Found
означает, что запрошенный ресурс не найден.500 Internal Server Error
означает, что запрос валидный, но сервер не смог его выполнить по каким-то непредвиденным причинам.Пояснение:
Большинство поставщиков API использует малую часть кодов статусов HTTP. Например, Google GData API использует только 10 кодов статусов, Netflix - 9, а Digg только 8. Конечно же, они передают дополнительную информацию в теле ответа. Существует свыше 70 кодов статусов. Однако, большинство разработчиков не помнят все 70 кодов. Поэтому, если вы выбираете код статуса, который не очень распространен, вы заставите разработчика переключиться с построения приложения на поиск в википедии, что же вы хотели ему сказать. узнать больше...
-
Указывайте общее количество ресурсов в вашем ответе.
-
Поддерживайте параметры запроса
limit
иoffset
. -
Количество данных, которое предоставляет ресурс, должно быть учтено. Потребитель вашего API не всегда нуждается в полном представлении ресурса. Используйте параметр запроса
fields
, который принимает на вход разделенный запятой список полей, необходимых для включения в ответ:GET /student?fields=id,name,age,class
-
Вам не обязательно поддерживать пагинацию, фильтрацию и сортировку с самого начала для всех ресурсов. Просто задокументируйте ресурсы, которые предоставляют эту возможность.
Здесь представлены несколько основных лучших практик для безопасности:
-
Не используйте базовую аутентификацию, если вы не работаете по защищенному соединению (HTTPS). Токены аутентификации не должны передаваться в URL'е:
GET /users/123?token=asdf....
Почему:
Потому что Токен или ID пользователя и пароль передаются по сети как простой текст, закодированный в base64, но base64 это обратимое кодирование. Схема базовой аутентификации не безопасна. узнать больше...
-
Токены должны передаваться с использованием заголовка
Authorization
при каждом запросе:Authorization: Bearer xxxxxx, Extra yyyyy
. -
Жизненный цикл
Authorization Code
должен быть кратковременным. -
Отклоняйте все запросы, переданные через незащищенный протокол (non-TLS requests), чтобы избежать передачи данных небезопасным путем. Отвечайте на подобные HTTP запросы статусом
403 Forbidden
. -
Задумайтесь над использованием ограничения запросов (Rate Limiting).
Зачем:
Чтобы защитить API от угроз ботов, которые вызывают его тысячи раз в час. Вы должны задуматься над реализацией ограничения количества запросов на ранних этапах построения приложения.
-
Правильно сконфигурированные HTTP заголовки помогут вам обезопасить ваше web-приложение. узнать больше...
-
Ваше API должно преобразовывать данные, получаемые в запросе, в их каноничное представление или, если это невозможно, отклонять запрос. Вернуть статус
400 Bad Request
с детальной информацией об ошибках с некорректными или отсутствующими данными. -
Весь обмен данными с REST API должен валидироваться самой API.
-
Сериализуйте ваш JSON.
Зачем:
Ключевая цель JSON сериализаторов - это предотвращение удаленного выполнения произвольного JavaScript кода в браузере... или, если вы используйте Node.js, на сервере. Поэтому жизненно необходимо иметь правильный JSON сериализатор, чтобы безопасно кодировать данные для предотвращения выполнения предоставленного пользователем кода в браузере.
-
Валидируйте заголовок
Content-Type
и используйте, в основном, сapplication/*json
значением.Зачем:
Например, если разрешить MIME-тип
application/x-www-form-urlencoded
, то злоумышленник сможет создать форму и вызвать простойPOST
запрос. Сервер никогда не должен предполагатьContent-Type
. Отсутствие заголовкаContent-Type
или его неожиданное значение должно служить причиной для сервера отклонить запрос со статусом4XX
. -
Вы можете использовать чек-лист для проверки безопасности API. например
- Заполните раздел
API Reference
в шаблоне README.md для API. - Опишите методы аутентификации API с примерами кода.
- Опишите структуру URL'ов (только путь, без корневого URL), включая тип запроса (метод HTTP).
По каждому URL'у разъясните:
-
Параметры URL'а, если они есть, укажите их в соответствии с именами, указанными в разделе URL:
Required: id=[integer] Optional: photo_id=[alphanumeric]
-
Если метод запроса
POST
, приведите рабочие примеры. Правило для параметров URL'а здесь тоже работает. Разбейте раздел на Необязательные и Обязательные данные. -
Если ответ успешный, укажите какой должен быть код статуса и вернутся ли какие-нибудь данные. Это будет полезно для людей, которые хотят знать какие данные ожидать в ответе.
Code: 200 Content: { id : 12 }
-
Если ответ неуспешный. Большинство запросов имеет множество вариантов неуспешно завершиться. Начиная от неавторизованного доступа до неправильных параметров и т.д. Все эти варианты должны быть задокументированы. При документировании вы будете повторяться, но это поможет предотвратить додумывание со стороны потребителя API. Например:
{ "code": 403, "message" : "Authentication failed", "description" : "Invalid username or password" }
-
Используйте готовые решения для дизайна API. Существует множество инструментов с открытым исходным кодом для документирования API. Например, API Blueprint и Swagger.
Убедитесь, что у вас есть право на ресурсы, которые вы используете. Если вы используете библиотеки, не забудьте проверить, что они имеют лицензию MIT, Apache или BSD. Если вы их модифицируете, проверьте детали лицензии на разрешение. Использование изображений и видео материалов, защищенных авторским правом, может повлечь проблемы с законом.
Источники: RisingStack Engineering, Mozilla Developer Network, Heroku Dev Center, Airbnb/javascript, Atlassian Git tutorials, Apigee, Wishtack
Иконки от icons8