web-dev-qa-db-fra.com

Design de l'API: Béton contre une approche abstraite - meilleures pratiques?

Lors de la discussion API entre les systèmes (au niveau des entreprises) il y a souvent deux points de vue différents dans notre équipe: certaines personnes préfèrent une plus - disons - générique approche abstraite, à une approche avant droit " concrète ".

Exemple: la conception d'une API simple " de recherche de personne ". la version concrète serait

 searchPerson(String name, boolean soundEx,
              String firstName, boolean soundEx,
              String dateOfBirth)

Les gens en faveur de la voix de la version du béton:

  • l'API est autodocumenté
  • c'est facile à comprendre
  • il est facile de valider (compilateur ou comme webservice: validation du schéma)
  • KISS

L'autre groupe de personnes dans notre équipe serait dire "C'est juste une liste de critères de recherche "

searchPerson(List<SearchCriteria> criteria)

avec

SearchCritera {
  String parameter,
  String value,
  Map<String, String> options
}

avec éventuellement faire " paramètre " d'un certain type d'énumération.

Les partisans disent:

  • sans changer la (déclaration) de l'API la mise en œuvre peut changer, par exemple l'ajout de critères ou plus d'options. Même sans la synchronisation d'un tel changement au moment du déploiement.
  • la documentation est nécessaire, même avec la variante de béton
  • validation du schéma est surfaite, souvent, vous devez valider davantage, le schéma ne peut pas traiter tous les cas
  • nous avons déjà une API similaire avec un autre système - réutilisation

Le contre-argument est

  • beaucoup de documentation sur les paramètres valides et combinaisons de paramètres valides
  • plus d'efforts de communication, car il est plus difficile à comprendre pour les autres équipes

Y a-t-il des meilleures pratiques? Littérature?

25
erik

Cela dépend du nombre de champs dont vous parlez et comment ils sont utilisés. Le béton est préférable pour des requêtes hautement structurées avec seulement quelques champs, mais si la requête a tendance à être une forme très libre, l'approche concrète devient rapidement manifeste avec plus de trois ou quatre champs.

D'autre part, il est très difficile de garder une API générique pure. Si vous faites une recherche de nom simple dans de nombreux endroits, une personne va éventuellement se battre de répéter les mêmes cinq lignes de code, et ils vont l'envelopper dans une fonction. Une telle API évolue invariablement dans un hybride d'une requête générique avec des emballages en béton pour les requêtes les plus couramment utilisées. Et je ne vois rien de mal avec ça. Cela vous donne le meilleur des deux mondes.

18
Karl Bielefeldt

La conception de la bonne API est un art. La bonne API est appréciée même après la passe de temps. À mon avis, il ne devrait y avoir aucun biais général sur la ligne abstraite-béton. Certains paramètres peuvent être aussi concrets que des jours de la semaine, certains ont besoin d'être conçus pour une extensibilité (et il est assez stupide de les rendre concrets, par exemple, une partie des noms de fonction), mais une autre peut aller encore plus loin et afin d'avoir élégant L'API Il faut fournir des rappels ou même un domaine spécifique à un domaine aidera à lutter contre la complexité.

Il y a rarement de nouvelles choses qui se passent sous la lune. Jetez un coup d'œil à la technique antérieure, en particulier des normes et des formats établis (par exemple, de nombreuses choses peuvent être modélisées après les aliments pour animaux, des descriptions d'événements ont été élaborées dans ICAL/VCAL). Faites votre API facilement additif, où des entités fréquentes et omniprésentes sont des extensions concrètes et envisagées sont des dictionnaires. Il existe également des modèles bien établis pour traiter des situations spécifiques. Par exemple, la manipulation de la requête HTTP (et similaire) peut être modélisée dans l'API avec des objets de demande et de réponse.

Avant de concevoir l'API, réfléchissez à des aspects, y compris ceux qui ne seront pas inclus, mais vous devez être au courant. Des exemples de telles représentent la langue, la direction d'écriture, le codage, les paramètres régionaux, les informations de fuseau horaire et similaires. Faites attention aux endroits où les multiples peuvent apparaître: utilisez la liste, pas une valeur unique pour eux. Par exemple, si vous dessinez API pour le système VOOYCHAT, votre API sera beaucoup plus utile, si vous assumez n participants, pas seulement deux (même si vos spécifications sont telles que telles).

Parfois, être abstraite aide à réduire considérablement la complexité: même si vous concevez une calculatrice pour ajouter seulement 3 + 4, 2 + 2 et 7 + 6, il peut être beaucoup plus simple d'implémenter x + y (avec des limites techniquement réalisables sur x et Y, et inclure ajouter (x, y) à votre API au lieu de add_3_4 (), add_2_2 (), ...

Dans l'ensemble, choisir d'une manière ou d'une autre n'est qu'un détail technique. Votre documentation doit décrire des cas d'utilisation fréquente de manière concrète.

Quoi que vous fassiez sur la structure de données, fournissez un champ pour une version API.

Pour résumer, API devrait minimiser la complexité lorsqu'il s'agit de votre logiciel. Pour apprécier l'API, le niveau de complexité exposé devrait être adéquat. Décider de la forme de l'API dépend beaucoup de la stabilité du domaine problématique. Ainsi, il devrait y avoir une estimation sur quelle direction le logiciel et son API se développera, car ces informations peuvent affecter l'équation de complexité. En outre, l'API Desing est là pour que les gens comprennent. S'il y a de bonnes traditions dans la zone de technologie logicielle, essayez de ne pas vous écarter beaucoup d'eux, car cela vous aidera à comprendre. Prenez en compte pour qui vous écrivez. Les utilisateurs plus avancés apprécieront la généralité et la flexibilité, tandis que ceux avec moins d'expérience peuvent être plus à l'aise avec la concrétricité. Cependant, soins à la majorité des utilisateurs de l'API, c'est-à-dire ceux entre débutants et experts.

Sur le côté de la littérature, je peux recommander "beau codes" les programmeurs principaux expliquent comment ils réfléchissent par Andy Oram, Greg Wilson, comme je pense que la beauté consiste à percevoir une optimalité cachée (et d'une adéquation à des fins de certains but).

7
Roman Susi

Je ne dirais pas qu'une API abstrait est nécessairement plus difficile à valider. Si les paramètres de critère sont suffisamment simples et que peu de dépendances entre elles, il ne fait pas grand nombre de différences si vous transmettez les paramètres séparément ou dans un tableau. Vous devez toujours les valider tous. Mais cela dépend de la conception des paramètres de critères et des objets eux-mêmes.

Si l'API est assez complexe, avoir des méthodes concrètes n'est pas une option. À un moment donné, vous vous retrouverez probablement avec les deux méthodes avec de nombreux paramètres ou trop de méthodes simples qui ne couvrent pas tous les cas d'utilisation requis. En ce qui concerne mon expérience personnelle dans la conception d'une API consommant, il est préférable d'avoir plus de méthodes génériques sur le niveau de l'API et de mettre en œuvre des emballages spécifiques requis sur le niveau d'application.

1
Pavels

L'argument de changement doit être rejeté avec YAGNI. Fondamentalement, à moins que vous avez réellement au moins 3 différents cas d'utilisation qui utilisent l'API générique différemment, les chances sont assez bas, vous la conception afin qu'il ne devra pas changer lors de son prochain cas d'utilisation arrive (et quand vous avez la utilisation- les cas, vous devez évidemment l'interface générique, période). Donc, ne pas essayer et être prêt pour le changement.

Le changement n'a pas besoin d'être synchronisé pour le déploiement dans les deux cas. Lorsque vous généralisez l'interface plus tard, vous pouvez toujours fournir l'interface plus spécifique pour la compatibilité descendante. Mais dans la pratique, tout déploiement aura tant de changements que vous le synchroniser de toute façon si vous n'avez pas à tester les états intermédiaires. Je ne vois pas que l'argument soit.

En ce qui concerne la documentation, que ce soit la solution peut être facile à utiliser et évidente. Mais il se présente comme argument important. Mettre en œuvre l'interface afin qu'il sera facile à utiliser dans vos cas réels. Parfois spécifique peut être de meilleurs ans peut parfois être générique.

1
Jan Hudec

Je favoriserais l'approche d'interface abstraite. Pour mettre une requête à ce type de service (recherche) est un problème courant et se produira probablement à nouveau. En outre, vous trouverez de manière proprablement davantage de candidats de services qui conviennent à la réutilisation d'une interface plus générale. Pour pouvoir fournir une interface commune cohérente pour ces services, je n'éumérerais pas les paramètres de requête identifiés dans la définition de l'interface.

Comme il a été souligné précédemment - j'aime la possibilité de modifier ou d'étendre la mise en œuvre sans modifier l'interface. L'ajout d'un autre critère de recherche ne doit pas être reflété dans la définition de service.

Bien qu'il ne s'agisse pas de question de concevoir des interfaces bien définies, concises et exprimées, vous devrez toujours fournir une documentation en plus. L'ajout du champ de définition des critères de recherche valides n'est pas une telle charge.

1
0x0me

Le meilleur résumé que j'ai jamais vu est l'échelle de Rusty, maintenant appelée Manifesto design API de Rusty . Je ne peux que le recrutement fortement que l'un. Par souci de complétude, je cite le résumé de la balance du premier lien (mieux sur le dessus, l'orifice ci-dessous):

Bonnes API

  • Il est impossible de se tromper.
  • Le compilateur/lieur ne vous laissera pas vous tromper.
  • Le compilateur mettra en garde si vous vous trompez.
  • L'utilisation évidente est (probablement) la bonne.
  • Le nom vous indique comment l'utiliser.
  • Faites-le correctement ou il va toujours casser au moment de l'exécution.
  • Suivez la convention commune et vous obtiendrez bien.
  • Lisez la documentation et vous le ferez correctement.
  • Lisez la mise en œuvre et vous le ferez correctement.
  • Lisez le thread de liste de diffusion correcte et vous le ferez correctement.

Bad Apis

  • Lisez le thread de la liste de diffusion et vous vous tromperez mal.
  • Lisez la mise en œuvre et vous vous tromperez mal.
  • Lisez la documentation et vous vous tromperez mal.
  • Suivez la convention commune et vous vous tromperez mal.
  • Faites-le bien et cela se brisera parfois au moment de l'exécution.
  • Le nom vous indique comment ne pas l'utiliser.
  • L'utilisation évidente est fausse.
  • Le compilateur mettra en garde si vous le faites bien.
  • Le compilateur/linker ne vous laissera pas le faire correctement.
  • Il est impossible de bien avoir raison.

Les deux coordonnées pages ici et ici Venez avec une discussion approfondie de chaque point. C'est vraiment un must pour les concepteurs de l'API. Merci rouillé, si vous le lisez jamais.

1
JensG

Ma préférence personnelle est d'être abstraite, mais les politiques de mon entreprise m'accordent-elles à être concrète. C'est la fin du débat pour moi :)

Vous avez effectué un bon travail des avantages et des inconvénients pour les deux approches, et si vous continuez à creuser, vous trouverez de nombreux arguments en faveur des deux côtés. Tant que votre architecture d'API est développée correctement - ce que vous avez donné pensé à la manière dont il sera utilisé aujourd'hui et comment cela peut évoluer et grandir à l'avenir - alors vous devriez être bien.

Voici deux signets que j'avais avec des points de vue opposés:

favorisant des classes abstraites

Favoring Interfaces

Demandez-vous: "L'API remplit-t-elle mes besoins en entreprise? Ai-je des critères bien définis pour réussir? Cela peut-il échouer?". Ceux-ci semblent être très simples les meilleures pratiques à suivre, mais honnêtement, ils sont beaucoup plus importants que le béton contre le générique.

1
gws2

dans les mots de layman :

  • L'approche abstraite a l'avantage de permettre de construire des méthodes concrètes autour de celle-ci.
  • L'inverse n'est pas vrai
0
Tulains Córdova

Si vous prolongez le SearchCriteria idée un peu, cela peut vous donner une flexibilité telle que la création AND, OR etc. Critères. Si vous avez besoin de cette fonctionnalité, ce serait la meilleure approche.

Sinon, concevez-le pour la convivialité. Rendre l'API facile pour les personnes qui l'utilisent. Si vous avez des fonctions de base nécessaires (comme la recherche d'une personne par son nom), fournissez-les directement. Si les utilisateurs avancés ont besoin de recherches avancées, ils peuvent toujours utiliser le SearchCriteria.

0
Uooo

Quel est le code derrière l'API? Si c'est quelque chose de flexible, une API flexible est bonne. Si le code derrière l'API est très spécifique, mettez un visage flexible à ce sujet signifie que les utilisateurs de l'API vont être frustrés et agacés de tout ce que l'API prétend est possible mais ne peut pas être accompli.

Pour l'exemple de recherche de votre personne, les trois champs sont-ils nécessaires? Si tel est le cas, la liste des critères est mauvaise car elle permet une multitude d'utilisations qui ne fonctionnent tout simplement pas. Sinon, obliger l'utilisateur à spécifier des entrées non requises est mauvaise. Quelle est la probabilité de rechercher par adresse à ajouter en v2? L'interface flexible facilite l'ajout que celui inflexible.

Tous les systèmes ne doivent pas être un ultra flexible, essayant de faire tout ce que l'architecture est l'astronaute. Un arc flexible pousse des flèches. Une épée flexible est aussi utile qu'un poulet en caoutchouc.

0
stonemetal