🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: alt.pl.comp.lang.csharp
6 messages
6 total messages Started by MarlonB Wed, 22 Feb 2012 13:08
ServiceLayer - rozważanie, best practice
#22357
Author: MarlonB
Date: Wed, 22 Feb 2012 13:08
68 lines
3902 bytes
Witam,

    Jestem w trakcie pisania warstwy ServiceLayer w moim projekcie. 
Pośredniczy ona między wartwą logiki biznesowej (businessLayer) a wartwą 
prezentacji, czyli jest ona fabryką różnych api, tak jak ja to rozumiem. Co 
mnie zastanawiało:
- Jak ma wyglądać takie api?
- Jakie typy danych ma zwracać?
- Jakie typy danych ma przyjmować na wejściu?

Warstwy businessLayer, dataAccessLayer, serviceLayer dzielą się w spólnie 
głupimi modelami danych - POCO, które odzwierciedlają jeden do jeden, to co 
jest w bazie danych. To znaczy, klasa User i jej właściwości odzwierciedlają 
tabelę User i jej kolumny w bazie danych.

Wprowadzenie serviceLayer ma m.in. za zadanie zerwanie zależności po między 
tymi typami danych, które są dość skomplikowane a wartwą prezentacji. 
Warstwa serviceLayer może mieć kilka api i każde api musi być dość jasne, 
przejrzyste, dać się łatwo modyfikować i testować.

Co wymyśliłem? Jedno z api, które produkuje serviceLayer będzie to api do 
zarządanie aplikacją - panel admina (to jest tylko przykład, nie rzeczywisty 
kod):

interface AdminPanelApi
{
    IDictionary<string, object> GetUsers(GetUsersRequired, 
GetUsersOptional);
    IDictionary<string, object> GetSomeObjects(GetSomeObjectsRequired, 
GetSomeObjectsOptional);
}

Co na tym widać:
- Wszystkie metody zwracają dokładnie i zawsze to samo, czyli drzewo 
IDictionary<string, object>, gdzie object może być typem prostym lub 
następnym IDictionary<string, object>.
- Każda metoda na wejściu ma dedykowane 2 obiekty: <nazwa metody>Required i 
<nazwa metody>Optional. Po co? W pierwszym są dane, które muszą być, aby 
wywołanie miało sens. Drugie są opcjonalne, gdzie każda właściwość może być 
nullem. Jeśli dojdzie jakaś własność, to łatwo to będzie zmodyfikować, 
udokumentować, zwalidować i serializować. Typy wejściowe nie są drzewiaste: 
mogą zawierać proste typy i proste kolekcje.
- Dodanie każdej metody, to: wpisanie nagłówka do interfacu, 
zaimplementowanie metody, napisanie 2 klas i udokumentowanie jakie klucze 
będą zwracane.

Zalety:
- łatwo modyfikowalne,
- łatwo zrozumiałe,
- IDictionary<string, object> można łatwo przerobić na Jsona, xmla lub 
cokolwiek w przypadku napisania web servicu korzystającego z serviceLayer,
- w zależności od poziomu dostępu wywołującego metodę i danych wejściowych 
IDictionary<string, object> może zawierać czasem mniej lub więcej kluczy - 
to musi być w dokumentacji co od czego zależy.

Wady:
- Typ IDictionary<string, object> nie jest jasno opisany przez kod - 
potrzeba pracy z dokumentacją.

I teraz główne pytania:
- Czy to ma sens?
- Czy ktoś już pisał coś podobnego i natrafił na lepsze rozwiązanie?
- Gdzie znajde jakieś informacje best practice jak się piszę porządne api, 
które może się rozrastać bez końca?

Pozdrawiam.

M. 
Re: ServiceLayer - rozważanie, best practice
#22358
Author: Łukasz 'Maly' Ostrowski
Date: Wed, 22 Feb 2012 15:54
133 lines
6596 bytes
On Wed, 22 Feb 2012 14:08:45 +0100, MarlonB wrote:
>     Jestem w trakcie pisania warstwy ServiceLayer w moim projekcie. 
> Pośredniczy ona między wartwą logiki biznesowej (businessLayer) a wartwą 
> prezentacji, czyli jest ona fabryką różnych api, tak jak ja to rozumiem. Co 
> mnie zastanawiało: <snip>

Czyli service layer to po prostu kontener IoC/service-locator? ;-)

> Warstwy businessLayer, dataAccessLayer, serviceLayer dzielą się w spólnie 
> głupimi modelami danych - POCO, które odzwierciedlają jeden do jeden, to co 
> jest w bazie danych. To znaczy, klasa User i jej właściwości odzwierciedlają 
> tabelę User i jej kolumny w bazie danych.

Mhm, Domain Model aka DDD:
http://en.wikipedia.org/wiki/Domain-driven_design

> Wprowadzenie serviceLayer ma m.in. za zadanie zerwanie zależności po między 
> tymi typami danych, które są dość skomplikowane a wartwą prezentacji. 
> Warstwa serviceLayer może mieć kilka api i każde api musi być dość jasne, 
> przejrzyste, dać się łatwo modyfikować i testować.

To się z reguły robi poprzez dependency injection, tzn. pytasz
kontener IoC o instancję kontrolera(mvc), a ten kontener wstrzeliwuje 
zależności bez aktywnego odpytywania explicite kontenera o dane 
serwisy.

http://en.wikipedia.org/wiki/Dependency_injection#Automatically_injected_dependency
http://en.wikipedia.org/wiki/Service_locator_pattern
http://en.wikipedia.org/wiki/Inversion_of_control

> interface AdminPanelApi
> {
>     IDictionary<string, object> GetUsers(GetUsersRequired, 
> GetUsersOptional);
>     IDictionary<string, object> GetSomeObjects(GetSomeObjectsRequired, 
> GetSomeObjectsOptional);
> }

To wygląda bardziej jak Repository pattern w tym wydaniu. Serwisy
z reguły "coś robią", wykonują procesy biznesowe etc. Z kolei
repozytoria(DAO) są właśnie do GetUsers(string filter) ;-).

/Podział ideologiczno-nomenklaturyowy jest czysto syntetyczny/

> Co na tym widać:
> - Wszystkie metody zwracają dokładnie i zawsze to samo, czyli drzewo 
> IDictionary<string, object>, gdzie object może być typem prostym lub 
> następnym IDictionary<string, object>.

Czemu Dictionary<>? Dlaczego nie Set/List lub Customowy View Model? 
To powinno zależeć od realnie wykonywanej akcji i oczekiwanego 
rezultatu. Późniejsze kombinacje

var res = GetUsers(...);
var registeredUsers = res["Registered"] as IList<User>;

to bezpośrednie proszenie o kłopoty. ;-). Nie działa do tego 
IntelliSense...

> - Każda metoda na wejściu ma dedykowane 2 obiekty: <nazwa metody>Required i 
> <nazwa metody>Optional. Po co? W pierwszym są dane, które muszą być, aby 
> wywołanie miało sens. Drugie są opcjonalne, gdzie każda właściwość może być 
> nullem. Jeśli dojdzie jakaś własność, to łatwo to będzie zmodyfikować, 
> udokumentować, zwalidować i serializować. Typy wejściowe nie są drzewiaste: 
> mogą zawierać proste typy i proste kolekcje.

Jeżeli do XxxRequired dojdzie property, to build nie pójdzie w krzaki,
i.e. przejdzie do implementacji "API" niezainicjowane prop, moim zdaniem
to źle. Gdy są explicite argumenty dodane, wciskasz Build i od razu masz
potencjalne miejsca które "zepsułeś", w postaci listy błędów kompilacji.
I to compile-time, nie runtime, nie test-run-time.

Reasumując, moim zdaniem nie warto nadbudowywać na argumenty, warstwę
abstrakcji w postaci kontenera argumentów, tylko użyć tego co jest:

IEnumerable<Users> GetSomeUsers(bool includeDeleted, 
	Expression<Func<User, bool>> filterBy = null);

> - Dodanie każdej metody, to: wpisanie nagłówka do interfacu, 
> zaimplementowanie metody, napisanie 2 klas i udokumentowanie jakie klucze 
> będą zwracane.

Najlepsze jest taki kod który się dokumentuje sam. :). 

> Zalety:
> - łatwo modyfikowalne,
> - łatwo zrozumiałe,
> - IDictionary<string, object> można łatwo przerobić na Jsona, xmla lub 
> cokolwiek w przypadku napisania web servicu korzystającego z serviceLayer,

Takowoż IEnumerable<>, View Modele lub cokolwiek innego.

> - w zależności od poziomu dostępu wywołującego metodę i danych wejściowych 
> IDictionary<string, object> może zawierać czasem mniej lub więcej kluczy - 
> to musi być w dokumentacji co od czego zależy.

Nie nazwałbym wszystkich czterech zalet, zaletami. To raczej rzeźbienie na 
void* albo $php. IMO ofc ;-).

> Wady:
> - Typ IDictionary<string, object> nie jest jasno opisany przez kod - 
> potrzeba pracy z dokumentacją.

- Nie funkcjonuje IntelliSense na Dictionary<string,object>.

> I teraz główne pytania:
> - Czy to ma sens?

Pi razy drzwi. Idea wydaje się być ok, ale wykonanie rodem z PHP. 
Nic osobistego ;-).

> - Czy ktoś już pisał coś podobnego i natrafił na lepsze rozwiązanie?

Cośtam ktoś pisał i maintainuje aktywnie. "Większa" aplikacja 
na ASP.NET MVC + SharpArch, generalnie IoC, DI i główne 
"funkcjonalności" rozdzieone pomiędzy ICośtamCośtamService i
ICośtamCośtamRepository. Nie narzekam.

> - Gdzie znajde jakieś informacje best practice jak się piszę porządne api, 
> które może się rozrastać bez końca?

To raczej advocacy, ja śledzę m.in. blog Ayende, czasami się nie zgadzam,
ale z reguły ma rację co do architektury i okołotematycznych rantów.

(Wiekszość akapitów można przyozdobić "IMO", żadne objawienia, 
dlatego żadnych linków ani sławnych nazwisk nie podałem, nawet 
jeżeli są to ideologiczne zaczerpnięcia z Fowlera czy kogokolwiek 
- jestem zbyt leniwy żeby je znaleźć - a.k.a. Wikipediowe 
"missing references" ;-)).

-- 
Pozdrawiam,
Łukasz 'Maly' Ostrowski.      http://l3v.pl/
Re: ServiceLayer - rozważanie, best practice
#22359
Author: MarlonB
Date: Wed, 22 Feb 2012 17:02
173 lines
7919 bytes
Użytkownik "Łukasz 'Maly' Ostrowski" <maly@USUNnemo.pl> napisał w wiadomości 
news:12b400yh5lb3r.mg3vhkurgug9.dlg@40tude.net...
> On Wed, 22 Feb 2012 14:08:45 +0100, MarlonB wrote:
>>     Jestem w trakcie pisania warstwy ServiceLayer w moim projekcie.
>> Pośredniczy ona między wartwą logiki biznesowej (businessLayer) a wartwą
>> prezentacji, czyli jest ona fabryką różnych api, tak jak ja to rozumiem. 
>> Co
>> mnie zastanawiało: <snip>
>
> Czyli service layer to po prostu kontener IoC/service-locator? ;-)

O! to, właśnie to! :)


>> Warstwy businessLayer, dataAccessLayer, serviceLayer dzielą się w spólnie
>> głupimi modelami danych - POCO, które odzwierciedlają jeden do jeden, to 
>> co
>> jest w bazie danych. To znaczy, klasa User i jej właściwości 
>> odzwierciedlają
>> tabelę User i jej kolumny w bazie danych.
>
> Mhm, Domain Model aka DDD:
> http://en.wikipedia.org/wiki/Domain-driven_design

Dokładnie :)

>> Wprowadzenie serviceLayer ma m.in. za zadanie zerwanie zależności po 
>> między
>> tymi typami danych, które są dość skomplikowane a wartwą prezentacji.
>> Warstwa serviceLayer może mieć kilka api i każde api musi być dość jasne,
>> przejrzyste, dać się łatwo modyfikować i testować.
>
> To się z reguły robi poprzez dependency injection, tzn. pytasz
> kontener IoC o instancję kontrolera(mvc), a ten kontener wstrzeliwuje
> zależności bez aktywnego odpytywania explicite kontenera o dane
> serwisy.
>
> http://en.wikipedia.org/wiki/Dependency_injection#Automatically_injected_dependency
> http://en.wikipedia.org/wiki/Service_locator_pattern
> http://en.wikipedia.org/wiki/Inversion_of_control
>
>> interface AdminPanelApi
>> {
>>     IDictionary<string, object> GetUsers(GetUsersRequired,
>> GetUsersOptional);
>>     IDictionary<string, object> GetSomeObjects(GetSomeObjectsRequired,
>> GetSomeObjectsOptional);
>> }
>
> To wygląda bardziej jak Repository pattern w tym wydaniu. Serwisy
> z reguły "coś robią", wykonują procesy biznesowe etc. Z kolei
> repozytoria(DAO) są właśnie do GetUsers(string filter) ;-).
>
> /Podział ideologiczno-nomenklaturyowy jest czysto syntetyczny/
>
>> Co na tym widać:
>> - Wszystkie metody zwracają dokładnie i zawsze to samo, czyli drzewo
>> IDictionary<string, object>, gdzie object może być typem prostym lub
>> następnym IDictionary<string, object>.
>
> Czemu Dictionary<>? Dlaczego nie Set/List lub Customowy View Model?
> To powinno zależeć od realnie wykonywanej akcji i oczekiwanego
> rezultatu. Późniejsze kombinacje
>
> var res = GetUsers(...);
> var registeredUsers = res["Registered"] as IList<User>;
>
> to bezpośrednie proszenie o kłopoty. ;-). Nie działa do tego
> IntelliSense...

Wydawało mi się to dobrym pomysłem... ale właśnie przestało.


>> - Każda metoda na wejściu ma dedykowane 2 obiekty: <nazwa metody>Required 
>> i
>> <nazwa metody>Optional. Po co? W pierwszym są dane, które muszą być, aby
>> wywołanie miało sens. Drugie są opcjonalne, gdzie każda właściwość może 
>> być
>> nullem. Jeśli dojdzie jakaś własność, to łatwo to będzie zmodyfikować,
>> udokumentować, zwalidować i serializować. Typy wejściowe nie są 
>> drzewiaste:
>> mogą zawierać proste typy i proste kolekcje.
>
> Jeżeli do XxxRequired dojdzie property, to build nie pójdzie w krzaki,
> i.e. przejdzie do implementacji "API" niezainicjowane prop, moim zdaniem
> to źle. Gdy są explicite argumenty dodane, wciskasz Build i od razu masz
> potencjalne miejsca które "zepsułeś", w postaci listy błędów kompilacji.
> I to compile-time, nie runtime, nie test-run-time.
>
> Reasumując, moim zdaniem nie warto nadbudowywać na argumenty, warstwę
> abstrakcji w postaci kontenera argumentów, tylko użyć tego co jest:
>
> IEnumerable<Users> GetSomeUsers(bool includeDeleted,
> Expression<Func<User, bool>> filterBy = null);
>
>> - Dodanie każdej metody, to: wpisanie nagłówka do interfacu,
>> zaimplementowanie metody, napisanie 2 klas i udokumentowanie jakie klucze
>> będą zwracane.
>
> Najlepsze jest taki kod który się dokumentuje sam. :).
>
>> Zalety:
>> - łatwo modyfikowalne,
>> - łatwo zrozumiałe,
>> - IDictionary<string, object> można łatwo przerobić na Jsona, xmla lub
>> cokolwiek w przypadku napisania web servicu korzystającego z 
>> serviceLayer,
>
> Takowoż IEnumerable<>, View Modele lub cokolwiek innego.
>
>> - w zależności od poziomu dostępu wywołującego metodę i danych 
>> wejściowych
>> IDictionary<string, object> może zawierać czasem mniej lub więcej 
>> kluczy -
>> to musi być w dokumentacji co od czego zależy.
>
> Nie nazwałbym wszystkich czterech zalet, zaletami. To raczej rzeźbienie na
> void* albo $php. IMO ofc ;-).

hmm... no może w sumie racja...

>> Wady:
>> - Typ IDictionary<string, object> nie jest jasno opisany przez kod -
>> potrzeba pracy z dokumentacją.
>
> - Nie funkcjonuje IntelliSense na Dictionary<string,object>.
>
>> I teraz główne pytania:
>> - Czy to ma sens?
>
> Pi razy drzwi. Idea wydaje się być ok, ale wykonanie rodem z PHP.
> Nic osobistego ;-).
>
>> - Czy ktoś już pisał coś podobnego i natrafił na lepsze rozwiązanie?
>
> Cośtam ktoś pisał i maintainuje aktywnie. "Większa" aplikacja
> na ASP.NET MVC + SharpArch, generalnie IoC, DI i główne
> "funkcjonalności" rozdzieone pomiędzy ICośtamCośtamService i
> ICośtamCośtamRepository. Nie narzekam.
>

Mógłbyś napisać coś więcej w jaki sposób / ze względu na co rozdzielasz 
funkcjonalność na Service i Repository?
Repository wykorzystuje między warsta dataAccess a businessLogic. Jak 
rozumiem repository ma tylko operacje CRUD? Dlatego nie bardzo widzę 
zastosowania repository w serviceLayer, jako że potrzebuje konkretnych 
akcji. Być może coś źle rozumiem...
Ciekawi mnie bardzo opinia kogoś już doświadczonego, czyli co powinno 
znaleźć się w serviceLayer? Jakie patterny? W serviceLayer korzystam z unity 
do pozyskania konkretnej implementacji danego serwisu.

Może jakieś ciekawe artykuły jak dobrze zaprojektować to wszystko?

>> - Gdzie znajde jakieś informacje best practice jak się piszę porządne 
>> api,
>> które może się rozrastać bez końca?
>
> To raczej advocacy, ja śledzę m.in. blog Ayende, czasami się nie zgadzam,
> ale z reguły ma rację co do architektury i okołotematycznych rantów.
>
> (Wiekszość akapitów można przyozdobić "IMO", żadne objawienia,
> dlatego żadnych linków ani sławnych nazwisk nie podałem, nawet
> jeżeli są to ideologiczne zaczerpnięcia z Fowlera czy kogokolwiek
> - jestem zbyt leniwy żeby je znaleźć - a.k.a. Wikipediowe
> "missing references" ;-)).
>

Dzięki za odpowiedź.

Pozdro.

M. 
Re: ServiceLayer - rozważanie, best practice
#22361
Author: Łukasz 'Maly' Ostrowski
Date: Wed, 22 Feb 2012 18:04
49 lines
2999 bytes
On Wed, 22 Feb 2012 18:02:20 +0100, MarlonB wrote:
> Mógłbyś napisać coś więcej w jaki sposób / ze względu na co rozdzielasz 
> funkcjonalność na Service i Repository?

Behavior i Composite Actions - Service
Data Access - Repository

Ale w uproszczeniu, wszystko można traktować jako Service. Zostajesz
wtedy przy "Data Services". Ale tak jak napisałem:
> /Podział ideologiczno-nomenklaturyowy jest czysto syntetyczny/

Przykładowo w wersji #A z której korzystam, jest overkill bo
kontroler nigdy nie korzysta bezpośrednio z repository,
tylko z serwisów, które z kolei "importują" sobie repozytoria. 
Dochodzi do sytuacji w której
  IUserService.Get(int id);
jest bezpośrednim forwardem do
  IUserRepository.Get(id);
Nie zauważyłem żadnego zysku z takiego rozwarstwienia, więc 
zacząłem także importować repozytoria bezpośrednio do kontrolerów.

Wszystko jest umowne, wybiera się ścieżkę najsensowniejszą z Twojego
punktu widzenia.

> Repository wykorzystuje między warsta dataAccess a businessLogic. Jak 
> rozumiem repository ma tylko operacje CRUD? Dlatego nie bardzo widzę 
> zastosowania repository w serviceLayer, jako że potrzebuje konkretnych 
> akcji. Być może coś źle rozumiem...

Dobrze rozumiesz. Repository pattern to CRUD.

> Ciekawi mnie bardzo opinia kogoś już doświadczonego, czyli co powinno 
> znaleźć się w serviceLayer? Jakie patterny? W serviceLayer korzystam z unity 
> do pozyskania konkretnej implementacji danego serwisu.

ServiceLocator.Resolve<T>() będzie prawdopodbnie w zupełności jedynym
wymaganym callem kontenera IoC, defacto, ewentualnie wystarczy
sforwardować podstawowe calle Unity.

> Może jakieś ciekawe artykuły jak dobrze zaprojektować to wszystko?

Przyjrzyj się SharpArchitecture, nie jest doskonałe, ale tak do
poglądowego ogarnięcia jest całkiem niezłe. Ostatnim razem jak
widziałem #A, było nieźle, nie wiem w jakim dokładnie stanie
architekturalnym jest wersja aktualna.

-- 
Pozdrawiam,
Łukasz 'Maly' Ostrowski.      http://l3v.pl/
Re: ServiceLayer - rozważanie, best practice
#22362
Author: MarlonB
Date: Thu, 23 Feb 2012 11:03
83 lines
4692 bytes
Użytkownik "Łukasz 'Maly' Ostrowski" <maly@USUNnemo.pl> napisał w wiadomości 
news:1mt437iq9a6yz.1vti2z6dbuetk.dlg@40tude.net...
> On Wed, 22 Feb 2012 18:02:20 +0100, MarlonB wrote:
>> Mógłbyś napisać coś więcej w jaki sposób / ze względu na co rozdzielasz
>> funkcjonalność na Service i Repository?
>
> Behavior i Composite Actions - Service
> Data Access - Repository
>
> Ale w uproszczeniu, wszystko można traktować jako Service. Zostajesz
> wtedy przy "Data Services". Ale tak jak napisałem:
>> /Podział ideologiczno-nomenklaturyowy jest czysto syntetyczny/
>
> Przykładowo w wersji #A z której korzystam, jest overkill bo
> kontroler nigdy nie korzysta bezpośrednio z repository,
> tylko z serwisów, które z kolei "importują" sobie repozytoria.
> Dochodzi do sytuacji w której
>  IUserService.Get(int id);
> jest bezpośrednim forwardem do
>  IUserRepository.Get(id);
> Nie zauważyłem żadnego zysku z takiego rozwarstwienia, więc
> zacząłem także importować repozytoria bezpośrednio do kontrolerów.

Kapuje. U mnie będzie potrzebna właśnie taka warstwa, bo być może przed MVC 
będę miał jakiś web service.

> Wszystko jest umowne, wybiera się ścieżkę najsensowniejszą z Twojego
> punktu widzenia.
>
>> Repository wykorzystuje między warsta dataAccess a businessLogic. Jak
>> rozumiem repository ma tylko operacje CRUD? Dlatego nie bardzo widzę
>> zastosowania repository w serviceLayer, jako że potrzebuje konkretnych
>> akcji. Być może coś źle rozumiem...
>
> Dobrze rozumiesz. Repository pattern to CRUD.
>
>> Ciekawi mnie bardzo opinia kogoś już doświadczonego, czyli co powinno
>> znaleźć się w serviceLayer? Jakie patterny? W serviceLayer korzystam z 
>> unity
>> do pozyskania konkretnej implementacji danego serwisu.
>
> ServiceLocator.Resolve<T>() będzie prawdopodbnie w zupełności jedynym
> wymaganym callem kontenera IoC, defacto, ewentualnie wystarczy
> sforwardować podstawowe calle Unity.


No to mam w takim razie pytanie. Czy serviceLayer ma mieć swoje własne view 
modele? Tzn czy oprócz zależności od domain modeli ma mieć jeszcze jakieś 
swoje modele, na które będę je mapował?
Bo stąd był mój pomysł z IDoctionary, bo coś musze zwracać. A co mam zwracać 
jesli nie domain modele? Jakiś ViewModel? Bo w MVC też mam ViewModele i nie 
bardzo wiem jak to pożenić.

dataaccessLayer, businessLayer, serviceLayer => te mają zależność od domain 
models.
UiWebLayer => ma zależność od serviceLayer i posiada własne ViewModele. Nie 
chciałbym, aby była zależność od domain models.

Co sprowadza się do tego, że serviceLayer musi zwracać swoje ViewModele, 
które będą mapowane na ViewModele z UiWebLayer :)

Cel jest taki aby niepotrzebnie nie mieszać i nie przepisywać ciągle z 
modelu na model, ale widzę, że trudno coś innego wymyśleć. Do mapowania 
używam Automappera, więc może nie będzie aż tyle roboty. Rzecz, której się 
boje, to nagły rozrozt aplikacji i możliwość pogubienia się i koszty w 
utrzymaniu skomplikowanego kodu. Teraz to wygląda niewinnie...

>> Może jakieś ciekawe artykuły jak dobrze zaprojektować to wszystko?
>
> Przyjrzyj się SharpArchitecture, nie jest doskonałe, ale tak do
> poglądowego ogarnięcia jest całkiem niezłe. Ostatnim razem jak
> widziałem #A, było nieźle, nie wiem w jakim dokładnie stanie
> architekturalnym jest wersja aktualna.
>

Sciągnąłem właśnie i sobie "na to pacze" :)

Dzięki za wskazówki.

Pozdro.

M. 
Re: ServiceLayer - rozważanie, best practice
#22363
Author: Łukasz 'Maly' Ostrowski
Date: Thu, 23 Feb 2012 14:42
26 lines
2325 bytes
On Thu, 23 Feb 2012 12:03:40 +0100, MarlonB wrote:
> No to mam w takim razie pytanie. Czy serviceLayer ma mieć swoje własne view 
> modele? Tzn czy oprócz zależności od domain modeli ma mieć jeszcze jakieś 
> swoje modele, na które będę je mapował?
> Bo stąd był mój pomysł z IDoctionary, bo coś musze zwracać. A co mam zwracać 
> jesli nie domain modele? Jakiś ViewModel? Bo w MVC też mam ViewModele i nie 
> bardzo wiem jak to pożenić.
> <snip>
> Co sprowadza się do tego, że serviceLayer musi zwracać swoje ViewModele, 
> które będą mapowane na ViewModele z UiWebLayer :)

Taaak, dobrze rozumiesz. Pozatym nie zawsze możesz pchać domain model
bezpośrednio, bo może zawierać info które ma być przykładowo, ukryte.

> Cel jest taki aby niepotrzebnie nie mieszać i nie przepisywać ciągle z 
> modelu na model, ale widzę, że trudno coś innego wymyśleć. Do mapowania 
> używam Automappera, więc może nie będzie aż tyle roboty. Rzecz, której się 
> boje, to nagły rozrozt aplikacji i możliwość pogubienia się i koszty w 
> utrzymaniu skomplikowanego kodu. Teraz to wygląda niewinnie...

Ja staram się reusować domain modele tam gdzie się da, bo Automapper
i ciągłe konwersje wprowadzają zamęt.

-- 
Pozdrawiam,
Łukasz 'Maly' Ostrowski.      http://l3v.pl/
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads