web-dev-qa-db-fra.com

Comment dois-je gérer les hiérarchies d'objets dans une API RESTful?

Je suis en train de concevoir l'API pour une application PHP existante, et à cette fin, j'étudie REST comme une approche architecturale sensée).

Je crois que j'ai une compréhension raisonnable des concepts clés, mais j'ai du mal à trouver quelqu'un qui a abordé les hiérarchies d'objets et REST.

Voici le problème ...

Dans la hiérarchie des objets métier [application], nous avons:

Users 
 L which have one-to-many Channel objects
 L which have one-to-many Member objects

Dans l'application elle-même, nous utilisons une approche de chargement paresseux pour remplir l'objet Utilisateur avec des tableaux de ces objets selon les besoins. Je crois aux termes OO c'est de l'agrégation d'objets, mais j'ai vu diverses incohérences de nommage et je ne tiens pas à déclencher une guerre contre la convention de nommage précise.

Pour l'instant, considérez que j'ai quelques objets faiblement couplés que je peux/peut ne pas remplir en fonction des besoins de l'application.

Du point de vue REST, j'essaie de déterminer quelle devrait être l'approche. Voici ma pensée actuelle (en considérant GET uniquement pour le moment):

Option 1 - remplir entièrement les objets:

GET api.example.com/user/{user_id}

Lisez l'objet User (ressource) et renvoyez l'objet User avec tous les objets Channel et Member possibles préchargés et codés (JSON ou XML).

AVANTAGES: réduction du nombre d'objets, aucune traversée des hiérarchies d'objets requise
CONTRE: les objets doivent être entièrement remplis (coûteux)

Option 2 - remplir l'objet principal et inclure des liens vers les autres ressources d'objet:

GET api.example.com/user/{user_id}

Lisez l'objet utilisateur (ressource) et renvoyez les données utilisateur de l'objet utilisateur remplies et deux listes.

Chaque liste fait référence à la (sous-) ressource appropriée, c'est-à-dire.

api.example.com/channel/{channel_id}
api.example.com/member/{member_id}

Je pense que cela est proche (ou exactement) des implications de l'hypermédia - le client peut obtenir les autres ressources s'il le souhaite (tant que je les étiquette de manière raisonnable).

AVANTAGES: le client peut choisir de charger les subordonnés ou autrement, une meilleure séparation des objets en tant que ressources REST
CONS: voyage supplémentaire nécessaire pour obtenir les ressources secondaires

Option 3 - activer les récupérations récursives

GET api.example.com/user/{user_id}

Lisez l'objet utilisateur et incluez des liens vers les listes des sous-objets, c'est-à-dire.

api.example.com/user/{user_id}/channels
api.example.com/user/{user_id}/members

l'appel/channels renverrait une liste de ressources de canaux sous la forme (comme ci-dessus):

api.example.com/channel/{channel_id}

AVANTAGES: les ressources primaires indiquent où aller pour obtenir les sous-définitions mais pas ce qu'elles sont (plus RESTful?), Aucune obligation d'obtenir les subordonnés à l'avance, les générateurs de listes subordonnés (/ canaux et/membres) fournissent des interfaces (méthode similaire) la réponse plus de service comme.
CONS: trois appels sont maintenant nécessaires pour remplir entièrement l'objet

Option 4 - (re) considérer la conception d'objet pour REST

Je réutilise la hiérarchie des objets d'application [existants] et j'essaie de l'appliquer à REST - ou peut-être plus directement, lui fournir une interface API.

Peut-être que la hiérarchie d'objets REST devrait être différente, ou peut-être que la nouvelle pensée RESTful expose les limites de la conception d'objet existante.

Toute réflexion sur ce qui précède est la bienvenue.

Merci beaucoup

Paul

68
paulkmoore

Il n'y a aucune raison de ne pas les combiner.

  • api.example.com/user/{user_id} - retourne une représentation utilisateur
  • api.example.com/channel/{channel_id} - retourne une représentation de canal
  • api.example.com/user/{user_id}/channels - retourne une liste de représentations de canaux
  • api.example.com/user/{user_id}/channel_list - retourne une liste des identifiants de canaux (ou des liens vers leurs représentations complètes, en utilisant les liens ci-dessus)

En cas de doute, réfléchissez à la façon dont vous afficheriez les données à un utilisateur humain sans soucis "API": un utilisateur souhaite les deux pages d'index ({user_id}/channel_list) et des vues complètes ({user_id}/channels).

Une fois que vous avez cela, il suffit de prendre en charge JSON au lieu de (ou en plus de) HTML comme format de représentation, et vous avez REST.

39
Pi Delport

Le meilleur conseil que je puisse donner est d'essayer d'éviter de penser à votre REST api comme exposant vos objets. Les ressources que vous créez doivent prendre en charge les cas d'utilisation dont vous avez besoin. Si nécessaire, vous pouvez créer des ressources pour tous trois options:

api.example.com/completeuser/{id}
api.example.com/linkeduser/{id}
api.example.com/lightweightuser/{id}

Évidemment, mes noms sont un peu loufoques, mais peu importe comment vous les appelez. L'idée est que vous utilisez le REST api pour présenter les données de la manière la plus logique pour le scénario d'utilisation particulier. S'il y a plusieurs scénarios, créez plusieurs ressources, si nécessaire. J'aime penser à mes ressources ressemblent plus à des modèles d'interface utilisateur qu'à des entités commerciales.

25
Darrel Miller

Je recommanderais Restful Obects qui est des normes pour exposer reposant du modèle de domaine

L'idée de Restful Objects est de fournir une interface RESTful standard et générique pour les modèles d'objets de domaine, exposant les représentations de leur structure à l'aide de JSON et permettant les interactions avec les instances d'objets de domaine à l'aide de HTTP GET, POST, PUT et DELETE.

Selon la norme, les URI seront comme:

  • api.example.com/object/user/31
  • api.example.com/object/user/31/properties/username
  • api.example.com/object/user/31/collections/channels
  • api.example.com/object/user/31/collections/members
  • api.example.com/object/user/31/actions/someFunction
  • api.example.com/object/user/31/actions/someFunction/invoke

Il existe également d'autres ressources

  • api.example.com/services
  • api.example.com/domain-types

La spécification définit quelques représentations principales:

  • objet (qui représente tout objet ou service de domaine)
  • liste (de liens vers d'autres objets)
  • propriété
  • collection
  • action
  • résultat de l'action (contenant généralement un objet ou une liste, ou simplement des messages de rétroaction)
  • et aussi un petit nombre de représentations secondaires telles que la maison et l'utilisateur

Ceci est intéressant car vous verrez que les représentations sont entièrement auto-descriptives, ouvrant la possibilité d'implémenter des visualiseurs génériques si nécessaire.

Alternativement, les représentations peuvent être consommées directement par une application sur mesure.

9
Yasir Hantoush

Voici mes conclusions de nombreuses heures de recherche et avec la contribution des répondants ici:

Lorsque j'ai un objet qui est effectivement un objet en plusieurs parties, je dois le traiter comme une ressource unique. Ainsi, si j'obtiens l'objet, toutes les sous-coordonnées doivent être présentes. Cela est nécessaire pour que la ressource puisse être mise en cache. Si je charge partiellement l'objet (et fournit un tampon ETag), les autres demandeurs peuvent recevoir un objet partiel lorsqu'ils en attendaient un complet. Conclure - les objets doivent être entièrement remplis s'ils sont mis à disposition en tant que ressources.

Les relations d'objets associées doivent être mises à disposition sous forme de liens vers d'autres ressources (principales). De cette façon, les les objets sont détectables en traversant l'API.

En outre, la hiérarchie d'objets qui avait du sens pour le site d'application principal peut ne pas sembler être ce dont vous avez besoin pour agir de manière RESTful, mais elle révèle plus probablement des problèmes avec la hiérarchie existante. Cela dit, l'API peut nécessiter des cas d'utilisation plus spécialisés que ce qui avait été envisagé auparavant, et des ressources spécialisées peuvent être nécessaires.

J'espère que cela aide quelqu'un

6
paulkmoore