Pozostałe interfejsy API - wyzwania specyficzne dla urządzeń mobilnych

25

Pracuję nad nowym projektem aplikacji na iOS po stronie mobilnej. Trwają pewne zmiany architektury i okazuje się, że będziemy musieli polegać na niestandardowym, prywatnym interfejsie API, który będzie używany przez aplikację, którą tworzymy, a także przez innych klientów, takich jak strona internetowa.

Zaprojektowany interfejs API jest zgodny ze stylem Rest operacji URI i CRUD zorientowanych na zasoby odwzorowanych na czasowniki HTTP. rzeczy jak:

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

Problem polega na tym, że ten styl często powoduje, że klient mobilny musi wykonywać wiele żądań ładowania pojedynczego ekranu aplikacji lub zarządzania pojedynczym działaniem interfejsu użytkownika. To powoduje, że aplikacja jest w trybie ładowania przez 8 sekund, aż będzie miała wszystko, czego potrzeba. Wolna i niereagująca aplikacja.

Klienci mobilni mają poważne ograniczenia, jeśli chodzi o łączność, dlatego najlepiej jest przestrzegać takiej zasady:

1 ekran == 1 wywołanie API

1 zapis == 1 wywołanie API.

Istnieje wiele sytuacji, w których stawia Cię kurs kolizyjny z zasadami projektowania REST, na przykład:

  • powiedzmy, że Twoja aplikacja była offline przez jeden dzień i musisz zsynchronizować się z czterema tabelami baz danych zaplecza i potrzebujesz połączenia takiego jak www.example.com/sync_everything?since=2015-07-24
  • powiedzmy, że jest ekran, na którym użytkownik może edytować wiele swoich obiektów, na przykład zaznaczanie zadań na swojej liście zadań. powinien istnieć sposób edycji wszystkich tych rekordów zadań w jednym pojedynczym wywołaniu interfejsu API zamiast jednego wywołania interfejsu API na edycję.
  • powiedzmy, że jest ekran, który miesza informacje z tabel db ORDER, SALESMEN i PRODUCT, powinienem uzyskać te dane w jednym wywołaniu zamiast trzech.

istnieje ryzyko, że możemy skończyć z najbardziej restrykcyjnym interfejsem API, jaki istnieje, a także z najbardziej bezużyteczną, niereagującą aplikacją mobilną.

Chodzi o to, że jestem tam tylko nowym kontrahentem i potrzebuję czegoś, co pomogłoby mi przedstawić te punkty, niektóre artykuły z cenionych źródeł lub coś w tym rodzaju. Główni gracze kompromitują się ze stylem REST dla swojego klienta mobilnego (np. Poprzez użycie punktów końcowych zagregowanego API złożonego).

Lub jakiekolwiek rozwiązanie tego ogólnego problemu. Dzięki!

MikaelW
źródło
3
Wygląda na to, że twoje pytanie brzmi: „W jaki sposób interfejs API może dostarczać kolekcje obiektów i osadzonych obiektów podobnych lub niepodobnych typów, zachowując styl REST?” Czy rozumiem twoje pytanie?
joshp,
Uważam, że ogólną odpowiedzią jest to, że każde wywołanie REST musi przyjmować różnorodne parametry opcjonalne, aby mogło być elastyczne, a jednocześnie względnie intuicyjne. Przypadek synchronizacji zawsze będzie trudny, ale w przypadku zwykłych stron zwykle oglądasz kilka wywołań tego samego typu , tj. Wszystkie GETY, prawda?
Ixrec
1
Myślę, że dostosowanie interfejsu API jest złym rozwiązaniem, gdy problemem jest brak równoległych żądań - 8 małych żądań nie jest dużo gorszych niż jedno duże żądanie, gdy nie muszą na siebie czekać. Czy możesz przejść na HTTP / 2? Lub przynajmniej użyć potokowania HTTP / 1.1?
amon
Zobacz także: Wzorce obsługi operacji wsadowych w usługach internetowych REST? . Kluczem jest określenie, jakie rodzaje poleceń (i pod jakimi warunkami) można łączyć ze sobą bez konfliktów, a następnie utworzyć reprezentację JSON kolejności wsadowej, a następnie przesłać ją. Traci główną atrakcyjność dla REST, którą jest pamięć podręczna, ale pamięć podręczna nie zawsze jest odpowiednia dla wszystkich rodzajów aplikacji. Należy pamiętać, że partia / współbieżność nie ma zastosowania, jeśli istnieją logiczne zależności.
rwong,
Analogią do sytuacji, w której pośrednik musi wykonywać wiele operacji w sekwencji, z nietrywialnymi logicznymi zależnościami od każdej poprzedniej operacji, jest coś w rodzaju „procedury składowanej”, która jest wykonywana w tym pośredniku zamiast w bazie danych. Pod spodem pośrednik może konwertować pojedyncze wywołanie „procedury składowanej” na tyle żądań RESTful, ile potrzeba, ale jest to szczegół implementacji pośrednika.
rwong,

Odpowiedzi:

27

Zaprojektowany interfejs API jest zgodny ze stylem Rest operacji URI i CRUD zorientowanych na zasoby odwzorowanych na czasowniki HTTP.

To jest twój problem tutaj.

Ograniczyłeś swoje zasoby do (zakładam) modeli w bazie danych. W związku z tym ładowanie wszystkich tych zasobów trwa wieki, ponieważ twój serwer nie ma pojęcia o zasobach, które nie mają reprezentacji w bazie danych.

Na przykład może mieć

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

wszystkie muszą zostać załadowane, aby uzyskać moją bibliotekę

To nie jest problem z RESTful design, to jest faktycznie anty-wzorzec REST. W REST absolutnie nic nie mówi, że nasze zasoby muszą mieć mapowanie jeden na jeden z czymkolwiek innym w twoim systemie, w tym modelami baz danych.

Rozwiązaniem jest utworzenie większej liczby zasobów, które lepiej pasują do tego, co chcesz załadować. Jeśli masz 5 zasobów, które zawsze kończą się razem, utwórz nowy zasób zawierający informacje o tych 5 zasobach.

Powinieneś mieć coś takiego

www.example.com/users/334/my_library

który po prostu ładuje wszystkie książki dla tego użytkownika. „moja_biblioteka” nie jest modelem w bazie danych, ale jest zasobem. Serwer tworzy go na podstawie modeli w bazie danych, ale nie ma mapowania 1 do 1, a serwer ma elastyczność w tworzeniu tego zasobu bez zmiany modelu DB.

Ty też możesz mieć

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

z których żaden nie musi istnieć jako model w bazie danych lub przestrzeni domeny.

Istnieje powszechne błędne przekonanie, że jest to niewłaściwa rzecz, ponieważ frameworki, takie jak Rails, nauczyły ludzi mapowania zasobów w sposób 1: 1 na modele w przestrzeni domeny, które ponownie mapują 1: 1 z wierszami bazy danych. Nie jest to konieczne ani zalecane.

Zasoby powinny być liczne, tanie i lekkie . Utworzenie ich powinno być łatwe i powinny zostać wyodrębnione z modelu domeny. Jeśli uznasz, że potrzebujesz nowego, po prostu stwórz nowy. Jeśli masz problemy z robieniem tego, jest to wina twoich ram, a nie błąd REST.

Teraz dużym zastrzeżeniem jest to, czy twoje ramy na to pozwalają. Ramy takie jak Rails i Django, które przeszły kurs mapowania 1-do-1 w celu „zaoszczędzenia czasu”, utrudniają to. Jest to jednak wada ram, a nie RESTful.

Oto Jim Webber omawiający to bardziej szczegółowo (w tym także kilka wykopalisk w Railsach!)

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

Cormac Mulhall
źródło
Jest to bardzo interesujące i całkowicie się z tym zgadzam, ale niestety nie jestem tym, który robi API i nie mam na to żadnego wpływu. Wiele osób będzie używać tego „anty-wzorca” wszędzie (z wielu powodów, z jednymi ograniczeniami ramowymi) i po prostu używają definicji URI do jasnego myślenia o swojej bazie danych. Punkty końcowe interfejsu API są po prostu innym sposobem wizualizacji ich bazy danych ... Ponadto w niektórych przypadkach utworzenie zasobu, takiego jak ten, który opisałeś, jest trudne ze względu na fakt, że obiekty są naprawdę różne, po prostu ich nazwanie prowadziłoby do bardzo niejasnych terminów.
MikaelW,
Wracając do kwestii z punktu widzenia wydajności, zgodzili się, że jeśli ekran telefonu komórkowego jest bardzo wolny (i tylko jeśli tak się stanie), możliwe będą pewne połączenia kompozytowe, ale będą siedzieć w komponencie, który otacza interfejs API ( zamiast samego interfejsu API), będą używane tylko przez klientów mobilnych i nie będą uważane za część podstawowego interfejsu API, podstawowej domeny.
MikaelW,
@MikaelW, masz rację. Nawet to, co powiedział Cormac, jest idealnym scenariuszem. Czasami pracujesz z interfejsem API, który musi obsługiwać wiele innych systemów (komputer, telefon komórkowy, Internet, zaplanowane zadania, starsze systemy itp.). Ten rodzaj interfejsu API musi być naprawdę elastyczny, zapewniając zasoby pozwalające na korzystanie z wielu możliwych możliwości, ale nie może zaspokoić wszystkich szczególnych potrzeb wydajnościowych od jednego konsumenta. W takim razie nie masz wielu możliwości wyboru ...
Dherik,