Podział aplikacji na podprojekty

Podział aplikacji na podprojekty
MI
  • Rejestracja:około 11 lat
  • Ostatnio:10 miesięcy
  • Postów:22
0

Cześć, ostatnio robię aplikacje internetową asp.net (organizer pracy) w technologii mvc4 i mam pytanie odnośnie podziału aplikacji na pod projekty. Doradzono mi bym stworzył 3 pod projekty. Jeden z operujący bazą danych, drugi zawierający całą logikę i trzeci główny zawierający web interfejs.
Czy taki podział aplikacji ma duży wpływ na jej jakość tzn. jest potrzebny?
Czy jeśli pobieram enity frameworka, to tylko załączam go do tego projektu operującego bazą danych?
Może lepiej użyć nhibernate, bo baza danych nie będzie jakaś obszerna?

Z góry dzięki i pozdrawiam :)

0

Poczytaj o wzorcu MVC. Tu nie chodzi o "podprojekty", tylko podział jednego projektu na trzy warstwy Model-View-Controller. Odpowiednio model danych, widok (prezentację), i logikę biznesową.

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

Cześć, ostatnio robię aplikacje internetową asp.net (organizer pracy) w technologii mvc4 i mam pytanie odnośnie podziału aplikacji na pod projekty. Doradzono mi bym stworzył 3 pod projekty. Jeden z operujący bazą danych, drugi zawierający całą logikę i trzeci główny zawierający web interfejs.
Czy taki podział aplikacji ma duży wpływ na jej jakość tzn. jest potrzebny?

Podział na warstwy ma wpływ na jakość, bo dzięki niemu kod jest usystematyzowany, a nie staje się spaghetti. Poszczególne warstwy mogą być w oddzielnych projektach, dzięki temu też łatwiej zapanować nad strukturą, bo fizycznie oddzielamy pliki z poszczególnych warstw, więc trudniej wprowadzić bałagan.
Należy tylko pamiętać, ze sam podział na warstwy i moduły nie gwarantuje jakości.

Czy jeśli pobieram enity frameworka, to tylko załączam go do tego projektu operującego bazą danych?
Może lepiej użyć nhibernate, bo baza danych nie będzie jakaś obszerna?

LOL
Entity Framework to zabawka dla przedszkolaków, słabe rozwiązanie dla małych baz i aplikacji. Niektórzy co prawda używają EF do dużych systemów, ale cierpi na tym wydajność i produktywność.
NHibernate to znacznie dojrzalsze, wydajniejsze i elastyczniejsze rozwiązanie, znacznie lepsze właśnie do dużych projektów.

Hrypa
  • Rejestracja:około 18 lat
  • Ostatnio:3 miesiące
1
Nie Mam Konta napisał(a):

Poczytaj o wzorcu MVC. Tu nie chodzi o "podprojekty", tylko podział jednego projektu na trzy warstwy Model-View-Controller. Odpowiednio model danych, widok (prezentację), i logikę biznesową.

Chyba mylisz MVC z n-tier. Całe MVC jest wzorcem warstwy prezentacji (a nie sam widok), pakowanie tam logiki biznesowej nie jest najlepszym pomysłem. Projekt MVC powinien tylko operować na gotowych serwisach innej warstwy.

Odyn
  • Rejestracja:ponad 16 lat
  • Ostatnio:ponad 5 lat
  • Postów:493
0

Samo MVC wskazuje Nam na 3 wydzielone warstwy naszej aplikacji. Ewentualnie 4 ze względu na to, że można wziąć pod uwagę ViewModele aby odciążyć system bazodanowy.

Oprócz tego mam taką praktykę ( nie wiem czy tak się fachowo robi ), że w osobnym projekcie wydzielam sobie warstwe dostępu do danych np. DataAccessLayer(DAL), tam również zawieram Repository i UoW.

Natomiast dodatkowo, jeśli korzystasz z serwisów to warto do osobnego projektu sobie je również wydzielić.

Ogólnie chodzi o lepszą organizacje kodu co ułatwia później rozwój aplikacjii.


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

Samo MVC wskazuje Nam na 3 wydzielone warstwy naszej aplikacji. Ewentualnie 4 ze względu na to, że można wziąć pod uwagę ViewModele aby odciążyć system bazodanowy.

ViewModele to nie jest ani warstwa ani odciążenie bazy danych, to tylko klasy.
MVC to jest wzorzec dla jednej warstwy - warstwa prezentacji. Za to Model może już się składać z n warstw.

Oprócz tego mam taką praktykę ( nie wiem czy tak się fachowo robi ), że w osobnym projekcie wydzielam sobie warstwe dostępu do danych np. DataAccessLayer(DAL), tam również zawieram Repository i UoW.

To akurat dobra praktyka, z dokładnością do tego, że w DAL umieszcza się implementacje repozytoriów, bo repozytoria to logika biznesowa.

0

Repozytoria w żadnym wypadku nie są logiką biznesową aplikacji. Powinny się ograniczać wyłącznie do operacji CRUD. MVC to jak ktoś już wspomniał wzorzec prezentacji. Nie potrafie sobie wyobrazić jak View Modele miałyby odciążyć bazę danych:D, wręcz odwrotnie, obciążają serwer. View modele są wykorzystywane do zapewnienia większej separacji w warstwie prezentacji. W tym wypadku wszystkie POCO/DTO z warstw niższych mapowane są na ViewModels w np. warstwie usług aplikacji, dzięki temu warstwa prezentacji nie zawiera do nich referencji. Porównywanie NHibernate z ET to jakaś głupota, oba frameworki służą do tego samego i różnią się detalami. Zamiast męczenia się relacyjnymi bazami danych polecam NOSQL (np. RavenDb czy MonboDb) - w 95% aplikacje które budujemy nie potrzebują atomowości danych czy narzędzi do raportowania z MSSQL. Do tego praca z takim RavenDb to czysta przyjemność. Można nawet pokusić się o zrezygnowanie z repo bo RavenDb jest implementowany w postaci właśnie UOW. Wszystko zależy od tego jakiej wielkości budujesz aplikacje i co będzie się z nią działo póżniej. Jednak minimum architektury zawsze należy zapewnić. Jeśli nie masz wielu reguł biznesowych - skorzystaj z Transaction Script - odsyłam do Fowlera. Ew Domain Model z kontraktami repo + implementacja repo w wartwie infrastruktury. Wszelka logika biznesowa która wymaga zestawów danych powinna być implementowana w warstwie usług DM w której można związać logikę biznesową z danymi. Zamiast warstwy usług można także skorzystać z imo ciekawszego rozwiązania jakim jest ServiceBus i zbudować aplikację w oparciu o CQRS (przykład tutaj: https://github.com/gregoryyoung/m-r/tree/master/SimpleCQRS). Podsumowując, dla bardzo prostej aplikacji która nie będzie w przyszłości rozwijana: Transaction Script, bardziej złożona (choć nie koniecznie jeśli czujesz się bardziej pewnie w paradygmacie obiektowym) Domain Model i/lub CQRS.

msm
Administrator
  • Rejestracja:około 16 lat
  • Ostatnio:5 miesięcy
1

Nie potrafie sobie wyobrazić jak View Modele miałyby odciążyć bazę danych:D, wręcz odwrotnie, obciążają serwer

Dlaczego? Najczęstszą przyczyną problemów typu N+1 SELECT jest korzystanie z modeli bazodanowych bezpośrednio w widokach.

Porównywanie NHibernate z ET to jakaś głupota, oba frameworki służą do tego samego i różnią się detalami

No tak, oba są ORMami więc służą do tego samego więc pewno różnią się tylko detalami :P. A feature listy obu się bardzo różnią.

Repozytoria w żadnym wypadku nie są logiką biznesową aplikacji. Powinny się ograniczać wyłącznie do operacji CRUD.

Jesli korzystamy z ORMa to CRUDowe repozytoria są krokiem wstecz.

Można nawet pokusić się o zrezygnowanie z repo bo RavenDb jest implementowany w postaci właśnie UOW

To tak jak przy NHibernate czy ET, ORM sam robi za repozytorium.

Zamiast warstwy usług można także skorzystać z imo ciekawszego rozwiązania jakim jest ServiceBus i zbudować aplikację w oparciu o CQRS

Może jest ciekawsze, ale IMO w 90% aplikacji niepotrzebne.

edytowany 2x, ostatnio: msm
msm
Autor zaczął
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
1
Zimny Młot napisał(a):

Repozytoria w żadnym wypadku nie są logiką biznesową aplikacji. Powinny się ograniczać wyłącznie do operacji CRUD.

Repozytoria to kontrakty źródeł danych dla logiki biznesowej, z jej punktu widzenia mają się zachowywać po prostu jak kolekcja encji. To, że konkretne implementacje repozytoriów wykonują operacje CRUD na bazie nie zmienia faktu, że ich kontrakty muszą być częścią logiki biznesowej, żeby mogła ona na nich operować. W tym sensie repozytoria są częścią logiki biznesowej - co nie znaczy, że ją wykonują.

Nie potrafie sobie wyobrazić jak View Modele miałyby odciążyć bazę danych:D, wręcz odwrotnie, obciążają serwer.

To uwaga do wszystkich - same ViewModele nie odciążają ani nie obciążają bazy danych... No chyba, że trzymamy w niej kod C#. ;)

Odciążyć może generowanie ViewModeli na poziomie warstwy dostępu do danych, która zbuduje optymalne zapytania. Tylko to wymaga odejścia od podejścia z repozytoriami zwracającymi encje na rzecz prostoty i wydajności.

Porównywanie NHibernate z ET to jakaś głupota, oba frameworki służą do tego samego i różnią się detalami.

NHibernate oferuje wbudowane cache drugiego poziomu, kilka generatorów PK, obsługuje różne rodzaje kolekcji, możliwość batchowego wykonywania zapytań, pełną konfigurowalność (w dowolnym miejscu można się wpiąć i zmienic domyślne zachowanie lub wykonać dodatkową operację), możliwość wykonywania operacij bez wczytywania obiektów (w EF, żeby usunąć obiekt z bazy, musisz go najpierw odczytać!) i daje pełną kontrolę nad generowanym kodem SQL.

EF ma za to tylko LINQ providera generującego kod SQL metodą Monte Carlo. No i od grudnia zeszłego roku obsługuje takie skomplikowane elementy składni SQL 2012 jak OFFSET FETCH. Do tego implementuje własną matematykę, bo domyślnie przy zapisie liczby zmiennoprzecinkowej nie wykonuje zaokrąglenia tylko ucięcie miejsc po przecinku.

To są detale?

Do tego praca z takim RavenDb to czysta przyjemność. Można nawet pokusić się o zrezygnowanie z repo bo RavenDb jest implementowany w postaci właśnie UOW.

No, a w ORM to nie można? Dziwne, bo ja (o ile mam wpływ na projekt) repozytoriów nigdy nie używam. Repozytoria w 99% aplikacji nie są potrzebne, bo 99% aplikacji nie potrzebuje DDD. A ISession czy nawet głupi DbContext są same w sobie implementacjami UoW.

msm
Ale miałeś porównywać NH do ET, a porównałeś z EF.
somekind
W końcu się domyśliłem, że to nie o kosmitę lecz kosmiczną technologię chodzi. ;)
MI
  • Rejestracja:około 11 lat
  • Ostatnio:10 miesięcy
  • Postów:22
0

A ma ktoś może jakiś project example z podpiętym i skonfigurowanym NHibernatem?

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
0

@Mikios, podpięcie to zainstalowanie paczki Fluent NHibernate z NuGeta i napisanie banalnej klasy budującej konfigurację. Masz jakiś konkretny problem?

QO
  • Rejestracja:około 11 lat
  • Ostatnio:11 miesięcy
  • Postów:40
0

@somekind @Mikios Entity Framework z racji popularności, doczekał się m.in. takiego projektu https://genericunitofworkandrepositories.codeplex.com/ .
Po stwierdzeniu

Entity Framework to zabawka dla przedszkolaków, słabe rozwiązanie dla małych baz i aplikacji.
aż z ciekawości sobie sprawdzę jakiś przykładowy projekt napisany z NHibernate, bo przyznam że choć EF 6.1 jest zdecydowanie lepszy względem poprzednich wersji, to jednak ciągle jednak nie zachwyca.
Znalazłem coś takiego: https://github.com/sharparchitecture/Sharp-Architecture

Zobacz pozostałe 2 komentarze
QO
Hmm, na pierwszy rzut oka nie widzę czemu niby generyczne repozytorium czy wystawianie IQueryable traktować za antywzorce. W podanym projekcie do generycznego repozytorium można dodawać metody https://genericunitofworkandrepositories.codeplex.com/SourceControl/latest#main/Sample/Northwind.Repository/Repositories/CustomerRepository.cs , a samą logikę można wrzucić do warstwy service'ów https://genericunitofworkandrepositories.codeplex.com/SourceControl/latest#main/Sample/Northwind.Service/CustomerService.cs . Całość wydaje się przemyślana.
MS
nie widzę czemu niby generyczne repozytorium czy wystawianie IQueryable traktować za antywzorce - jak pisałem - mamy dodawanie nowych metod przez extensiony, które opierają się na słowie static, w dodatku nie ma to żadnej przewagi nad gołym DbContextem. Co do IQueryable - grozi to tym, że ktoś, gdzieś i w kilku miejscach zrobi np. .ToList() na 1mln obiektów, albo zacznie sobie po tym iterować.
QO
W takim razie Microsoft forsuje antywzorce? http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options#server-paging Spójrzmy na OData, nawet przykład dokładnie odnoszący się do 1mln obiektów ; )
MS
Ale jak link ma się do tego co napisałem? IQueryable nie jest antywzorcem, tylko akurat zwracanie tego w kontekście repozytorium nie należy do dobrych praktyk, bo naraża nas na potencjalne problemy.
MS
Co do artykułów w sieci - byłem kiedyś na wykładzie prowadzonym przez jednego z guru MS. Prezentacja miała dotyczyć technologii X - by szybko pokazać możliwości prowadzący utworzył projekt w WinForms, dodał buttona, kliknął w niego dwa razy i zaczął kodzić... Po czym dodał: "mam nadzieję, że wiecie, że się tak nie robi." Sorry, ale w artykułach muszą być jakieś uproszczenia inaczej każdy artykuł musiałby się zaczynać od 100 unit testów ;)
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
3

@QwertzOne, repozytoria z definicji powinny definiować ścisłe kontrakty dla logiki biznesowej i izolować ją od źródła danych. Udostępnianie generycznych repozytoriów logice biznesowej to po prostu łamanie tego wzorca, bo po pierwsze w ten sposób wcale nie definiujesz żadnego kontraktu (bo nie masz specyficznych dla danej encji metod), dla większości przypadków takie repozytorium zawiera zbyt wiele metod (nie zawsze potrzebujesz GetAll, Save albo Delete. A udostępnianie metod zwracających IQueryable to po pierwsze wyciek abstrakcji, bowypuszczasz szczegół implementacji technologi dostępu do danych do logiki biznesowej, a po drugie przyczyna problemów wydajnościowych, bo logika biznesowa czy nawet warstwa prezentacji powodują wtedy materializację, a co za tym idzie dzięki lazy loading mogą spowodować problem n+1.

Repozytoria to są przede wszystkim INTERFEJSY z deklaracjami metod definiujących kontrakt dostępu do danych dla logiki biznesowej, a nie implementacja używająca takiego czy innego ORMa, żeby udawać jakąś separację między aplikacją a bazą.

Czy Microsoft promuje antywzorce? W dużej mierze tak - wszystkie ich oficjalne tutoriale do ASP.NET MVC łamią zasady tego wzorca, mają trywialne błędy projwktowe w bazowych bibliotekach (np. DateTime.Now nie powinno być właściwością), do tego np. MembershipProvider łamie podstawowe zasady SOLID, a taki System.Web to kupa legacy code.

I jeszcze coś - to, że coś się kompiluje i działa, nie znaczy jeszcze, że jest dobrze zrobione. A to, że wszyscy coś robią, nie znaczy od razu, że tak jest dobrze. Często jest wręcz przeciwnie.

edytowany 1x, ostatnio: somekind
QO
  • Rejestracja:około 11 lat
  • Ostatnio:11 miesięcy
  • Postów:40
0

@somekind Czy oceniając czy coś jest dobrze zrobione, nie powinno brać się pod uwagę skali projektu? Dla większego systemu takie rozwiązania nie będą się nadawać i o tworzeniu takich systemów nie mam pojęcia, ale w przypadku małych, średnich projektów (czyli takich którymi zajmuje się wielu programistów) kosztem łamania części "dobrych" wzorców, które sprawdzają się w większych projektach czy wycieków abstrakcji (myślę, że te ew. zawsze się pojawią i można iść na kompromis, przyjmując kiedy są akceptowalne), zyskuje się prostotę i czas, mniej doświadczonym osobom też łatwiej wejść do takiego projektu.
PHP + MySQL zyskały popularność, bo były proste, dzisiaj mamy m.in. C#, node.js, tony framework'ów/bibliotek javascriptowych(które odgrywają coraz większą rolę z popularyzacją SPA), z których użyciem można pisać prosto i przyjemnie, bez konieczności posiadania dużej wiedzy o tworzeniu architektury.
Przeciętni programiści stanowią większość, jest więc i na to popyt.

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Wrocław
1

Ja jestem jak najbardziej za uproszczeniami i stosowaniem jak najprostszej architektury w stosunku do rozmiaru zadania. Ale jak ma nam w tym pomóc:

  1. nazywanie repozytorium czegoś, co z repozytorium nie ma nic wspólnego?
  2. tworzenie własnej abstrakcji w postaci generycznego repozytorium opakowującego kontekst EF, który sam w sobie jest przecież generycznym repozytorium?
  3. popełnianie elementarnych błędów, takich jak dopuszczenie do powstania n+1?

Zrobienie czegoś dobrze nie oznacza, że trzeba na to poświęcić więcej czasu. Często właśnie wręcz przeciwnie. Tylko trzeba przestać na siłę wciskać wszędzie antywzorce, do których jest się przyzwyczajonym.

0

Możesz napisać coś więcej o punkcie 2 i 3?

Jak powinna wyglądać dobrze zaprojektowana aplikacja?
Mam coś takiego: kontroler operuje na interfejsie, który reprezentuje operacje na konkretnej tabeli(klasie POCO) w bazie danych. Ten interfejs implementuje klasa, która operuje na interfejsie kontekstu. Z wykorzystaniem IoC.

Co jest złego w zwracaniu do kontrolera IQueryable<T>? Każda książka do ASP.NET MVC ma taki przykład z Lazy Loading.

Co do punktu 3. Problem N + 1 występuje gdy nie korzysta się z Lazy Loading i chce się pobrać listę obiektów połączonych relacją z inną tabelą. Wtedy dla każdego obiektu są pobierane w oddzielnym poleceniu obiekty połączone relacja.
W takim razie czy IQueryable<T> nie rozwiązuje tego problemu?

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

Jak powinna wyglądać dobrze zaprojektowana aplikacja?

Powinna trzymać się zasad SOLID, a chociaż SRP. Czyli:

  1. Klasa, która opisuje format danych w bazie, nie powinna służyć do wyświetlania ich użytkownikowi. Chociażby dlatego, że często użytkownik potrzebuje widzieć mniej albo więcej danych, niż te zawarte w jednej tabeli. Dlatego w widokach wyświetla się viewmodele, a nie encje.
  2. Jeśli mamy warstwę dostępu do danych, to ona powinna zwracać dane pobrane z bazy, a nie wirtualne zapytanie. Dlatego kontrolery nie powinny pracować na IQueryable.
  3. Klasa służąca do obsługi żądań użytkowników, wołania modelu i przekierowania widoku, nie realizacji logiki biznesowej ani pobierania danych z bazy. Chodzi mi w tym momencie o kontrolery - i o tej ich odpowiedzialności wyraźnie mówi wzorzec MVC.

Mam coś takiego: kontroler operuje na interfejsie, który reprezentuje operacje na konkretnej tabeli(klasie POCO) w bazie danych. Ten interfejs implementuje klasa, która operuje na interfejsie kontekstu. Z wykorzystaniem IoC.

Jak chcesz, ale to nie jest na pewno MVC, i na pewno nie masz tam repozytoriów.

Co jest złego w zwracaniu do kontrolera IQueryable<T>? Każda książka do ASP.NET MVC ma taki przykład z Lazy Loading.

Kontroler powinien dostać gotowe dane do przekazania do widoku, a nie wyciągać je z bazy. I nie powinien nic wiedzieć o konkretnej technologii dostępu do danych. Ani nawet o tym, że gdzieś tam jest baza danych.
Przykłady w książkach do ASP.NET MVC to uproszczone przykłady jak działa ten framework, a nie jak należy pisać sensowne aplikacje.

Problem N + 1 występuje gdy nie korzysta się z Lazy Loading

Jesteś pewien?
Ten problem występuje, gdy nawigujemy po właściwościach obiektów z jakiejś listy. Jeśli są one leniwe, to dla każdego obiektu z listy zostanie wykonane zapytanie do bazy. Jeśli obiekty listy wczytamy zachłannie z ich właściwościami, to problem ten przecież nie wystąpi.

W takim razie czy IQueryable<T> nie rozwiązuje tego problemu?

Ani go nie powoduje, ani go nie rozwiązuje. To zupełnie inna rzecz.

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.