Nauka API - gdzie umieszczać logikę biznesową wykraczającą poza zwykły CRUD?

0
piotrpo napisał(a):

@loza_prowizoryczna Serio porównujesz szyfrowanie asymetryczne do zaciemnonego kodu JS?

Nie, jakbyś wcześniej czytał co napisałem to byś zrozumiał że udostępnienie fragmentu logiki biznesowej na zewnątrz. g**no daje jeśli chodzi o bezpieczeństwo. Już pomijam że dzisiaj w większości nie trzeba robić obfuskacji JS tylko po prostu skompilować do wasma i yolo.

3

Najlepiej na backendzie, dopóki użytkownik nie doda nic nowego, to zawsze odsyłasz już raz obliczoną wersję zcachowaną, więc nawet do bazy danych nie musisz robić zapytania, a tak za każdym razem wszystkie dane wysyłasz na frontend i ponownie liczysz.

W ogóle czasem lepiej wszystkich danych nie wysyłać, kto wie czy jak ktoś nie pozna jak twoje api działa to jakoś tego nie wykorzysta, bo wszystko robisz na froncie.

Ja front bardziej traktuje jako widok, dostaje dane to generuje np. elementy i je tymi danymi uzupełnia, można robić jakieś obliczenia, ale jak masz do każdego użytkownika przesyłać plik tysiąca elementów i on ma to potem przetwarzać to dziwnie tak, lepiej jak mu odeślesz jeden element, do tego jest cache zrobiony bo ktoś raz użył to raz zostało to wyliczone i dopóki użytkownik nie doda nowego elementu to nie trzeba nic przeliczać tylko się zwraca wartość z cache.

2

@bbhzp: Rozumiem, że przykład przykładem, ale szukasz ogólnej odpowiedzi jak żyć. Masz jeszcze jeden pogląd na sytuację.

Masz ogólne architektury, które dostosowujesz do specyficznej potrzebny.
i w drugą stronę:
Masz konkretną architekturę, którą uogólniasz pod szersze zastosowania.

Gdzieś pomiędzy nimi masz różne pośrednie realizacje.

Ogólna <--- Realizacja A --- ... --- Realizacja X ---> Konkretna

Rozważ wymaganie do systemu "Powinno się dać zagrać melodię Dla Elizy".

Realizacje:

  • Pozytywka - gra zawsze "Dla Elizy" i nic więcej, ma 1 przycisk
  • Fortepian - masz dużo klawiszy, które odpowiednio naciskane spełniają wymaganie "Powinno się dać zagrać melodię Dla Elizy"
  • Keyboard - też dużo klawiszy, a dodatkowo pod niektórymi możesz podpiąć nagrane uprzednio melodie, w szczególności "Dla Elizy"

Która z realizacji jest lepsza? Nie da się odpowiedzieć bez uprzedniego zdefiniowania jakichś kryteriów (np. lepsze = tańsza? zajmuje mniej miejsca? prostota nade wszystko?).
Pewnie w głowie masz wizję tego co budujesz, której to wizji nie widzą inni i jesteś w stanie w locie powiedzieć, który wariant jest lepszy i pewnie wiesz, w którym kierunku będzie to rozwiązanie podążać. Podobnie miewają klienci. Wysokopoziomowe wymagania, wizja w głowie, a jak przychodzi do prezentacji funkcjonalności to jest "nie, to nie do końca o to chodziło".

W praktyce masz jakieś wymagania co do systemu, które trzeba zebrać, doprecyzować i zrozumieć, do tego ograniczenia budżetowe, czasowe i prawne. Na tej podstawie można wybierać architekturę, które będzie nadawała się do realizacji przy tych konkretnych ograniczeniach. Tworzy się modele (dzięki temu można zweryfikować, że coś jest zwalone już na etapie koncepcji) i prototypy (coś tam zaimplementowane, działa, ale czy o to chodzi? co można poprawić?).

Co do umieszczania logiki tu, czy tam. To zależy ;-) Oprócz tego, że masz front end i back end, to czasem logikę można umieścić w warstwie pośredniej, która dostaje wysokopoziomowe requesty i robi
orkiestrację wywołań Twojego komponentu backendowego. Jeśli sam sobie jesteś klientem i dostawcą i masz masę czasu, to spróbuj różnych podejść i obserwuj gdzie zaczną pojawiać się pierwsze problemy i jak Twoje wybory będą skutkować na rozwój aplikacji (np. chcę dodać dostęp także z aplikacji na telefon, albo via chat bot na whatzupie).

2
Riddle napisał(a):

Jasne, i kiedy tak się stanie, wtedy można dorobić odpowiednie struktury pod to. Ale z szacunkiem sugeruję żeby nie robić designu "bo może się okazać że". Pamiętajmy o YAGNI.

YAGNI nie oznacza, że masz zawsze programować zachłannie, po linii najmniejszego oporu. Raz przemyślane, sensowne API nada się zarówno do FE, jak i aplikacji mobilnej, czy desktopowej. Nawet jeżeli w momencie projektowania nie myślałeś o tym, że "pobierz listę dostępnych terminów", albo "dokonaj rezerwacji X o godzinie Y dla użytkownika Z" przyda się dla innego typu klienta, albo posłuży do integracji z jakimś zewnętrznym serwisem, to dostajesz tę elastyczność jako bonus.
Jeżeli dla odmiany zrobisz np. CRUD, to tę elastyczność tracisz, nie zyskując właściwie nic w zamian. Logika trafia do klienta i nie może zostać użyta ponownie w innych klientach. API BE staje się mocno związane ze sposobem przechowywania danych. Kontrola dostępu staje się bardziej skomplikowana itd.

1
piotrpo napisał(a):

Raz przemyślane, sensowne API nada się zarówno do FE, jak i aplikacji mobilnej, czy desktopowej. Nawet jeżeli w momencie projektowania nie myślałeś o tym, że "pobierz listę dostępnych terminów", albo "dokonaj rezerwacji X o godzinie Y dla użytkownika Z" przyda się dla innego typu klienta, albo posłuży do integracji z jakimś zewnętrznym serwisem, to dostajesz tę elastyczność jako bonus.

Dokładnie tak! Ale suchy tekst bez przykładu niewiele daje. Dlatego tu ci wkleję przykład niesamowicie prostego, ekstensywnego API które jest używane na milionach urządzeń i pomimo wielu lat wciąż się sprawdza bez względu na lokalizację czy zastosowanie.

https://en.wikipedia.org/wiki/Pipeline_(Unix)

0
loza_prowizoryczna napisał(a):

Dokładnie tak! Ale suchy tekst bez przykładu niewiele daje. Dlatego tu ci wkleję przykład niesamowicie prostego, ekstensywnego API które jest używane na milionach urządzeń i pomimo wielu lat wciąż się sprawdza bez względu na lokalizację czy zastosowanie.

https://en.wikipedia.org/wiki/Pipeline_(Unix)

Sugerujesz, że WEB API powinno się budować na tej samej zasadzie? Dla przykładu pojedynczy endpoint z pojedynczym argumentem typu String, bo jak wiadomo, to jest w stanie przekazać wszystko?

0
piotrpo napisał(a):

Sugerujesz, że WEB API powinno się budować na tej samej zasadzie? Dla przykładu pojedynczy endpoint z pojedynczym argumentem typu String, bo jak wiadomo, to jest w stanie przekazać wszystko?

Ty jakiś dinozaur jesteś, HTTP już dawno nie opiera się o plaintext. Jest binarny bo to naturalny język dla maszyn. Long polling, websockets - to jest przyszłość API które możemy nadbudować o pipeliny.

2
Riddle napisał(a):
piotrpo napisał(a):

@Riddle Nie o to chodzi. W wielu produkcyjnych aplikacjach funkcjonalność (więc i logika biznesowa) jest względnie stała w czasie. Natomiast w czasie całego cyklu życia systemu FE jest cyklicznie odświeżany, bywa, że pisany od początku, z powodów czysto estetycznych.

Tak, ale jeśli masz odpowiednią modularność na froncie, to możesz mieć jedną część która jest cycklicznie odświeżana, i jedną która jest względnie stała. Kein problem.

Tylko jeśli FE kręci się wokół jednego języka.

piotrpo napisał(a):

Zakładasz też, że FE będzie jedynym klientem backendu, a przecież nie musi tak być, bo mogą się jeszcze pokazać np. aplikacje mobilne, albo integracje z innymi systemami.

Jasne, i kiedy tak się stanie, wtedy można dorobić odpowiednie struktury pod to. Ale z szacunkiem sugeruję żeby nie robić designu "bo może się okazać że". Pamiętajmy o YAGNI.

Tylko, że pisanie logiki na froncie nic nie upraszcza. Tyle samo wysiłku będzie nas kosztowało napisanie jej na backendzie, a będą z tego same korzyści. YAGNI możesz stosować jak masz mało użytkowników i zamiast projektować rozproszoną bazę danych będziesz trzymał wszystko w pamięci, dopóki to nie będzie wystarczać.

0

Gdyby ktoś chciał się doszkolić, w szczególności jeśli chodzi o to czy warto podejmować decyzje na raz na początku, czy lepiej je odroczyć na później, to polecam zerknąć: Paving the Road to Effective Software Development

2
bbhzp napisał(a):

W aplikacji desktopowej stworzyłbym po prostu dodatkowe okno i, po naciśnięciu przycisku, na podstawie wcześniej pobranych danych jakimś algorytmem załatwił sprawę. Ale co z podejściem API + front end? Czy takie obliczenia powinny być wykonywane u klienta za pomocą JS, czy może powinienem stworzyć jakiś nowy endpoint, np. /AvailableDates?

Aplikację powinno tworzyć się tak, żeby w pełni działała nawet nie mając żadnego frontendu - bo frontend zazwyczaj jest całkowicie zbędny, a w 95% i tak nieudany.
Zamiast frontendu lepiej napisz testy.

0

@bbhzp - moja rada jest dosyć prosta. Wydaj te 400-600 pln na kurs "SOLID-ne API" od DevMentors. Oni tam poruszają problemy z którymi się aktualnie mierzysz w formie tworzenia aplikacji do obsługi miejsc parkingowych (rezerwacje). Mają przy tym bardzo fajną strukturę aplikacji na Backendzie.

Obejrzyj to bardzo dużo się nauczysz. Na tyle dużo, że nawet nie wiedział bym od czego Ci tutaj zacząć tłumaczenie co i jak.

P.S. Jak coś struktura aplikacji dostępna jest na githubie wiec każdy może sobie obejrzeć czy polecam coś wartościowego czy nie: https://github.com/devmentors/MySpot

0
somekind napisał(a):

Aplikację powinno tworzyć się tak, żeby w pełni działała nawet nie mając żadnego frontendu - bo frontend zazwyczaj jest całkowicie zbędny, a w 95% i tak nieudany.
Zamiast frontendu lepiej napisz testy

Aplikacja w epoce ML tworzy się sama, testy unitowe też. Pozostaje integracja ale tą wykonuje się na użytkownikach przy użyciu minimalnego UI.

2

Tak to powinno być:

  • warstwa dostepu do danych (czyli w .NET encje i dbcontext)
  • warstwa aplikacji / logiki biznesowej (w .NET robi się zwykle serwisy, np. ReservationService)
  • warstwa API (kontrolery), tutaj w prostych aplikacjach często pobierane są dane zarówno z warstwy aplikacji jak i warstwy dostępu do danych (nie tworzy się serwisów do wszystkiego), jeżeli chcemy aby kod był "bardziej SOLID" to wtedy dobrze jest mieć oddzielny DbContext który nie jest widoczny dla warstwy API, tylko dla serwisów
  • warstwa prezentacji (po stronie klienta)

Nie rozumiem nad czym taka dyskusja na 2 strony...

Logiki aplikacji jeżeli nie jest to konieczne to nie rób po stronie klienta. Może w przyszłości będzie z API korzystać jakaś aplikacja mobilna albo coś innego i będziesz musiał duplikować kod.

2
Kamil A napisał(a):
  • warstwa aplikacji / logiki biznesowej (w .NET robi się zwykle serwisy, np. ReservationService)

No nie wiem. Potem klasa na 4k linii.
Jak już to command/query handlery

0
szydlak napisał(a):
Kamil A napisał(a):
  • warstwa aplikacji / logiki biznesowej (w .NET robi się zwykle serwisy, np. ReservationService)

No nie wiem. Potem klasa na 4k linii.
Jak już to command/query handlery

Handlery to dodatkowy element, one też powinny korzystać z jakiejś warstwy aplikacji, a nie ją zastępować bo przecież nie chcemy mieć logiki rezerwacji rozwalonej w 20 plikach/klasach handlerów.

1

Nauka modularności, architektury i designu na aplikacjach webowych jest spisana na niepowodzenie. Aplikacje webowe często mają wiele elementów, baza danych, widok, http, logika biznesowa, autentykacja, pewnie z 10 jeszcze innych, wszystko z komplikacją frameworków i bibliotek; masa elementów. To jak nauka jazdy na nartach od razu na Mount Everescie.

Ktoś chcący nauczyć się dobrego projektowania aplikacji powinien zacząć od aplikacji która ma tylko dwa moduły - np. aplikacja desktopowa lub konsolowa która ma tylko widok i logikę, bez persystencji. To pozwoli nam w odpowiednim tempie uczyć się projektować oprogramowanie. Kiedy mamy to już obcykane (co samo w sobie nie jest łatwe), możemy dodać kolejny moduł i zobaczyć jak współgra on z naszymi dwoma istniejącymi - czy musi wiedzieć o każdym z nich, czy wystarczy żeby wiedział o jednym?

Uczyć się projektowania warto bez otoczenia frameworka - dlatego że to jest dodatkowa rzecz o której musimy myśleć i jakoś wcisnąć ją w nasz design - utrudniając całą rzecz.

Dopiero kiedy umiemy ogarniać wiele modułów na raz (co nie jest ławe), i umiemy odpowiednio dopasować framework do naszej aplikacji, tak żeby coupling nie był za duży, i reużycie było na odpowiednim poziomie; wtedy moim zdaniem jesteśmy gotowi na projektowanie aplikacji webowej: z widokiem, html/css, spa, bazą danych, http, autnetykacją, logiką, resilience, etc.

0
Riddle napisał(a):

Nauka modularności, architektury i designu na aplikacjach webowych jest spisana na niepowodzenie. Aplikacje webowe często mają wiele elementów, baza danych, widok, http, logika biznesowa, autentykacja, pewnie z 10 jeszcze innych, wszystko z komplikacją frameworków i bibliotek; masa elementów. To jak nauka jazdy na nartach od razu na Mount Everescie.

Żeby się brać za poważne aplikacje w całości trzeba mieć odklepane parę ładnych lat w różnych środowiskach/ekosystemach. Full stack nie jest dla juniorów. Trzeba poznać dobrze od środka kilka projektów żeby zrozumieć o co w tym wszystkim chodzi.

1
Kamil A napisał(a):

Tak to powinno być:

  • warstwa dostepu do danych (czyli w .NET encje i dbcontext)
  • warstwa aplikacji / logiki biznesowej (w .NET robi się zwykle serwisy, np. ReservationService)
  • warstwa API (kontrolery), tutaj w prostych aplikacjach często pobierane są dane zarówno z warstwy aplikacji jak i warstwy dostępu do danych (nie tworzy się serwisów do wszystkiego), jeżeli chcemy aby kod był "bardziej SOLID" to wtedy dobrze jest mieć oddzielny DbContext który nie jest widoczny dla warstwy API, tylko dla serwisów
  • warstwa prezentacji (po stronie klienta)

Nie rozumiem nad czym taka dyskusja na 2 strony...

Nad tym, żeby nie powielać takich błędnych pomysłów jak w punktach powyżej i jeszcze twierdzić, że tak powinno być.
Te "zwykle robione serwisy" będące łamiącymi SRP godobjectami na tysiące linii kodu albo DbContext używany jako jedyna forma dostępu do danych to główne źródła bólu w projektach.

0
Riddle napisał(a):

Ktoś chcący nauczyć się dobrego projektowania aplikacji powinien zacząć od aplikacji która ma tylko dwa moduły - np. aplikacja desktopowa lub konsolowa która ma tylko widok i logikę, bez persystencji. To pozwoli nam w odpowiednim tempie uczyć się projektować oprogramowanie. Kiedy mamy to już obcykane (co samo w sobie nie jest łatwe), możemy dodać kolejny moduł i zobaczyć jak współgra on z naszymi dwoma istniejącymi - czy musi wiedzieć o każdym z nich, czy wystarczy żeby wiedział o jednym?

Uczyć się projektowania warto bez otoczenia frameworka - dlatego że to jest dodatkowa rzecz o której musimy myśleć i jakoś wcisnąć ją w nasz design - utrudniając całą rzecz.

Dopiero kiedy umiemy ogarniać wiele modułów na raz (co nie jest ławe), i umiemy odpowiednio dopasować framework do naszej aplikacji, tak żeby coupling nie był za duży, i reużycie było na odpowiednim poziomie; wtedy moim zdaniem jesteśmy gotowi na projektowanie aplikacji webowej: z widokiem, html/css, spa, bazą danych, http, autnetykacją, logiką, resilience, etc.

To prawda, ale dla kontekstu tylko dodam, że mam już za sobą kilka dużych desktopowych projektów :)

Od mojego postu minął dopiero miesiąc, a ja już teraz uważam, że było to pytanie może nie głupie, ale bardzo początkujące :) Gdy je umieściłem, to nie obejrzałem jeszcze żadnego filmu, nie przeczytałem żadnego poradnika, tylko była to taka pierwsza myśl, która mi przyszła do głowy, gdy dowiedziałem się o SPA :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.