Implementacja najlepszych praktyk .NET Full Webdev na przykładzie własnej aplikacji pisanej po godzinach

Odpowiedz Nowy wątek
2019-02-09 16:51
4

Mój pierwszy post więc w ramach przywitania się z community od razu podzielę się wiedzą i swoją pracą ;)

Na moim koncie gh:
[email protected]://github.com/piotr-mamenas/performance-app

Udostępniłem aplikacje nad którą pracuję po godzinach od dwóch lat, apka składającą się w sumie z 10 assembly, w tym backendowego Serwisu RESTowego w Web Api 2 oraz aplikacji Postback (wspomaganej akcjami SPA w Ajax) napisanej w MVC 5. Służyła mi ona do pogłębiania wiedzy odnośnie architektury aplikacji. Generalnie jest to ekstrakt najlepszych praktyk sugerowanych przez guru .NET developmentu takich jak: Dino Esposito, Martin Fowler, Robert C. Martin czy Gary McLean Hall i wiele wielu innych których chętnie i fanatycznie czytam :)

Co zatem znajdziecie w środku?

  1. Najlepsze praktyki z zakresu Domain Driven Development z wykorzystanie jednego Bounded Context zawierającego kilkanaście agregatów Encji z pojedyńczym Entity Root per Agregat, odpowiadającym za tranzakcyność. Ponadto podział na Base Entities, Relationship Entities oraz ValueObjects. Nie-anemiczny model domeny (Encje domenowe zawierają logikę biznesową),
  2. Podział na tzn Domain Layer, Infrastructure Layer, Service Layer i Presentation Layer wraz z zastosowaniem reguł SOA
  3. Zastosowane najlepsze praktyki z zakresu SOLID. Patternów Go4 (np Facade, Singleton, Builder, Decorator, Strategy), DRY, KISS oraz innych.
  4. Na frontendzie kod Javascriptowy jest podzielony na oddzielne komponenty izolowane Revealing Module Pattern opartej na Closures. Jeśli chodzi o strukturę strony to głównie jest to Bootstrap 3 z mieszanką flexa.
  5. Dependency Injection z wykorzystaniem kontenera Ninject w celu wtrzykiwania Repozytoriów i Serwisów bezpośrednio do Konstruktorów Kontrolerów.
  6. Implementacja tranzakcyjności operacji poprzez patterny Unit of Work i Generic Repository z użyciem Entity Framework 6 podpiętej pod bazę relacyjną. Z podziałem na zewnętrzne konfiguracje oraz przeładowaniami konfiguracji dla Base Entities.
  7. Najlepszymi praktykami w serializacji danych z użyciem DTO, View Modeli oraz mapowania obiektów AutoMapperem.
  8. Authentykacje i Autoryzacje opartą na Identity Framework 2 oraz ciasteczkach.

Jeśli ktoś się uczy lub chciałby po prostu poszerzyć swoją wiedzę z zakresu dobrych praktyk to jest to miejsce w którym można podpatrzeć rozwiązania implementacyjne i mam nadzieję nauczyć się czegoś nowego ;)

Domain Driven Design ;) - Aventus 2019-02-09 18:11

Pozostało 580 znaków

2019-02-10 23:25
1

@roch.mamenas: pobieżnie przeglądałem sobie Twój kod bo nie mam czasu żeby bardziej nad tym przysiąść. Odnośnie warstwy prezentacji, a konkretnie organizacji kodu to proponuję poczytać o feature folders/slices. Nie każdemu to musi odpowiadać, ale moim zdaniem (i wielu innych) jest to lepszy sposób organizowania kodu UI.

Ponadto warto pomyśleć o przepisaniu tego na ASP Core.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Pokaż pozostałe 10 komentarzy
@Hosap: Właśnie w ViewEngine da się definiować te pathe, ale jakoś tak opornie szło aby zaciągać je z innego csproja - Kontrolery i View to osobne csproje, ale wtedy return View przestaje działać. - WeiXiao 2019-02-11 18:13
@WeiXiao: Wiele powodów, większość aplikacji jest mocno zcouple-owana z layout frameworkami typu bootstrap, flex czy inne a sam razor nie zapewnia backwards compatibility więc reusability prawie nie istnieje (zajrzyj do obu web.configów i spójrz na wpisy, nie użyjesz tego z inną aplikacją w większości). Widoki z implementacjami wewnątrz kontrolów są też same mocno złączone chodźby przez viewbagi. Do tego sam framework też tego nie ułatwia, masz chociażby podział na areas więc aplikacja która chciałaby re-usować widoki musiałaby mieć identyczną strukturę (bez sensu nie?) - roch.mamenas 2019-02-11 19:52
@WeiXiao: odnośnie drugiego pytania to mam projekt drugi poboczny (prywatne repo na gh), microserwisy w core z apką angularową na froncie którą chciałbym w przyszłości skomercjalizować. Nie mam po prostu czasu tego przepisywać, są inne rzeczy. Commitować do tej apki na boku będę niezależnie bo kilka punktów jest jeszcze do poprawek na liście ;) - roch.mamenas 2019-02-11 19:56
Moim zadaniem powinieneś w innym csproju a najlepiej w paczce nugetowej trzymać view componenty i używać ich w view csproja z kontrolerami. Jeśli chcesz mieć całe View w innym cproju to teoretycznie jakakolwiek integracja ASP z zewnętrznym kontenerem IOC powinna nadpisywać ViewEngin wiec teoretycznie powinno to działać jak zarejestrujesz views (assemby cproj'a) i cotrolers w kontenerze, ale pewności nie mam, nigdy nie próbowałem tego rozdzielać. - Hosap 2019-02-12 01:59
sam razor nie zapewnia backwards compatibility więc reusability prawie nie istnieje Niby z czym te "backwards compatibility" z Algularem? Bezsensu, niby dlaczego reusability nie istnieje?. - Hosap 2019-02-12 06:59

Pozostało 580 znaków

2019-02-12 09:24
1

odpuść, dlatego nikt mu nie odpisuje. To takie ostatnie wycie trolla, wszyscy ignorują to co pisze to zaczyna wyzywać ludzi aby tylko dostać jakąkolwiek negatywną reakcje. Gość nawet nie ma pojęcia o czym piszę co już kilka osób mu w tym poście wytknęło.

Co wytknęło i gdzie.? To ty nie masz pojęcie, o czym mówisz te twoje "dobre praktyki" mają tyle wspólnego z dobrymi praktykami co historia papiestwa ze świętością.

Proszę, naruszenie tak podstawowych zasad, jak Open Close.

Od kiedy to UintOfWork jest fasadą na "repozytoria"?

https://github.com/piotr-mame[...]/Infrastructure/UnitOfWork.cs

W domenie wystawiłeś schemat bazy danych i udajesz, że to model domeny. Pfff....

Bardzo byś chciał, żebym kogoś wyzywał, bo wtedy można by mnie wytknąć palcem i zamieść pod stół, póki co to wy mnie wyzywacie razem z Aventusem od Trola, trzeba być nie powiem kim, żeby tego nie zauważyć. Szukanie kolegów w ten sposób jest żałosne, nie rób tak.

Edit:
W ogóle to po co ci tam te interfejsy od repozytoriów ?
Jak się nazywa taka odmiana Unit of work? "Unit of work manager"?
Tak ja wiem zaraz odpiszesz, bo tak pisało w książce Freemana albo to jest dobra praktyka, bo jakiś hindus na YouTube tak mówi.
Żałosne...

edytowany 2x, ostatnio: Hosap, 2019-02-12 09:32

Pozostało 580 znaków

2019-02-12 17:47
12
roch.mamenas napisał(a):

Generalnie jest to ekstrakt najlepszych praktyk sugerowanych przez guru .NET developmentu takich jak: Dino Esposito, Martin Fowler, Robert C. Martin czy Gary McLean Hall i wiele wielu innych których chętnie i fanatycznie czytam :)

Ten kod to zbiór najpopularniejszych antywzorców, kultów cargo, niekiedy doprawione zwykłym spaghetti:

  1. DAO nazwane dla niepoznaki repozytorium.
  2. "Repozytoria" wstrzykiwane bezpośrednio do kontrolerów.
  3. Podobnie jak i Unit of Work.
  4. Jedno "repozytorium" per tabela: https://github.com/piotr-mame[...]ructure/Repositories/Business
  5. Logika biznesowa w kontrolerach. https://github.com/piotr-mame[...]ers/AccountController.cs#L111
  6. Eksponowanie detali ORMa (czyli IQueryable) z "repozytorium": https://github.com/piotr-mame[...]ness/PartnerRepository.cs#L17
  7. No i nieśmiertelne, nikomu niepotrzebne GetAll: https://github.com/piotr-mame[...]epositories/Repository.cs#L23
  8. Style CSS w domenie: https://github.com/piotr-mame[...]ileWidgets/FontAwesomeIcon.cs Ktoś tu pisał coś o SOA?
  9. Infrastruktura w domenie (uwierzytelnianie): https://github.com/piotr-mame[...]e/master/Core/Domain/Identity
  10. Infrastruktura w domenie (jakieś joby jak sądzę): https://github.com/piotr-mame[...]re/Domain/Tasks/ServerTask.cs
  11. Używanie klas infrastrukturalnych w domenie, zamiast tworzenia typów opisujących domenowe przeznaczenie: https://github.com/piotr-mame[...]/Services/AssetService.cs#L25
  12. Walidacja zwracająca stringi: https://github.com/piotr-mame[...]omain/Partners/Partner.cs#L46
  13. UoW będący wrapperem na repozytoria. Ktoś coś pisał o SOLID?
  14. Anemic domain model - mutowalne "encje" będące odwzorowaniem struktury bazy. Wstawienie czasem publicznej metody, nie zamienia ADM w DDD.

I tylko tego nie umiem nazwać: https://github.com/piotr-mame[...]lers/ContactController.cs#L27 - jakieś podejrzane rzutowanie parametru konstruktora, bo pole jest innego typu. WTF?

roch.mamenas napisał(a):
  1. Jeśli chodzi o repozytoria to jest to często źle rozumiany koncept, repozytorium jest implementacją idei Inversion of Control w SOLID a zatem:
    "High-level modules should not depend on low-level modules. Both should depend on abstractions."

Repozytoria zostały zdefiniowane przez Fowlera (definicję podlinkował @Aventus) oraz Evansa:

For each type of object that needs global access, create an object that can provide the illusion of an in-memory collection of all objects of that type. Set up access through a well-known global interface. Provide methods to add and remove objects, which will encapsulate the actual insertion or removal of data in the data store. Provide methods that select objects based on some criteria and return fully instantiated objects or collections of objects whose attribute values meet the criteria, thereby encapsulating the actual storage and query technology. Provide REPOSITORIES only for AGGREGATE roots that actually need direct access. Keep the client focused on the model, delegating all object storage and access to the REPOSITORIES

Nie ma potrzeby silenia się na własne definicje.

Taką formą abstrakcji od Entity Framework będącego "High-level module" jest repozytorium. Dzięki użyciu repozytorium jesteśmy w stanie odizolować wykorzystanie metod ORM'a od faktycznej logiki biznesowej

Mylisz repozytorium z DAO.

i nawet wymienić ORM'a jak zmienią się wymagania

Ale Ty tego nie zrobisz - bo wystawiasz z "repozytoriów" IQueryable.

Sprawa jest prosta - mamy DDD, mamy encje, mamy aggregate rooty i kolekcje operujące na tychże AR to są repozytoria. Jak nie mamy DDD, to nie mamy repozytoriów tylko DAO.

Druga sprawa to czysty porządek. W tej architekturze repozytoria odpowiadają za enkapsulacje logiki chwytającej dane

No nie bardzo: https://github.com/piotr-mame[...]ers/PartnerController.cs#L135

serwisy za wykonywanie logiki biznesowej

Jedną metodę na cały ten projekt.

aniżeli setki opatrzonych grubymi komentarzami kwerend linqowych

Tak, bo nie da się zrobić porządnie, trzeba mieć albo "repozytoria" wstrzyknięte w kontrolery, albo grube kontrolery na kontekście EF.

W tym kontekście, dobrze się czyta tych panów:
https://programmingwithmosh.com/tag/repository-pattern/
https://lostechies.com/jimmyb[...]ices-in-domain-driven-design/

I gdzie tam jest napisane, żeby wstrzykiwać repozytoria i UoW do kontrolerów?

developer przy użyciu contextu może sobie dowolnie zapisywać zmiany kilkukrotnie w jednym requescie.

Przy użyciu UoW też może.

Repozytorium umożliwia wdrożenie UoW.

Niczego nie umożliwia, UoW można mieć zupełnie niezależnie od repozytorium, nawet na gołym kontekście EF. Co więcej, nie da się nawet używać EF bez UoW.

Nie jest również prawdą że EF nie obsługuje ignorancji persystencji:
Lista providerów EF6: https://docs.microsoft.com/en-us/ef/ef6/fundamentals/providers/

Bosz... "Persistence ignorance" nie oznacza dowolności wyboru bazy danych, tylko uzależnienie kodu "encji" od technologii ORMa.

Pozostałe rzeczy które powiedziałeś nie mają najmniejszego sensu. Mylisz też pojęcia, Monolith często nazywany lazanią jest typem architektury, tak jak typem architektury są mikroserwisy

Można mieć lazanię zarówno w monolicie jak i mikroserwisach, to są ortogonalne pojęcia.

Aventus napisał(a):

@Klojtex: zaznaczam że nie pisałem o generycznym repo tak jak w tym przypadku. Masz jak najbardziej rację. Jedno tylko sprostowanie- z dzisiejszymi frameworkami rzadko kiedy istnieje potrzeba oddzielenia encji z baz danych od modeli domenowych.
W większości przypadków to właśnie model domenowy będzie zapisywany jako encje. Zazwyczaj nie ma potrzeby na klasy pośrednie (encje) ponieważ modele domenowe mogą być używane przez ORM przy zachowaniu ignorancji perzystencji.

To nie jest kwestia frameworka. To się nazywa Single Responsibility Principle. Jeśli klasa zawiera jednocześnie logikę i opisuje model składowania, to ma dwie odpowiedzialności, więc SRP łamie. A jeśli system zawiera jakąś faktyczną logikę biznesową, a nie tylko CRUD na sterydach, to encje domenowe znacząco się różnią od tego, co trzeba przechowywać, więc tym bardziej trzymanie jednego zestawu klas do dwóch celów nie ma sensu. Do tego encje DDD powinny się opierać o enkapsulację. Jaką masz enkapsulację z publicznymi setterami wymaganymi przez EF?

Niestety, większość ludzi wciąż myśli tabelkami i procedurami, zmapują sobie ADM przy użyciu ORMa ukrytego pod "repozytoriami" i twierdzą, że mają DDD, a to tak naprawdę skrypt transakcji rozbity na biedawarstwy (za to modnie nazwane!).

A jak bardzo EF nie jest PI opisuje chociażby ten wpis: https://enterprisecraftsmansh[...]nhibernate-4-ddd-perspective/


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."
Szacun, że ci się chciało. - KreonPoKawie 2019-02-13 04:33
Serio ktoś wymienia ORM'y? - Desu 2019-02-13 12:07

Pozostało 580 znaków

2019-02-12 18:10
0

Jaką masz enkapsulację z publicznymi setterami wymaganymi przez EF?

Nie wiem, ja tam używam EF Core z wartościami przekazywanymi przez konstruktor i prywatnymi properties. Mało tego, możesz nawet używać read only properties. Nie chcę nic mówić ale na dzień dzisiejszy to NHibernate bardziej łamie PI... I tak naprawdę nie ma nic złego w takim drobnym łamaniu PI (np. wymagany virtual w NH. Chociaż to brzydko wygląda).

Liczba rzeczy jakie musisz zmieniać w POCO aby było kompatybilne z EF Core: 0. Naprawdę. Wszystko można skonfigurować przez konwencję EF.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Pokaż pozostałe 6 komentarzy
Jakiś czas temu robiłem zadanie rekrutacyjne, od jednego usera z tego forum (miały być testy), no i czytając co nie co o DDD wcześniej stwierdziłem, że zrobię prywatne setery i potem miałem problem z napisaniem testów. https://github.com/szydlaczek/CarRental - szydlak 2019-02-12 21:09
@szydlak: Przegladnalem Twoj kod ale nie wiem gdzie konkretnie jest Twoj problem. Masz zmockowany context (nie jestem zwolennikiem takiego mockowania ogolnie, ani testowania kontrolerow jak zwyklych klas, no ale to moja opinia) i sprawdzasz czy zostala przywolana metoda SaveChangesAsync(). Po co wiec chcesz wyciagac utworzony rekord po ID? Tak czy inaczej, nadal moglbys wlasnie uzyc konstruktory. - Aventus 2019-02-12 22:15
@Aventus: Nie podobało mi się to, że musiałem używać Id=0 (CarTypeId) w testach :P, już dawno robiłem ten projekt i mi się zapomniało jakie miałem wątpliwości dokładnie. Ale teraz widzę, że chyba trochę spierniczyłem tu tworzenie CarReservation. Ten CarTypeId w konstruktorze nie był potrzebny raczej. - szydlak 2019-02-12 22:37
Rozumiem. Nie chcę być czepialski bo nie tego dotyczy rozmowa, ale te "zatruwanie" klas domenowych atrybutami perzystencji kłuje po oczach. Lepiej używać fluent API. Klasy domenowe nie powinny nic wiedzieć o perzystencji. - Aventus 2019-02-12 22:45
@Aventus: Spoko, wiem. Jak wspominałem już dawno to robiłem i ostatnie projekty wzoruje na tym: https://github.com/JasonGT/NorthwindTraders - szydlak 2019-02-12 22:50

Pozostało 580 znaków

2019-02-12 20:13
3
somekind napisał(a):

Jak nie mamy DDD, to nie mamy repozytoriów tylko DAO.

Biorąc pod uwagę że repozytoria oficjalnie narodziły się w książce Fowlera wydanej w 2002 roku, natomiast DDD oficjalnie narodziło się w książce Evans wydanej w 2003 roku, rodzi się zasadnicze pytanie :D, Skąd Fowler miał repozytoria skoro repozytoria nie mogą istnieć bez DDD które powstało później :D?

Odpowiedź że Fowlera jest ziomkiem Evans i miał wcześniejszy dostęp do rękopisu się nie liczy :P.

Widzę tylko dwie możliwości:

  • albo podróże w czasie istnieją
  • albo repozytoria poza DDD istnieją
Problem polega na tym że somekind kategorycznie sprzeciwia się użyciu słowa repozytorium w odniesieniu do czegokolwiek innego niż do repo w sensie DDD. Kiedyś podsunąłem mu definicje tego tego słowa, ale nie poskutkowało. Albo masz DDD i repozytoria, albo nie waż się używać tego słowa... - Aventus 2019-02-12 20:18
Bo miał racje, ty po prostu nie potrafisz tego zrozumieć. - KreonPoKawie 2019-02-13 03:19
Używanie repozytoriów bez modelowania Domain Model'u według DDD. Jest jak Holiday w Tajlandii bez prezerwatyw. - KreonPoKawie 2019-02-13 03:47

Pozostało 580 znaków

2019-02-13 03:18
0
neves napisał(a):
somekind napisał(a):

Jak nie mamy DDD, to nie mamy repozytoriów tylko DAO.

Biorąc pod uwagę że repozytoria oficjalnie narodziły się w książce Fowlera wydanej w 2002 roku, natomiast DDD oficjalnie narodziło się w książce Evans wydanej w 2003 roku, rodzi się zasadnicze pytanie :D, Skąd Fowler miał repozytoria skoro repozytoria nie mogą istnieć bez DDD które powstało później :D?

Odpowiedź że Fowlera jest ziomkiem Evans i miał wcześniejszy dostęp do rękopisu się nie liczy :P.

Widzę tylko dwie możliwości:

  • albo podróże w czasie istnieją
  • albo repozytoria poza DDD istnieją

@somekind Ma rację:

Równie dobrze możesz zapytać dlaczego w książce Fowlera są opisane Value Objecty, IdnetityField oraz Domain Model, Sokoro są również w książce o DDD.

DDD, nie wymyśla, żadnych nowych wzorców DDD uczy jak je poprawnie używać. Jak modelować dziedzinę.

Nie wiem, ja tam używam EF Core z wartościami przekazywanymi przez konstruktor i prywatnymi properties. Mało tego, możesz nawet używać read only properties. Nie chcę nic mówić ale na dzień dzisiejszy to NHibernate bardziej łamie PI... I tak naprawdę nie ma nic złego w takim drobnym łamaniu PI (np. wymagany virtual w NH. Chociaż to brzydko wygląda).

Liczba rzeczy jakie musisz zmieniać w POCO aby było kompatybilne z EF Core: 0. Naprawdę. Wszystko można skonfigurować przez konwencję EF.

Zawsze bardziej czytelne i ergonomiczne będzie używanie dwóch modeli. Poza tym 80% ludzi nie rozumie, że id w bazie to nie jest tożsamość encji i wystawianie togo w modelu dziedziny jako encji lub agregatu tylko dlatego, że "ORM tak chce" nie sensu.

edytowany 1x, ostatnio: KreonPoKawie, 2019-02-13 03:24

Pozostało 580 znaków

2019-02-13 05:16
0

Pozwólcie, że odpowiem poście na komentarze:

A tak z ciekawości. Jak trzeba zrobić test jednostkowy np z użyciem EF Core . Np dodanie czegoś do bazy a następnie wyszukanie po ID. Id w teście nie przypiszesz sam bo masz set jako private. Kiedyś pisałem na forum wątek ale nikt mi nie odpowiedział jak się za to zabrać. W EF Core w sumie problem rozwiązuje InMemory (bo sam wygeneruje ID) ale w EF 6 jak musisz podpiąc pod DBSeta jakąś fejkową listę to ona nie nada żadnego ID po zrobieniu SaveChanges.

To nie są żadne testy jednostkowe tylko funkcyjne, ewentualnie akceptacyjne i używa się do nich innego frameworka.

Spoko, wiem. Jak wspominałem już dawno to robiłem i ostatnie projekty wzoruje na tym: https://github.com/JasonGT/NorthwindTraders

Jak ktoś tworzy paczki i zależności pomiędzy nimi w ten sposób Domain.Infrastructure.
To znaczy, że nie ma pojęcie czym jest Port Adapter i jakakolwiek inna pokrewna architektura która się z niej wywodzi.

https://github.com/JasonGT/No[...]/tree/master/Northwind.Domain

Sama "Domena" to dalej ORM Development.

https://github.com/JasonGT/No[...]ter/Northwind.Domain/Entities

Po przeczytaniu tych wszystkich postów można stwierdzić, ze racja jest jak dupa, każdy ma swoją - szydlak 2019-02-13 08:11

Pozostało 580 znaków

2019-02-13 06:26
0
KreonPoKawie napisał(a):

Zawsze bardziej czytelne i ergonomiczne będzie używanie dwóch modeli. Poza tym 80% ludzi nie rozumie, że id w bazie to nie jest tożsamość encji i wystawianie togo w modelu dziedziny jako encji lub agregatu tylko dlatego, że "ORM tak chce" nie sensu.

Czemu nie ma sensu :)? Evans w niebieskiej książce nie ma nic przeciwko jeśli id zostanie wygenerowane przez źródło danych:

This means of identification may come
from the outside, or it may be an arbitrary identifier created by and
for the system, but it must correspond to the identity distinctions in
the model.

Pokaż pozostałe 27 komentarzy
Ile płacisz temu psychologowi może za mało...? - KreonPoKawie 2019-02-13 10:29
I jak widzę dalej niczego się nie nauczyłeś. - KreonPoKawie 2019-02-13 10:29
Czyli jednak rozmawiam ze ścianą :D ok, żeby nie było- spróbowałem. Miłych dalszych konfliktów i banów. - Aventus 2019-02-13 10:30
Czyli jednak rozmawiam ze ścianą Co ty nie powiesz, odnoszę to samo wrażenie. - KreonPoKawie 2019-02-13 10:33
Super, jak dobrze, że dałeś popis tego, jak wygląda dyskusja z tobą. - KreonPoKawie 2019-02-13 10:34

Pozostało 580 znaków

2019-02-13 06:46
0

Czemu nie ma sensu :)? Evans w niebieskiej książce nie ma nic przeciwko jeśli id zostanie wygenerowane przez źródło danych:

Id może również być wygenerowany w serwisie i podany w fabryce etc. Nie o to mi chodzi, chodzi mi o to, że brak rozdzielenia dwóch modeli sprzyja tworzeniu różnych dziwnych "tworów", które są zależne od mechaniki ORM'a między innymi również myleniu Value Objectu z Entity.

Ludzie zwykle myślą w ten sposób, Hmm Client, Hmm... PruductOwner Hmm... Identyfikator, bo muszę to jakoś zapisać, w bazie danych więc jest to encja. Właśnie, że w większości przypadków jest to wartość.

Poza tym trochę odbiegając od głównego tematu, mapowanie każdej wartości na relacje w bazie tylko dlatego, że ORM tak chce, jest przypadkową złożonością, a nawet niepożądaną a używanie jednego modelu właśnie temu sprzyja.

Edit:

A "Identity Field" to też jest encja tylko dlatego że ma Id? Ja zawsze myślałem że to wartość.

Edit2:

Tutaj masz przykład z Czerwonej książki: https://github.com/VaughnVern[...]on/Domain.Model/Collaborators

edytowany 2x, ostatnio: KreonPoKawie, 2019-02-13 07:56

Pozostało 580 znaków

2019-02-13 08:44
3

@roch.mamenas: Próbowałem znaleźć chociaż jeden kawałek logiki w domenie i jakiś test do tego. Nie znalazłem, ale C# . NET to nie moja działka. Może źle szukam? Możesz wskazać jakieś testy, najlepiej do jakiegoś nietrywialnego kawałka logiki?


Bardzo lubie Singletony, dlatego robię po kilka instancji każdego.
edytowany 1x, ostatnio: jarekr000000, 2019-02-13 08:44
Najbardziej rozbudowane są agregaty Portfolio i Asset - roch.mamenas 2019-02-13 11:50
A te testy są gdzie? - jarekr000000 2019-02-13 13:50

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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