При обсуждении API-интерфейсов между системами (на бизнес-уровне) в нашей команде часто бывают две разные точки зрения: некоторые люди предпочитают более общий, скажем так, общий абстрактный подход, а другие - прямой «конкретный» подход.
Пример: дизайн простого API «поиск человека». конкретная версия будет
searchPerson(String name, boolean soundEx,
String firstName, boolean soundEx,
String dateOfBirth)
Люди в пользу конкретной версии говорят:
- API самодокументируется
- это легко понять
- это легко проверить (компилятор или как веб-сервис: проверка схемы)
- ПОЦЕЛУЙ
Другая группа людей в нашей команде сказала бы: «Это просто список критериев поиска».
searchPerson(List<SearchCriteria> criteria)
с
SearchCritera {
String parameter,
String value,
Map<String, String> options
}
с возможностью создания «параметра» некоторого типа перечисления.
Сторонники говорят:
- без изменения (декларации) API реализация может измениться, например, добавив больше критериев или больше опций. Даже без синхронизации такого изменения во время развертывания.
- документация необходима даже при конкретном варианте
- валидация схемы переоценена, часто вам приходится валидировать дальше, схема не может обработать все случаи
- у нас уже есть похожий API с другой системой - повторное использование
Контр-аргумент
- много документации о допустимых параметрах и допустимых комбинациях параметров
- больше коммуникационных усилий, потому что это труднее понять для других команд
Есть ли лучшие практики? Литература?
Ответы:
Это зависит от того, сколько полей вы говорите, и как они используются. Бетон предпочтителен для высокоструктурированных запросов только с несколькими полями, но если запрос имеет тенденцию быть очень свободной формой, то конкретный подход быстро становится громоздким с более чем тремя или четырьмя полями.
С другой стороны, очень сложно поддерживать чистоту общего API. Если вы выполняете простой поиск по именам во многих местах, в конце концов, кто-то устает повторять те же пять строк кода, и они собираются обернуть его в функцию. Такой API-интерфейс неизменно превращается в гибрид общего запроса вместе с конкретными оболочками для наиболее часто используемых запросов. И я не вижу в этом ничего плохого. Это дает вам лучшее из обоих миров.
источник
Разработка хорошего API - это искусство. Хороший API ценится даже по прошествии времени. На мой взгляд, не должно быть общего смещения на абстрактно-конкретной линии. Некоторые параметры могут быть такими же конкретными, как дни недели, некоторые требуют разработки для расширяемости (и довольно глупо делать их конкретными, например, частью имен функций), а еще один может пойти еще дальше и для того, чтобы иметь элегантный API-интерфейс, необходимый для обеспечения обратных вызовов, или даже предметно-ориентированный язык помогут бороться со сложностью.
Редко что-то новое происходит под луной. Взгляните на уровень техники, в особенности на установленные стандарты и форматы (например, многие вещи можно смоделировать после каналов, описания событий были разработаны в формате ical / vcal). Сделайте ваш API легко аддитивным, когда частые и вездесущие сущности являются конкретными, а предполагаемые расширения - словарями. Есть также несколько устоявшихся моделей для решения конкретных ситуаций. Например, обработка HTTP-запроса (и аналогичного) может быть смоделирована в API с объектами Request и Response.
Перед разработкой API проведите мозговой штурм по аспектам, включая те, которые не будут включены, но вы должны знать об этом. Примерами таких языков являются язык, направление письма, кодирование, локаль, информация о часовом поясе и тому подобное. Обратите внимание на места, где могут появляться кратные значения: используйте список, а не одно значение для них. Например, если вы разрабатываете API для системы видеочата, ваш API будет гораздо полезнее, если вы примете N участников, а не только двоих (даже если ваши спецификации на данный момент таковы).
Иногда абстрактность помогает значительно снизить сложность: даже если вы разрабатываете калькулятор для добавления только 3 + 4, 2 + 2 и 7 + 6, может быть намного проще реализовать X + Y (с технически выполнимыми границами для X и Y, и добавьте ADD (X, Y) к вашему API вместо ADD_3_4 (), ADD_2_2 (), ...
В общем, выбор того или иного способа - это просто техническая деталь. Ваша документация должна описывать случаи частого использования конкретным образом.
Что бы вы ни делали на стороне структуры данных, предоставьте поле для версии API.
Подводя итог, API должен минимизировать сложность при работе с вашим программным обеспечением. Чтобы оценить API, уровень выставленной сложности должен быть адекватным. Выбор формы API во многом зависит от стабильности проблемной области. Таким образом, должна быть некоторая оценка, в каком направлении будет расти программное обеспечение и его API, потому что эта информация может влиять на уравнение сложности. Кроме того, API дизайн для людей, чтобы понять. Если в области программных технологий есть хорошие традиции, постарайтесь не сильно отклоняться от них, так как это поможет их пониманию. Примите во внимание, для кого вы пишете. Более продвинутые пользователи оценят универсальность и гибкость, в то время как те, у кого меньше опыта, могут быть более довольны конкретикой. Тем не менее, заботиться о большинстве пользователей API там,
Что касается литературы, я могу порекомендовать ведущим программистам «Красивый код» объяснить, как они думают. Энди Орам, Грег Уилсон, считают, что красота заключается в том, чтобы воспринимать скрытую оптимальность (и пригодность для каких-то целей).
источник
Мое личное предпочтение - быть абстрактным, но политика моей компании сводит меня к конкретности. Это конец дебатов для меня :)
Вы проделали хорошую работу, перечисляя плюсы и минусы для обоих подходов, и если вы продолжите копать, вы найдете множество аргументов в пользу обеих сторон. Если архитектура вашего API разработана должным образом - то есть вы задумывались о том, как он будет использоваться сегодня, и как он может развиваться и расти в будущем - тогда у вас все будет хорошо в любом случае.
Вот две закладки, которые у меня были с противоположных точек зрения:
Люблю абстрактные классы
Любимые интерфейсы
Задайте себе вопрос: «Соответствует ли API моим бизнес-требованиям? У меня есть четко определенные критерии успеха? Может ли он масштабироваться?». Похоже, что это действительно простые лучшие практики, которым нужно следовать, но, честно говоря, они гораздо важнее конкретных, чем общих.
источник
Я бы не сказал, что абстрактный API обязательно сложнее проверить. Если параметры критерия достаточно просты и имеют небольшие зависимости друг от друга, не имеет значения, передаете ли вы параметры отдельно или в массиве. Вам все еще нужно проверить их все. Но это зависит от дизайна параметров критериев и самих объектов.
Если API достаточно сложен, использование конкретных методов не является приемлемым вариантом. В какой-то момент вы, вероятно, в итоге получите либо методы с большим количеством параметров, либо слишком много простых методов, которые не будут охватывать все необходимые варианты использования. Что касается моего личного опыта в разработке потребляющих API, то лучше иметь более общие методы на уровне API и реализовывать конкретные необходимые оболочки на уровне приложений.
источник
Аргумент об изменении должен быть отклонен с YAGNI. По сути, если у вас нет как минимум 3 разных вариантов использования, которые используют универсальный API по-разному, шансы довольно малы, вы разрабатываете его так, что вам не нужно будет менять его при появлении следующего варианта использования (и когда у вас есть случаях, вам явно нужен общий интерфейс, точка). Так что не пытайтесь и будьте готовы к переменам.
В любом случае изменение не нужно синхронизировать для развертывания. Когда вы обобщаете интерфейс позже, вы всегда можете предоставить более конкретный интерфейс для обратной совместимости. Но на практике любое развертывание будет иметь так много изменений, что вы все равно будете его синхронизировать, поэтому вам не придется тестировать промежуточные состояния. Я бы тоже не воспринял это как аргумент.
Что касается документации, то любое решение может быть простым и очевидным. Но это важный аргумент. Реализуйте интерфейс так, чтобы его было легко использовать в ваших реальных случаях. Иногда конкретный может быть лучше, а иногда общий.
источник
Я бы предпочел подход абстрактного интерфейса. Задание запроса к этим видам (поисковой) службы является распространенной проблемой и, скорее всего, произойдет снова. Кроме того, вы, вероятно, найдете больше кандидатов на обслуживание, подходящих для повторного использования более общего интерфейса. Чтобы обеспечить согласованный общий интерфейс для этих служб, я бы не перечислял идентифицированные в настоящее время параметры запроса в определении интерфейса.
Как было указано ранее, мне нравится возможность изменять или расширять реализацию без изменения интерфейса. Добавление других критериев поиска не должно быть отражено в определении сервиса.
Несмотря на то, что нет сомнений в разработке четко определенных, лаконичных и понятных интерфейсов, вам всегда нужно будет дополнительно предоставить некоторую документацию. Добавление области определения для действительных критериев поиска не является таким бременем.
источник
Лучшее резюме, которое я когда-либо видел, - это шкала Расти, которая теперь называется манифестом API дизайна Расти . Я могу только настоятельно рекомендовать это. Для полноты приведу краткое изложение шкалы из первой ссылки (чем выше, тем хуже):
Хорошие API
Плохие API
Обе подробные страницы здесь и здесь содержат подробное обсуждение каждого пункта. Это действительно необходимо прочитать для дизайнеров API. Спасибо Расти, если ты когда-нибудь прочитал это.
источник
По словам непрофессионала:
источник
Если вы
SearchCriteria
немного расширите идею, это может дать вам гибкость, такую как критерии созданияAND
иOR
т. Д. Если вам нужна такая функциональность, это был бы лучший подход.В противном случае разработайте его для удобства использования. Сделайте API простым для людей, которые его используют. Если у вас есть некоторые основные функции, которые часто нужны (например, поиск человека по имени), предоставьте их напрямую. Если опытным пользователям нужны расширенные поиски, они все равно могут использовать
SearchCriteria
.источник
Что делает код API? Если это что-то гибкое, то гибкий API - это хорошо. Если код, стоящий за API, очень специфичен, то наложение на него гибкой грани означает, что пользователи API будут разочарованы и раздражены всем, что притворяется API, возможно, но на самом деле это невозможно.
Для вашего примера поиска человека все три поля обязательны для заполнения? Если так, то список критериев плох, потому что он допускает множество вариантов использования, которые просто не работают. Если нет, то требование пользователя указывать необязательные входные данные - это плохо. Насколько вероятно, что поиск по адресу будет добавлен в V2? Гибкий интерфейс облегчает добавление, чем негибкий.
Не каждая система должна быть очень гибкой, пытаясь сделать все то же самое, что архитектура Astronauting. Гибкий лук стреляет стрелами. Гибкий меч так же полезен, как резиновая курица.
источник