Mapowanie w DTO vs dedykowany mapper

Mapowanie w DTO vs dedykowany mapper
MY
  • Rejestracja:prawie 5 lat
  • Ostatnio:4 miesiące
  • Postów:24
0

Cześć,
mając prostą sytuację, w której jestem w stanie mapować DTO na jakiś obiekt domenowy często robię to bezpośrednio w nim dodając metodę:

Kopiuj
class CarRequest {
[...]
Car toCar() ...
}

Dzięki temu nie muszę nawet udostępniać getterów, bo ich nie potrzebuję.

Czasami jest tak, że do mapowania potrzebuję więcej informacji - np. jakiegoś propsa, albo wyliczenia jakiejś wartości. Mogę to robić przez przekazanie dodatkowych parametrów do funkcji getCar() albo wyniesienia mapowania do dedykowanego serwisu. Próbowałem znaleźć coś na ten temat od kogoś z większym doświadczeniem - kiedy stosować które podejście, czy warto być spójnym w projekcie, czy wynosić do mappera w jakimś konkretnym momencie. Kojarzycie? Albo możecie coś o tym powiedzieć?

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

To jakiś niezły fikołek :D Konwertowanie z obiektu domenowego na DTO w ten sposób sie spotyka, ale w drugą stronę to juz trochę ciężej. Ja bym zrobił jakś osobny serwis który zajmuje się taką konwersją.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MY
  • Rejestracja:prawie 5 lat
  • Ostatnio:4 miesiące
  • Postów:24
1
Shalom napisał(a):

To jakiś niezły fikołek :D Konwertowanie z obiektu domenowego na DTO w ten sposób sie spotyka, ale w drugą stronę to juz trochę ciężej.

Ale jak w drugą stronę? Że w obiekcie domenowym toResponse()? Wtedy mamy zależność domeny od infrastruktury, co raczej nie jest dobrym patternem

Shalom napisał(a):

Ja bym zrobił jakś osobny serwis który zajmuje się taką konwersją.

No jasne, pytanie czy zawsze warto - jeśli np. mapowanie to jest po prostu przepisanie pól

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Wtedy mamy zależność domeny od infrastruktury, co raczej nie jest dobrym patternem

? Masz tylko zależność od DTO bo przecież konkwertujesz sobie to na jakieś DTO. Nie widzę tu żadnej infrastruktury. Co więcej trudno mi sobie wyobrazić to co opisałeś bo u mnie DTO to są DTO i zwykle leżą w module razem z klientem tak zeby ktoś mógł łatwo tego serwisu uzywać. Dodanie tam zależności do domeny to jakiś hardkor. Ktoś kto chce używać serwisu potrzebuje znać endpointy + jak zmapować odpowiedź na jakieś DTO. W efekcie client nie powinien zawierać nic więcej zeby był lekki.

No jasne, pytanie czy zawsze warto - jeśli np. mapowanie to jest po prostu przepisanie pól

Jeśli tak jest to piszesz CRUDa i w ogóle nie masz obiektów domenowych tylko się okłamujesz i mapujesz DTO na inne DTO (anemic domain model)


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 4x, ostatnio: Shalom
MY
  • Rejestracja:prawie 5 lat
  • Ostatnio:4 miesiące
  • Postów:24
0

@Shalom:

? Masz tylko zależność od DTO bo przecież konkwertujesz sobie to na jakieś DTO. Nie widzę tu żadnej infrastruktury. Zresztą chcesz przecież zrobić identyczną zależność, dodając w twoim obiecie domenowym fromDTO ;)

Dobra dobra, spróbuję uściślić :) Albo najlepiej dać konkretny przykład:
Mam sobie endpoint, który przyjmuje zamówienie na samochód:

Kopiuj
class CarRestRequest(val color: String, val seats: Int)

Z drugiej strony zamówienia na samochody dostaję z jakiegoś pliku, który sobie wczytuję (nie mam tam ilości miejsc, więc przyjmuję jakąś wartość domyślną):

Kopiuj
class CarFileRequest(val color: String)

Chcę to sobie wrzucić do domeny jako CarRequest, żeby potem coś tam z tym działać. Czy w takim razie mówisz, ze powinienem zrobić dwa osobne serwisy zamieniające mi te obiekciki? Co jest nie tak w dodaniu do nich funkcji toCarRequest()?

Jestem początkujący, więc nie wykluczam, że błąd jest w ogóle dużo wyżej w moim projekcie/zrozumieniu, jestem otwarty na sugestie :)

EDIT: Widzę, że dorzuciłeś coś jeszcze. Spoko, widzę sens w rozdzieleniu tego jeśli np. chcemy używać tych obiektów w dwóch miejscach. Ale tutaj ewidentnie klient służy do jednej rzeczy, a pewnie w przyszłości się to nie zmieni. Chciałbym utrzymać architekturę jak najprostszą

edytowany 2x, ostatnio: mythflame
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:7 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
1
Shalom napisał(a):

Wtedy mamy zależność domeny od infrastruktury, co raczej nie jest dobrym patternem

? Masz tylko zależność od DTO bo przecież konkwertujesz sobie to na jakieś DTO. Nie widzę tu żadnej infrastruktury.

Może jestem w błędzie, ale byłem pewien że infrastruktura to właśnie między innymi DTO i klienty.
(W najprostszym podziale przecież mamy tylko domenę i infrastrukturę. Więc jak coś nie jest domeną to musi być infrastrukturą).
Nie mówię że lekki klient jest bez sensu. Jest sensowny zwłaszcza jak wydzielamy go jako osobną bibliotekę i wtedy wszystkie mikroserwisy korzystające z serwisu A mogą korzystać z tego klienta. A nie że wszędzie muszą rzeźbić od początku własnego klienta. W zasadzie pomysł OPa sprowadza nas do rzeźby własnych klientów :(

Dodanie tam zależności do domeny to jakiś hardkor. Ktoś kto chce używać serwisu potrzebuje znać endpointy + jak zmapować odpowiedź na jakieś DTO. W efekcie client nie powinien zawierać nic więcej zeby był lekki.

Dlaczego dodanie w infrastrukturze zależności do domeny to hardkor? Przecież w drugą stronę zależność jest zakazana a jakaś musi istnieć?


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 5x, ostatnio: KamilAdam
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1

@KamilAdam pisałem o sytuacji kiedy masz serwis i chcesz udostępnić do niego programowego klienta, tak zeby inny serwis mógł zrobić:

Kopiuj
MyClient client = new MyClient(host, port);
SomeDtoResponse response = client.invokeSomeAction(someDtoParameter);

I jednocześnie żeby nie trzeba było do tego wciagnąć całej domeny tego docelowego serwisu ;) Bo przecież ona cię w ogóle nie obchodzi. Obchodzi cię możliwość wykonania operacji + DTO.
Jak widać DTO są tu odrębnym elementem a nie częścia domeny ani infrastruktury, one co najwyżej mają zależność na te klasy.

Jednocześnie nie widzę nic zakazanego w tym żeby domain miało zależność do tych gołych DTO jeśli ktoś bardzo by chciał ją mieć.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 2x, ostatnio: Shalom
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)