web-dev-qa-db-fra.com

Comment décrire un changement architectural qui casse intentionnellement les normes REST?

Je propose des changements à un projet logiciel très mal architecturé qui souffre d'une multitude de problèmes. À un niveau élevé, le projet utilise Angular sur le front-end et consomme diverses REST APIs; ce qui est génial (je ne vois pas la nécessité de changer notre technologie ou nos outils). Le problème est que la base de code est disproportionnellement plus grande dans l'interface utilisateur que les API côté serveur. Une grande partie de la logique métier réside dans l'interface utilisateur, avec les API REST étant de simples interfaces de base de données CRUD avec la couche UI.

Par exemple, un POST to customer créera un enregistrement client, tandis qu'un PUT modifiera ce client. Pas beaucoup plus, et pas beaucoup moins. Cependant, notre logique métier est plus exigeante que cela. Le le processus général de création d'un client fait bien plus qu'insérer 1 enregistrement de base de données. Il fournira des données dans d'autres tables nécessaires, effectuera certaines validations et calculs, etc. Je préférerais faire un seul appel POST/PUT qui encapsule tout ce comportement, alléger la charge du client consommateur.

Mon point de vue est donc que cette orchestration globale devrait vivre sur le serveur (où nous avons le contrôle total, les journaux, etc.), pas l'interface utilisateur, mais un contre-argument est que cette approche ne serait plus RESTful. Je ne sais donc pas comment décrire au mieux cette approche lorsque ma recommandation est de continuer avec la pile technologique existante, mais d'implémenter des changements fondamentaux dans les emplacements auxquels appartient le code.

38
Ben Harrison

Je ne sais pas comment décrire au mieux cette approche lorsque ma recommandation est de continuer avec la pile technologique existante, mais d'implémenter des changements fondamentaux dans les emplacements auxquels appartient le code.

Service oriented architecture.

Vous proposez de repenser votre système afin que vos règles métier et vos données soient au même endroit. C'est effectivement la définition d'un service ; voir le discours d'Udi Dahan sur Trouver les limites du service .

Encadré: comme l'a noté Eric, cela n'a rien à voir avec "REST". Il n'y a absolument aucune raison pour que vous ne puissiez pas mettre une API REST (c'est-à-dire une API qui satisfait les contraintes du style architectural REST ) devant votre service. Mais cela peut ne pas être évident pour les personnes qui comprennent REST pour signifier un mappage des opérations de base de données avec les méthodes HTTP.

Il peut être utile ou non d'investir pour changer la compréhension de REST par votre public.

50
VoiceOfUnreason

REST n'est pas CRUD. Ce "contre-argument" est basé sur une compréhension fondamentalement erronée de ce qu'est REST. Je n'ai rien vu dans votre article qui indique que votre changement rendrait votre API plus ou moins RESTful.

30
Eric Stein

Une autre chose à garder à l'esprit est la suivante ... Ne pas valider votre côté serveur de règles métier signifie que vous faites implicitement confiance à tout ce qui arrive, par exemple une demande POST, est valide.

Cela signifie que, par exemple, alors que votre application angular peut vérifier si le client a une tranche d'âge valide et garantit que les utilisateurs légitimes obtiennent les bons commentaires, toute personne qui connaît l'URL de votre API peut faire un = POST requête contenant des valeurs non légitimes qui ne seraient plus validées.

Donc, ma suggestion serait de déplacer vos règles métier vers l'API, de le laisser valider l'entrée et de renvoyer les erreurs appropriées (ou peut-être simplement des codes indiquant ce qui n'a pas fonctionné) dans le corps de la réponse. Ces codes peuvent ensuite être utilisés par votre application frontale pour indiquer ce qui n'a pas fonctionné.

25
mrsmn

Pour ajouter aux autres bonnes réponses ici:

Votre interface, REST ou autre, ne doit pas être contrainte sur la base d'une sorte d'hypothèse concernant les détails de la mise en œuvre. Ceci est complètement contraire à la notion de services en tant que couche d'abstraction.

L'un des principaux avantages de l'utilisation des services est que les détails de mise en œuvre peuvent être modifiés sans que les clients n'aient à faire quoi que ce soit. D'après ce que vous avez décrit, il semble qu'il n'y ait pas de véritable couche d'abstraction. Les détails de l'implémentation ont été exposés via HTTP. Rien sur REST dit que c'est nécessaire, utile ou souhaitable. En fait, je pense que je pourrais discuter de certaines parties de la définition REST REST pour signifier qu'il s'agit en fait d'une implémentation non RESTful.

Ce que vous proposez, c'est comment une couche de service appropriée devrait être conçue. Si quelqu'un vous dit que vous ne pouvez pas le faire parce que ce n'est pas reposant, c'est malheureux. Vous pouvez être assuré que quelqu'un qui vous dit que vous en savez peu sur REST.

En fonction de votre question, vous disposez d'une ressource appelée client. Tout et tout ce qui est nécessaire pour créer une ressource client valide peut et doit être géré dans un POST vers la ressource de base client (ou alternativement/facultativement dans un PUT vers une ressource client spécifique, s'il n'existe pas). REST ne dit rien sur le nombre d'enregistrements de base de données que vous devez créer lors d'un appel donné. Comme l'a commenté Colin Young, il n'est pas nécessaire d'avoir une base de données du tout, la façon dont les services sont mis en œuvre n'a aucune importance. d'un point de vue REST.

11
JimmyJames

Il y a de bonnes réponses ici, mais je ne suis pas sûr qu'elles vous aideront à convaincre vos collègues. Comme beaucoup l'ont souligné, ce que vous proposez n'est pas un abandon de la conception RESTful, et je pense que c'est la clé pour les intégrer à votre proposition.

REST est pas pour s'assurer que votre API ne permet que le stockage et la récupération de données. Il s'agit plutôt de modéliser les actions comme ressources. Votre API devrait permet d'effectuer des actions (c'est une interface Application Programmation, après tout). La question est comment pour modéliser ces actions.

Plutôt que de trouver un terme, les exemples sont probablement le meilleur moyen d'expliquer cela à vos collègues . De cette façon, vous pouvez montrer comment ils le font maintenant, quels problèmes cela provoque, une solution qui résout le problème et comment il reste RESTful.

Examinons votre objet client.

Problème:

L'interface utilisateur POST un client, mais les tableaux suivants n'ont pas encore été mis à jour. Que faire si l'un des appels suivants échoue en raison d'une erreur dans votre code d'interface utilisateur (ou d'un plug-in de navigateur incorrect, etc.)? Maintenant, vos données sont dans un état incohérent. Il peut même s'agir d'un état qui casse d'autres parties de votre API ou de votre interface utilisateur, sans oublier qu'il est tout simplement invalide. Comment récupérez-vous? Il faudrait tester chaque état possible pour être sûr que cela ne casserait pas quelque chose, mais il serait difficile de savoir ce qui est possible.

Solution:

Créez un point de terminaison API pour créer des clients. Vous savez que vous ne voulez pas avoir un point de terminaison "/ client/créer" ou même "/ créer-client", car créer est un verbe et violerait REST. Alors dénoncez-le. "/ client-creation" pourrait fonctionner. Maintenant, lorsque vous POST votre objet CustomerCreation, il enverra tous les champs nécessaires pour qu'un client soit entièrement créé. Le point de terminaison s'assurera que les données sont complètes et valides (en retournant un 400 ou quelque chose si c'est le cas) échoue la validation), et peut persister tout au sein d'une même transaction db, par exemple.

Si vous avez également besoin d'un point de terminaison pour obtenir des objets GET/client, c'est très bien. Vous pouvez avoir les deux. L'astuce consiste à créer des points de terminaison qui répondent aux besoins des consommateurs.

Avantages:

  1. Vous garantissez que vous ne vous retrouverez pas en mauvais état
  2. Il est en fait plus facile pour les développeurs d'interface utilisateur s'ils n'ont pas à "connaître" l'ordre des demandes, les problèmes de validation, etc.
  3. Ce n'est pas aussi bavard d'une API, ce qui réduit la latence des demandes réseau
  4. Il est plus facile de tester et de conceptualiser des scénarios (les éléments de données manquants/mal formés de l'interface utilisateur ne sont pas répartis entre les demandes, dont certaines peuvent échouer)
  5. Il permet une meilleure encapsulation de la logique métier
  6. Rend généralement la sécurité plus facile (car la logique métier et d'orchestration dans l'interface utilisateur peut être modifiée par les utilisateurs)
  7. Réduira probablement la duplication logique (il est plus probable que vous ayez 2+ consommateurs d'une API que 2+ API qui donnent accès aux mêmes données)
  8. 100% RESTful

Inconvénients:

  1. C'est potentiellement plus de travail pour le développeur backend (mais peut-être pas à long terme)

Il peut être difficile pour les gens de comprendre ce paradigme et ses avantages s'ils ne l'ont pas essayé. J'espère que vous pourrez les aider à voir en utilisant un exemple de votre propre code.

D'après ma propre expérience, une fois que les développeurs de mon équipe ont commencé à mettre en œuvre cette stratégie, ils ont presque immédiatement vu les avantages.

Étude complémentaire:

Cet article de thinkworks m'a vraiment aidé à avoir l'idée de modéliser des actions en tant qu'objets à l'aide d'exemples pratiques: https://www.thoughtworks.com/insights/blog/rest-api-design-resource-modeling

Je suggérerais également de lire CQRS et Event Sourcing car ils sont précisément concernés par ce genre de chose (c'est-à-dire séparer votre API de la logique de persistance réelle) . Je ne sais pas à quel point vos collègues seraient prêts à lire ce genre de chose, mais cela pourrait vous donner plus de clarté et vous aider à leur expliquer.

3
Planky