Api model na interfejsach

PM
  • Rejestracja:prawie 8 lat
  • Ostatnio:7 miesięcy
  • Postów:30
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.

Kopiuj
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

AX
  • Rejestracja:ponad rok
  • Ostatnio:7 miesięcy
  • Postów:12
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.

dalbajob
  • Rejestracja:prawie 2 lata
  • Ostatnio:3 miesiące
  • Postów:149
3

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

YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 10 godzin
  • Postów:2367
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.

mustang_ex
  • Rejestracja:ponad rok
  • Ostatnio:18 dni
  • Postów:98
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.

edytowany 1x, ostatnio: mustang_ex
KL
  • Rejestracja:12 miesięcy
  • Ostatnio:około 3 godziny
  • Postów:372
2
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?

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10053
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.

edytowany 4x, ostatnio: Riddle
PM
  • Rejestracja:prawie 8 lat
  • Ostatnio:7 miesięcy
  • Postów:30
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...

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10053
1
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.

Miang
  • Rejestracja:prawie 7 lat
  • Ostatnio:3 minuty
  • Postów:1659
1
p_maciek napisał(a):

Cześć,

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

masz Interfejs (zastanów się co to znaczy rozwinięcie skrótu API) zadeklarowany interfejsami

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

  • 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.

ten zewnętrzny serwis byś serializował?

a spotkać się można w interfejsach do windowsowych dllek na przykład


dzisiaj programiści uwielbiają przepisywać kod z jednego języka do drugiego, tylko po to by z projektem nadal stać w miejscu ale na nowej technologii
edytowany 1x, ostatnio: Miang
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
0
Riddle napisał(a):

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.

Co jest przypadkowego w używaniu znanych bibliotek do serializacji danych?

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0
somekind napisał(a):
Riddle napisał(a):

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.

Co jest przypadkowego w używaniu znanych bibliotek do serializacji danych?

Jeśli coś ma być serializowane, to lepiej żeby to było widać explicitly, np. żeby był test pod to.

Jeśli nie, to ktoś mógłby chcieć kiedyś zrefaktorować record na klasę i ups, zepsuł serializacje.

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
0
Riddle napisał(a):

Jeśli coś ma być serializowane, to lepiej żeby to było widać explicitly, np. żeby był test pod to.

Ale to jest oczywiste, że kontrakt API jest serializowany, bo inaczej się danych do API przesłać nie da.

Jeśli nie, to ktoś mógłby chcieć kiedyś zrefaktorować record na klasę i ups, zepsuł serializacje.

Rekord to jest klasa, po prostu kompilator w locie dodaje jej kilka metod.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10053
0
somekind napisał(a):
Riddle napisał(a):

Jeśli coś ma być serializowane, to lepiej żeby to było widać explicitly, np. żeby był test pod to.

Ale to jest oczywiste, że kontrakt API jest serializowany, bo inaczej się danych do API przesłać nie da.

No to skoro tak, to post do którego się odnosiła moja odpowiedź (na którą z kolei Ty odpowiedziałeś) nie ma sensu (ten: #1960094)

edytowany 1x, ostatnio: Riddle
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)