API Rest - défis spécifiques aux mobiles

25

Je travaille sur un nouveau projet d'application iOS, côté mobile. Certains changements d'architecture sont en cours et il s'avère que nous devrons compter sur une API privée personnalisée qui sera utilisée par l'application que nous construisons et également par d'autres clients tels qu'un site Web.

L'API en cours de conception suit le style Rest des opérations URI et CRUD centrées sur les ressources mappées aux verbes HTTP. des choses comme:

GET www.example.com/books
DELETE www.example.com/books/482094
POST www.example.com/users/6793

Le problème est que ce style entraîne souvent la nécessité pour le client mobile de faire de nombreuses demandes pour charger un seul écran d'application ou gérer une seule action d'interface utilisateur. Cela conduit à l'application en mode de chargement pendant 8 secondes jusqu'à ce qu'elle ait tout le nécessaire. Une application lente et qui ne répond pas.

Les clients mobiles ont de sérieuses limitations en matière de connectivité et donc idéalement, nous devrions suivre ce genre de règle:

1 écran == 1 appel API

1 sauvegarde == 1 appel API.

Il existe de nombreuses situations où cela vous met sur une trajectoire de collision avec les principes de conception REST, par exemple:

  • disons que votre application est hors ligne depuis un jour et que vous devez vous synchroniser avec quatre tables des bases de données principales et que vous avez besoin d'un appel comme www.example.com/sync_everything?since=2015-07-24
  • disons qu'il y a un écran où l'utilisateur peut éditer plusieurs de ses objets, par exemple en cochant des tâches dans sa liste de tâches. il devrait y avoir un moyen de modifier tous ces enregistrements de tâches en un seul appel d'API par lots plutôt qu'en un seul appel d'API par modification.
  • disons qu'il y a un écran qui mélange les informations des tables db ORDER, SALESMEN et PRODUCT, je devrais obtenir ces données en un seul appel au lieu de trois.

le risque est que nous puissions nous retrouver avec l'API la plus reposante qui soit et aussi avec l'application mobile la plus inutile qui soit.

Le fait est que je ne suis qu'un nouvel entrepreneur là-bas et ce dont j'ai besoin, c'est de quelque chose qui m'aide à faire valoir ces points, de certains articles de sources bien respectées ou quelque chose comme ça. Les principaux acteurs faisant des compromis avec le style REST pour leur client mobile (par exemple: en utilisant des points de terminaison d'API d'agrégats composites).

Ou toute solution à ce problème général. Merci!

MikaelW
la source
3
Il semble que votre question pourrait être: "Comment une API peut-elle fournir des collections d'objets et d'objets intégrés de types similaires ou différents tout en conservant le style REST?" Suis-je en train de comprendre votre question?
joshp
Je crois que la réponse générale est que chaque appel REST doit prendre une variété de paramètres facultatifs afin qu'il puisse être flexible tout en restant relativement intuitif. Le cas de synchronisation sera toujours délicat, mais pour les pages normales, vous regardez normalement plusieurs appels du même type , c'est-à-dire tous les GET, non?
Ixrec
1
Je pense que l'adaptation de votre API n'est pas la bonne solution lorsque le problème est le manque de demandes parallèles - 8 petites demandes ne sont pas bien pires qu'une grande demande lorsqu'elles n'ont pas à attendre les unes des autres. Pouvez-vous passer à HTTP / 2? Ou au moins utiliser le pipeline HTTP / 1.1?
amon
Voir aussi: Modèles de gestion des opérations par lots dans les services Web REST? . La clé consiste à identifier quels types de commandes (et dans quelles conditions préalables) peuvent être regroupées par lots sans conflits, puis à créer une représentation JSON de la commande par lots, puis à les envoyer. Il perd l'attractivité principale pour REST qui est sa mise en cache mais la mise en cache n'est pas toujours pertinente pour tous les types d'applications. Notez que le traitement par lots / simultané n'est pas applicable s'il existe des dépendances logiques.
rwong
Une analogie pour la situation où l'intermédiaire doit effectuer plusieurs opérations dans une séquence, avec des dépendances logiques non triviales sur chaque opération précédente, est quelque chose comme une "procédure stockée", qui est exécutée dans cet intermédiaire plutôt qu'à l'intérieur d'une base de données. En dessous, l'intermédiaire est autorisé à convertir un seul appel de "procédure stockée" en autant de demandes RESTful que nécessaire, mais c'est un détail d'implémentation de l'intermédiaire.
rwong

Réponses:

27

L'API en cours de conception suit le style Rest des opérations URI et CRUD centrées sur les ressources mappées aux verbes HTTP.

C'est votre problème ici.

Vous avez limité vos ressources (je suppose) aux modèles de votre base de données. En tant que tel, il faut du temps pour charger toutes ces ressources car votre serveur n'a aucun concept de ressources qui n'ont pas de représentation dans la base de données.

Par exemple, pourrait avoir

www.example.com/books/482094
www.example.com/books/582045
www.example.com/books/427454
www.example.com/books/319343

que tous doivent être chargés pour obtenir ma bibliothèque

Ce n'est pas un problème avec la conception RESTful, c'est en fait un anti-motif REST. Il n'y a absolument rien dans REST qui dit que nos ressources doivent avoir un mappage un à un avec tout autre élément de votre système, y compris les modèles de base de données.

La solution est de créer plus de ressources qui correspondent mieux à ce que vous souhaitez charger. Si vous avez 5 ressources qui finissent toujours ensemble, créez une nouvelle ressource qui contient les informations pour ces 5 ressources.

Vous devriez avoir quelque chose comme ça

www.example.com/users/334/my_library

qui charge juste tous les livres pour cet utilisateur. "my_library" n'est pas un modèle dans votre base de données, mais c'est une ressource. Le serveur le crée en fonction des modèles de la base de données, mais il n'y a pas de mappage 1 à 1 et le serveur a la possibilité de créer cette ressource sans modifier votre modèle de base de données.

Vous pourriez aussi avoir

www.example.com/users/334/favioured_books
www.example.com/users/334/books_ordered_last_week
www.example.com/users/334/wishlist

aucun d'entre eux ne doit exister en tant que modèle dans votre base de données ou votre espace de domaine.

Il y a une idée fausse largement répandue selon laquelle ce n'est pas la bonne chose à faire, car des cadres comme Rails ont appris aux gens à mapper les ressources de manière 1 à 1 aux modèles de l'espace de domaine qui mappent à nouveau 1 à 1 avec des lignes de base de données. Ce n'est ni nécessaire ni recommandé.

Les ressources doivent être nombreuses, bon marché et légères . Il doit être facile de les créer et ils doivent être extraits de votre modèle de domaine. Si vous trouvez que vous en avez besoin d'un nouveau, il vous suffit d'en créer un nouveau. Si vous avez des problèmes à le faire, c'est la faute de votre framework, pas une faute avec REST.

Maintenant, la grande mise en garde avec cela est bien sûr de savoir si votre cadre vous permet de le faire. Des frameworks comme Rails et Django qui ont suivi le cours de mappage 1 à 1 afin de "vous faire gagner du temps" compliquent la tâche. Mais c'est un défaut avec les cadres, pas avec la conception RESTful.

Voici Jim Webber discutant de cela plus en détail (y compris quelques fouilles sur Rails aussi!)

https://yow.eventer.com/yow-2011-1004/domain-driven-design-for-restful-systems-by-jim-webber-1047

Cormac Mulhall
la source
C'est très intéressant et je suis entièrement d'accord avec cela, mais malheureusement, je ne suis pas celui qui fait l'API et j'ai peu de moyens de l'influencer, le cas échéant. Beaucoup de gens utiliseront cet "anti-modèle" partout (pour de nombreuses raisons, les limitations du cadre étant un) et ils utilisent simplement la définition d'URI pour penser clairement à leur base de données. Les points de terminaison API ne sont qu'une autre façon de visualiser leur base de données ... De plus, dans certains cas, la création d'une ressource telle que celle que vous avez décrite est difficile car les objets sont vraiment différents, le simple fait de les nommer conduirait à des termes très vagues.
MikaelW
Pour revenir au problème sous l'angle de l'efficacité, ils ont convenu que si un écran mobile est très lent (et seulement si cela se produit), il y aura des appels composites possibles, mais ils seront assis dans un composant qui entoure l'API ( plutôt que l'API elle-même), ne sera utilisé que par les clients mobiles et ne sera pas considéré comme faisant partie de l'API principale, le domaine principal.
MikaelW
@MikaelW, vous avez raison. Même ce que Cormac a dit est le scénario idéal, parfois vous travaillez avec une API qui a besoin de participer à de nombreux autres systèmes (ordinateur de bureau, mobile, Web, travaux planifiés, systèmes hérités, etc.). Ce type d'API doit être vraiment flexible, fournissant des ressources pour assister à de nombreuses possibilités, mais ne peut pas répondre à toutes les exigences de performances spécifiques d'un seul consommateur. Dans ce cas, vous n'avez pas beaucoup de choix ...
Dherik