Api model na interfejsach

0

Cześć,

czy spotkaliście z designem w którym objekty modelu api są zdefiniowane przez interfejsy ?

Mamy w projekcie libkę która jest wrapperem api do zewnętrznego serwisu. Objekty rq i rs zą zdefiniowne przez interfejsy :

np.

interface Request{

	Long id();
	String phoneNumber();
	String name()
	String address();
}

Nie ma tu żadnego zachowania, tylko definicja pól.

Architekt bardzo broni tego rozwiązania bo niby jest prosty model i rozszerzalny itp.. ale brak konkretów

Ja widzę tylko wady, jak

  • brak możliwości łatwej serializacji (użycia objecMapper), nie działa to na interfejsach, przez co potrzebna jest dodatkowa logika mapująca objekty api.
  • implementacja objektów(rs, rq) po stronie wygląda dziwnie, ponieważ trzeba zaimplementować odpowiednie metody zamiast przekazać argumenty przez konstruktor.

Co sądzicie ?
Czy to ma sens ?

Maciej

1

Do tej pory nie spotkałem się by ktoś tak robił. Jest to zaburzenie pewnej konwencji w imię dodatkowych narzędzi. Równie dobrze można pisać ciągiem kod bez metod albo wszystko robić public bo jest szybciej. Pytanie jak bardzo doświadczony jest architekt i czy ma dobre uzasadnienie do tego pomysłu. Jeżeli w Waszym przypadku działa to świetnie to narzędzie jest dla programisty, a nie programista dla narzędzia. Natomiast jeżeli jest to bardziej zachcianka to za jakiś czas będzie kolejna i kolejna i kod będzie cięższy do utrzymania. Z praktyki; czasem nadmiernie dodawało się kontruktory z uwagi na poszczególne DI, testy albo serializację bo inaczej nie szło ruszyć małym nakladem czasu.Takie interfejsy z polami to taka klasa abstrakcyjna, tylko że interfejsy można dziedziczyć w nieskonczoność, a klasę abstrakcyjną raz. Może warto poczytać "Przyczyny dziedziczenia klasy abstrakcyjnej tylko raz", może tam będzie coś co da Ci do myślenia. Mówię to w kontekście C#, w każdym języku jest trochę inaczej.

2

Dziwnie to wygląda. Do takich rzeczy IMO tylko data classy / rekordy - bo to jest paczka danych, a nie jakiś zestaw metod

1

Co jeśli w interfejsie pojawi się nowa metoda String gender(), która będzie miała jakąś domyślna implementację, a Ty nie jesteś zainteresowany tematyką gender() ? Wywali Ci to Twoją implementację? Co by było w przypadku, gdyby to była data class z konstruktorem, który oczekuje gender? Dopytałbym jednak architekta, czy zastosowanie buildera dla Request/Response nie rozwiązuje problemu i jaką dynamikę zmian przewiduje dla tych interfejsów. Być może wilk byłby syty i owca cała.

0

@p_maciek oczywiście że się spotkałem. Taka struktura jak ta co ją przedstawiłeś ma same zalety:

  • jest banalna w utrzymaniu.
  • jest skalowalna do w zasadzie dowolnej wielkości
  • jest banalna w optymalizacji
  • daje w zasadzie nieograniczone możliwości ekspansi poziomej jak i pionowej
  • można ją dowolnie dziedziczyć.

Jest spora grupa osób uparcie twierdząca że owa struktura nie ma zalet, natomiast ma cały szereg wad i oni tej struktury nie zastosują. Prawda jest jednak taka iż owa struktura jest coraz częściej wykorzystywana przez dużych graczy z powodzeniem.

1
mustang_ex napisał(a):

@p_maciek oczywiście że się spotkałem. Taka struktura jak ta co ją przedstawiłeś ma same zalety:

  • jest banalna w utrzymaniu.

Nie bardziej niz taka sama struktura zaimplementowana jako rekord.

  • jest skalowalna do w zasadzie dowolnej wielkości

Nie bardziej niz taka sama struktura zaimplementowana jako rekord.

  • jest banalna w optymalizacji

Nie bardziej niz taka sama struktura zaimplementowana jako rekord.

  • daje w zasadzie nieograniczone możliwości ekspansi poziomej jak i pionowej

Nie bardziej niz taka sama struktura zaimplementowana jako rekord.

  • można ją dowolnie dziedziczyć.

Nie bardziej niz taka sama struktura zaimplementowana jako rekord.

Jest spora grupa osób uparcie twierdząca że owa struktura nie ma zalet, natomiast ma cały szereg wad i oni tej struktury nie zastosują. Prawda jest jednak taka iż owa struktura jest coraz częściej wykorzystywana przez dużych graczy z powodzeniem.

To podasz jakies te zalety wzgledem zwyklego rekordu?

1

Na podstawie tego co powiedziałeś to w zasadzie ciężko stwierdzić czy to dobrze czy nie dobrze. Musiałbyś opisać więcej rzeczy.

Sam pomysł żeby interfejsem na jakieś API były po prostu interfejsy abstrakcyjne ma szanse działać, jeśli się to dobrze zrobi.

yarel napisał(a):

Co jeśli w interfejsie pojawi się nowa metoda String gender(), która będzie miała jakąś domyślna implementację, a Ty nie jesteś zainteresowany tematyką gender() ? Wywali Ci to Twoją implementację? Co by było w przypadku, gdyby to była data class z konstruktorem, który oczekuje gender? Dopytałbym jednak architekta, czy zastosowanie buildera dla Request/Response nie rozwiązuje problemu i jaką dynamikę zmian przewiduje dla tych interfejsów. Być może wilk byłby syty i owca cała.

Ale te interfejsy za pewne nie byłyby implementowane przez autora. To miałby być tylko interfejs wejściowy, jak rozumiem.

Jak konsumujesz taki input, to w zasadzie co za różnica czy wołasz Response record; record.name czy Response interfejs; interfejs.name().

Natomiast jak mówimy o tym że to ma być wyjściowy interfejs, to problem jest w zasadzie ten sam co z recordem. Jeśli twórca interfejsu wejściowego chce dodać nowe pole (nie ważne czy pole w recordzie czy metodę w interfejsie), to tak czy tak tą daną trzeba dodać (Albo jako pole, albo jako metodę). Chyba że twórca chciałby robić jakieś "tricki" (nie warto) z domyślnymi wartościami, np. domyślne pole w recordzie, albo domyślna metoda w interfejsie, ale to jest słabe.

Więc moim zdaniem na to samo wychodzi.

0

Dzieki za odpowiedzi. Mieliśmy w zespole deyskusje o tym. Ogólnie ktoś kiedyś zastosował taki design i próbowałem się dowiedzieć z czego to wynika ale nie dowiedziałem się niż poza tym że to jest api i taki design jest super prosty bo nie zawiera zbędnych rzeczy jak implementacje getterow, setterow. Cała implementacja jest przerzucona na klientów.
W przypadku naszego projektu ja zauważyłem tylko problemy jakie z tego wynikają np. brak możliwości łatwej serializacj/deserializacji czy zapiecia walidacji na polach api. Argument prostoty nie wg mnie nie wnosi nic istotnego.

Natomiast ciekawą rzecz poruszył @mustang_ex o skalowalności. Zaintrygowalo mnie to. Mozesz rozszerzyć co masz na myśli? Czy chodzi o to, że na tym samym api interfejsowym można np. oprzeć implementacje różnych model?. Np. dla protokolu REST z odnotacjami restowymi. To miałoby chyba sens...

0
p_maciek napisał(a):.

W przypadku naszego projektu ja zauważyłem tylko problemy jakie z tego wynikają np. brak możliwości łatwej serializacj/deserializacji czy zapiecia walidacji na polach api.

Moim zdaniem to nie jest wada.

Jeśli api ma wspierać serializację, to powinno być to należycie przemyślane i zaprojektowanie.

Jak mówisz *skorzystamy z recordów, bo będzie się to dało łatwo serializować", to wtedy taka cecha doszła by praktycznie przypadkiem. Pewnie nie byłaby przetestowana odpowiednio, etc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1