Если вы хотите разрабатывать хорошие API, думайте как дизайнер

Какова цена плохого API? Попробуйте умножить весь свой технический долг на количество пользователей.

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

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

Я немного покажу реальный пример. Но сначала, как выглядит хороший API?

Хороший API на (крошечном) примере

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

Один небольшой фрагмент общедоступного API выглядит следующим образом:

Вы можете увидеть некоторые требования и возможности.

  • login(credentials: Credentials) выглядит полезным. Не сразу понятно, как получить экземпляр Credentials, но поскольку это конкретный тип (вместо, скажем, plainString), он показывает, где искать дополнительную информацию.
  • Authorization содержит String «authToken», но конструктор фактически является закрытым. Вы должны использовать экземпляр AuthApi, чтобы его получить. В этом есть смысл - библиотека должна обрабатывать получение токенов.
  • Вам нужен экземпляр AuthApi, и есть конструктор.
  • Причины сочетаются с последствиями. login() имеет тип возврата.

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

Этот принцип становится более важным по мере увеличения площади поверхности API. Хорошая библиотека не обязательно скрывает сложность - она ​​может моделировать ее и даже научить вас, как работает сложный базовый протокол, пока вы его реализуете. Он кодирует сложность в цепочку шагов, которой должен следовать разработчик-потребителем, и обеспечивает защиту на этом пути.

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

Но, может быть, аутентификация просто поддается чистому API?

Нет.

Насколько плохо это может быть?

Предположим, что AuthApi вместо этого выглядел так. Помните, что это небольшая часть потенциально более крупного API:

Задумайтесь об этом на секунду.

  • Несомненно, вызов метода login() является решающим, но каковы требования? Включает ли это как анонимный, так и пользовательский вход?
  • setCredentials выглядит важным. Это Map для комбинаций имени пользователя и пароля? Если нет, каковы исходные данные и где их взять? String не зависит от типа аутентификации. Этот API должен ожидать строку определенного типа, так где же ограждения?
  • Каков ожидаемый эффект от вызова login? void доход не указывает на ожидаемый результат.

Эта область API не делает ничего, чтобы подтолкнуть к правильному использованию. Типы не указывают и не предписывают какой-либо порядок операций. Последствия не совпадают с их причинами. Вам нужно вручную искать другие соответствующие классы, методы и типы. Ничего не обозначено. Этот API с радостью позволит вам без промедления столкнуться с любыми возможными ошибками. Документация несет невероятное бремя объяснения всего этого - и там, где это не удается, вы сами по себе.

Но с этим никто не мирился. Как насчет реального примера?

Я только что показал это вам.

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

Хороший API делает наоборот: пользователи не могут не ошибаться, исследуя потенциально сложное взаимодействие. Он предлагает возможности, отзывы и требования к указателям. Принципы дизайна, часто применяемые к продуктам и пользовательскому интерфейсу, также применимы к программным интерфейсам (см. Применение концепций дизайна к коду, чтобы узнать больше по этой теме!).

Коллин пишет API с помощью Livefront, и он благодарит вас за чтение.