Dobry kod w asp.net mvc

0

Czołem koledzy programiści. Z tej strony Karol. Postanowiłem się przebranżowić i chciałbym pisać dobry kod. Skąd czerpać wiedzę, która pozwoli tworzyć kod, który byłby akceptowalny w zawodowej pracy programisty? Nieco już znam, potrafię sklecić stronkę, która jakoś działa i jakoś wygląda, lecz mam wrażenie, zapewne słuszne, że mój kod jest słaby. Staram się trzymać pewnych standardów, nie piszę niestosownego kodu w kontrolerach, operuję na ORM w serwisach, nie pcham encji na twarz, korzystam z automappera, autofaca i tak dalej.

Zapewne pomocnym byłoby móc spojrzeć na porządnie napisany projekt w wymienionej technologii, lecz niestety ze świecą takich szukać na githubie. Większość to logika w kontrolerach lub niedokończone projekty. Byłbym wdzięczny za jakiekolwiek wskazówki.

Pozdrawiam,
KK

3

Spróbuj może ten oficjalny materiał od Microsoftu razem z darmową książką Architecting Modern Web Applications with ASP.NET Core and Azure. Oczywiście to czym jest "dobry" kod to kwestia dyskusyjna ale myślę że to dobry punkt startowy.

https://github.com/dotnet-architecture/eShopOnWeb

1

oglądam sobie z ciekawości projekcik, sam się nadal uczę w swoim tempie ;)
ale mam pewne pytanie:
tam jest (jak i w wielu różnych tutorialach) odnoszenie się do repozytorium już na poziomie controllerów (przez wstrzykiwanie z kontenera IOC potem idzie bodajże do serwisu


   public OrderController(IOrderRepository orderRepository)
        {
            _orderRepository = orderRepository;
        }

czy to jest dobre podejście?
mnie kiedyś uczono przy projekcie web api (rest), że controller, czyli w pewnym zasadzie już coś bardzo blisko clienta nie ma prawa w ogole wiedzieć o istnieniu repozytorium

dla mnie zawsze dobrą praktyką było trzymanie warstwy DAO zaraz przy warstwie klas domenowych (tych wykorzystywanych w DBSet<T>).
dopiero serwis pukał do DAO o dostęp do danych - serwis też nie znał konkretnej bazy danych
z kolei do serwisów pukał controller - ten zaś znał jedynie interfejsy serwisów
zawsze to robiłem w ten sposób, że w warstwie serwisów tworzyłem serwisy (internal) - do tego publiczne interfejsy,
tam jakąs klasę mającą dostęp do kontenera IOC (czy to jest fasada?) -
przy pierwszym wywołaniu rejestrował wszystkie serwisy wraz z interfejsami, a przy zapytaniu o okreslony interfejs (np. IUsersService) zwracał UsersService
więc controller nawet nie wiedział o kontenerze IOC - był bardzo trywialny, gotowy jedynie na odebranie danych od klienta i w jakiś sposób przerzucenie ich do logiki biznesowej za pomocą interfejsu - controller wiedział tylko CO może zrobić serwis danego interfejsu (nie wiedział jak)

czy moje podejście to jakieś poplątanie ?
jak wy kodzicie?

Już pal licho czy mamy tą warstwę DAO. według wielu jest to nadmiarowe, przecież sam ORM jest w pewnym sensie tym DAO, a my to jeszcze bardziej opakowujemy,
chociaż gdyby przyszło nam zmieniać naglę bazę przykładowo z msSQL na oracle (wiem że to bardzo mało realne) to wtedy wystarczy przeorać warstwę DAO, a w samej warstwie logiki biznesowej będą juz niewielkie (o ile w ogóle) zmiany.
Ale koniec końców nawet bez dodatkowej abstrakcji w postaci warstwy DAO, to czy odwołania się do repozytorium są dopuszczalne w warstwie controllera ?
Może tak to się robi w tym czystym MVC (nie w WEB API)?

ja w ten sposób trzaskam nawet malutkie trywialne projekciki w ramach nauki,
pytam też bo za 2-3 miesiące chyba biorę się za naukę ASP.NET MVC Core
jeśli robię to źle to chciałbym się ocknąć ;)

0

Tak jak większość nie rozumiesz. Doman model to nie jest to samo co obiekt, który wysyłasz do wyświetlenia w widoku.

Samo używanie ORM'a pokroju (EF) do tworzenia tego obiektu jest dla mnie bez sensu zwłaszcza w Webie, bo niby po co ci tam lezy loading czy sesja na styl UOW.? ORM jest ci potrzebny, aby operować na DM a samo repozytorium to tylko opakowanie, które separuje ORM od Domeny.

0

no ale gdzie ja piszę że domain model gdzieś wyświetlam...?

1

A no nie pisałeś, ale pytałeś się, czy wstrzykiwanie repo do kontrolera to dobra praktyka. Nie chodzi o samo wysyłanie tylko to do czego je używasz. Jeśli pobierasz je tylko po to, żeby je przemapować w kontrolerze na ViewModele to trochę bez sensu.

Dlaczego nie można zrobić tak jak tutaj.?
https://github.com/VaughnVernon/IDDD_Samples_NET/blob/master/iddd_collaboration/Application/Forums/ForumQueryService.cs
https://github.com/VaughnVernon/IDDD_Samples_NET/blob/master/iddd_collaboration/Application/Forums/ForumApplicationService.cs

Czyli wydajnie i prosto.

1
heyyou napisał(a):

czy to jest dobre podejście?

Nie. Jest po prostu najbardziej popularne, bo wszyscy kopiują te same, idiotyczne tutoriale.

mnie kiedyś uczono przy projekcie web api (rest), że controller, czyli w pewnym zasadzie już coś bardzo blisko clienta nie ma prawa w ogole wiedzieć o istnieniu repozytorium

Tak.

dla mnie zawsze dobrą praktyką było trzymanie warstwy DAO zaraz przy warstwie klas domenowych (tych wykorzystywanych w DBSet<T>).

To nie są klasy domenowe tylko persistence modele.

dopiero serwis pukał do DAO o dostęp do danych - serwis też nie znał konkretnej bazy danych

Tak.

z kolei do serwisów pukał controller - ten zaś znał jedynie interfejsy serwisów
zawsze to robiłem w ten sposób, że w warstwie serwisów tworzyłem serwisy (internal) - do tego publiczne interfejsy,

A po co właściwie serwisom interfejsy?

tam jakąs klasę mającą dostęp do kontenera IOC (czy to jest fasada?) -
przy pierwszym wywołaniu rejestrował wszystkie serwisy wraz z interfejsami, a przy zapytaniu o okreslony interfejs (np. IUsersService) zwracał UsersService

Owrapowałeś kontener IoC? Czyli zrobiłeś jakiś service locator?

więc controller nawet nie wiedział o kontenerze IOC

Ale do tego nie trzeba jakichś karkołomnych konstrukcji. Każdy sensowny kontener IoC udostępnia biblioteczkę pozwalającą na integrację z webapi. A jeśli nie, to wystarczy napisać własne controllerfactory.

controller wiedział tylko CO może zrobić serwis danego interfejsu (nie wiedział jak)

Interfejs niczego w tej kwestii nie zmienia, kontroler i tak nie wie, co się dzieje w metodach innych klas.

Już pal licho czy mamy tą warstwę DAO. według wielu jest to nadmiarowe, przecież sam ORM jest w pewnym sensie tym DAO, a my to jeszcze bardziej opakowujemy,
chociaż gdyby przyszło nam zmieniać naglę bazę przykładowo z msSQL na oracle (wiem że to bardzo mało realne) to wtedy wystarczy przeorać warstwę DAO

A mając tylko ORM wystarczy zmienić connection string.

Ale koniec końców nawet bez dodatkowej abstrakcji w postaci warstwy DAO, to czy odwołania się do repozytorium są dopuszczalne w warstwie controllera ?
Może tak to się robi w tym czystym MVC (nie w WEB API)?

Tak się robi, bo programowaniem zajmuje się masa dyletantów, która umie jedynie kopiować kod z indiańskich tutoriali.

0
somekind napisał(a):

controller wiedział tylko CO może zrobić serwis danego interfejsu (nie wiedział jak)

Interfejs niczego w tej kwestii nie zmienia, kontroler i tak nie wie, co się dzieje w metodach innych klas.

No właśnie według mnie zmienia w takiej sytuacji:

Warstwę logiki biznesowej tworzymy w całkiem osobnej solucji, w niej każdy service jest internal, interfejsy + wrapper IOC publiczny,
następnie do WebApi dodajemy referencję (plik dll, czy to ręcznie, czy to bardziej profesjonalnie przez skrypty budujące "całość") do warstwy serwisów.
W takiej sytuacji nie podejrzymy sobie już żadnej z metod serwisu, a jedynie ich interfejsy (choćby w object explorerze)

0

Mógłby ktoś doświadczony wyjaśnić kwestię tworzenia serwisów i ich komunikację? Jakie metody powinny być wystawione w interfejsach serwisów i co zwracać? Ogólnie o dobrych praktykach tworzenia serwisów?

Póki co, robię tak, że tworzę serwisy dla każdej klasy mapowanej na tabele bazy danych i tam tworzę/aktualizuję/usuwam rekordy, operując na ORM i jako argumenty przyjmując view modele.
Ponadto tworzę serwisy, które zwracają view modele pod akcje kontrolerów do wyświetlenia w widoku. Czy taki podział ma sens?

0

Jakie metody powinny być wystawione w interfejsach serwisów

@danek
Wszystko jedno jakie nazwy, ważne żeby skończyć zanim PM wróci. :D

Póki co, robię tak, że tworzę serwisy dla każdej klasy mapowanej na tabele bazy danych i tam tworzę/aktualizuję/usuwam rekordy, operując na ORM i jako argumenty przyjmując view modele.
Ponadto tworzę serwisy, które zwracają view modele pod akcje kontrolerów do wyświetlenia w widoku. Czy taki podział ma sens?

Zdaje się, że @somekind jest prekursorem tego nurtu architektonicznego, najlepiej jego zapytaj :P

1

W tym temacie jest fajnie pokazane jak relacja serwisu z kontrolerem mogłaby wyglądać.

1
Karol Krawczyk napisał(a):

Mógłby ktoś doświadczony wyjaśnić kwestię tworzenia serwisów i ich komunikację? Jakie metody powinny być wystawione w interfejsach serwisów i co zwracać? Ogólnie o dobrych praktykach tworzenia serwisów?

Serwis to tak szerokie pojęcie, że jedyną prawidłową odpowiedzią na takie pytanie będzie: SOLID i DRY.

Póki co, robię tak, że tworzę serwisy dla każdej klasy mapowanej na tabele bazy danych i tam tworzę/aktualizuję/usuwam rekordy, operując na ORM i jako argumenty przyjmując view modele.
Ponadto tworzę serwisy, które zwracają view modele pod akcje kontrolerów do wyświetlenia w widoku. Czy taki podział ma sens?

Jeśli się sprawdza i nie prowadzi do pisania więcej kodu niż trzeba, to ma. Tylko czemu nazywać wszystko serwisami?

Gworys napisał(a):

Zdaje się, że @somekind jest prekursorem tego nurtu architektonicznego, najlepiej jego zapytaj :P

Dzięki, ale to nie ja.

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