Сервизен слой и структура на проекта в ASP.NET MVC 5 без хранилище и UoW шаблони

Бих искал да създам добро приложение в ASP.NET MVC 5, използвайки EF 6 Code first concept. Искам да е добре проектиран, т.е. най-общо казано: отделни слоеве за представяне, логика и данни. Искам да може да се тества :)

Ето моята идея и някои проблеми, свързани със създаването на приложение

Презентационен слой: Това е целият ми MVC - изглед на модели (не модели), изгледи, контролери. Вярвам, че това валидиране трябва да се направи някъде другаде (по мое мнение - това е част от бизнес логиката), но е доста удобно за използване на атрибути от пространството на имената DataAnnotations във ViewModelds и проверка на валидността в контролера.

Логически слой: Услуги - класове с техните интерфейси за управление на бизнес логиката. Поставих там функции като: AddNewPerson(PersonViewModel Person), SendMessageToPerson(...). Те ще използват контекста на DB, за да извършват своите действия (има шанс не всички от тях да разчитат на контекста). Има пряка връзка между услугата и db - имам предвид, че класът на услугата има препратка към контекст. Къде трябва да направя съпоставяне между ViewModel и Model? Чувал съм, че услугата е лошо място за това - така че може би в контролерите. Чувал съм, че услугата трябва да върши работата, свързана изключително с db. правилно ли е Моята картина на слоя услуга добра ли е?

Слой данни: Чел съм много за Repository и UoW шаблони. Има някои статии, които предполагат, че EF6 прилага тези две неща. Не искам да създавам допълнителен код, ако няма нужда от такова поведение. Въпросът е: прав ли съм да приема, че не ми трябват?

Ето моя поток:

Изглед‹->Контролери (използване на ViewModels)‹->Услуги (използване на модели)‹->DB.

**Ще използвам DI в моя проект.

Какво мислите за моята структура на проекта?


person WaltLift0    schedule 11.09.2014    source източник


Отговори (2)


Няма причина да използвате модел на единица работа с Entity Framework, ако не е необходимо да създавате общ механизъм за достъп до данни. Бихте направили това само ако сте:

  1. използване на технология за достъп до данни, която първоначално не поддържа модел на единица работа (EF го прави)
  2. Исках да мога да сменям доставчиците на данни някога в бъдещето... това обаче не е толкова лесно, колкото може да изглежда, тъй като е много трудно да НЕ се въведат зависимости от конкретни технологии за данни, дори когато се използва единица работа (може би дори ЗАЩОТО вие са)... или
  3. Трябва да имате начин да обединявате различни източници на данни в атомна транзакция.

Ако нито един от тези случаи не е такъв, най-вероятно нямате нужда от персонализирана единица работа. От друга страна, хранилището може да бъде полезно... но с EF6 много от предимствата на хранилището също са налични, тъй като EF6 предоставя подигравателни интерфейси за тестване. Независимо от това, стойте далеч от генерично хранилище, освен ако не е просто детайл от изпълнението на вашите конкретни хранилища. Излагането на генерични хранилища на другите ви слоеве е огромно изтичане на абстракция...

Въпреки това винаги използвам модел Repository/Service/Façade, за да създам разделение между моите данни и бизнес (и потребителски интерфейс и бизнес за този въпрос) слоеве. Осигурява удобен начин за подигравка, без да се налага да се подигравате с вашия достъп до данни, и отделя вашата логика от специфичното, въведено от слоя Linq, използван от EF (Linq е относително общ, но има неща, които са специфични за EF), интерфейс фасада/хранилище/сървър отделя това).

Като цяло сте на прав път... Позволете ми обаче да отбележа, че използването на атрибути на данни във вашите модели на изглед е нещо добро. Това централизира вашето валидиране на вашия модел, вместо да ви накара да поставите логика за валидиране навсякъде.

Вие сте прав, че имате нужда от валидиране и във вашата бизнес логика, но грешката ви е предположението, че трябва да го имате само в бизнес логиката. Имате нужда от валидиране на всички слоеве на вашето приложение. И по-специално, вашето валидиране на потребителския интерфейс може да има различни изисквания от валидирането на вашата бизнес логика.

Например, можете да внедрите създаването на нов акаунт като многоетапен съветник във вашия потребителски интерфейс, това ще изисква валидиране, различно от вашето бизнес ниво, тъй като всяка стъпка има само подмножество от валидирането на целия обект. Или може да изисквате вашият мобилен интерфейс да има различни изисквания за валидиране от вашия уеб сайт (единият може да използва captcha, докато другият може да използва базирано на докосване човешко валидиране например).

Така или иначе, важно е да имате предвид, че валидирането е важно както на клиента, сървъра, така и на различни слоеве...

person Erik Funkenbusch    schedule 11.09.2014
comment
Благодаря ти Ерик. Разбирам мисълта ти. Споменахте за валидиране - разбирам мисълта ви. Какво точно представляват хранилището и фасадата във вашия проект? - person WaltLift0; 12.09.2014
comment
@WaltLift0 - Моделът на хранилището всъщност е само специализиран фасаден модел. Това е поставянето на истинската ви реализация зад интерфейс, за да я разделите, така че никоя страна да не знае за другата. - person Erik Funkenbusch; 12.09.2014

Добре, нека изясним някои неща...

Понятието ViewModel (или действителната формулировка на ViewModel) е нещо, въведено от Microsoft Мартин Фаулър. Всъщност ViewModel не е нищо повече от обикновено class.

В действителност вашите Views са строго въведени до classes. Месечен цикъл. За да се избегне объркване, формулировката ViewModel се появи, за да помогне на хората да разберат това

„този клас ще се използва от вашия изглед“

затова ги наричаме ViewModel.

Освен това, въпреки че много книги, статии и примери използват думата ViewModel, нека не забравяме, че това не е нищо повече от просто Model.

Всъщност, забелязали ли сте някога защо има папка Models вътре в MVC приложение, а не папка ViewModels?

Също така, забелязали ли сте някога как в горната част на View имате директива @model, а не директива @ viewmodel?

Това е така, защото всичко може да бъде модел.

Между другото, за по-голяма яснота, можете да изтриете (или преименувате) папката Models и да създадете нова, наречена ViewModels, ако това помага.

Независимо какво правите, в крайна сметка ще извикате @model, а не @viewmodel в горната част на страниците си.

Друг подобен пример би бил DTO classes. DTO класовете не са нищо повече от обикновени класове, но те имат суфикс с DTO, за да помогнат на хората (програмистите) да правят разлика между всички останали класове (включително View Models).

В скорошен проект, върху който работих, това понятие не беше напълно разбрано от екипа, така че вместо техните Views строго въведени на Models, те щяха да имат своите изгледи строго въведени на DTO classes. На теория и на практика всичко работеше, но те скоро откриха, че имат свойства като IsVisible в техните DTO, когато всъщност; този вид свойства трябва да принадлежи към вашите ViewModel класове, тъй като се използват за логика на потребителския интерфейс.

Досега не съм отговорил на въпроса ви, но имам подобна публикация относно бърза архитектура. Можете да прочетете публикацията тук

Друго нещо, което бих искал да отбележа е, че ако и само ако вашият Service Layer планира да обслужва други неща като приложение Winform, мобилен уеб сайт и т.н., тогава вашият Service Layer не трябва да получава ViewModels.

Вашият Service Layer не трябва да има представа какво е ViewModel. Трябва да приема, получава, изпраща и т.н. POCO класове.

Това означава, че от вашия Controller, във вашия ActionResult, след като ModelState е Valid, трябва да трансформирате своя ViewModel в POCO, който на свой ред ще бъде изпратен до метода във вашия Service Layer.

С други думи, бих използвал/инсталирал пакета Automapper nugget и бих създал някои методи за разширение, които биха конвертирали ViewModel в POCO и обратно (POCO във ViewModel).

По този начин вашият AddNewPerson() метод ще получи Person обект за своя параметър, вместо да получи PersonViewModel параметър.

Не забравяйте, че това е валидно само if and only if вашите Service Layer планове за обслужване на други неща...

Ако това не е така, тогава не се колебайте да накарате вашите Service Layer да получават, изпращат, добавят и т.н...ViewModels вместо POCO. Това зависи от вас и вашия екип.

Не забравяйте, че има много начини да одерете котка.

Надявам се това да помогне.

person Vlince    schedule 11.09.2014
comment
Неправилно. Понятието ViewModel е създадено от Мартин Фаулър, въпреки че той го нарече Presentation Model и е дефинирано в неговия модел на Presentation Model. Вижте martinfowler.com/eaaDev/PresentationModel.html - Между другото, нарича се NuGet, а не самородно късче. Споменавам го само тъй като изглеждаш като привърженик на номенклатурата. - person Erik Funkenbusch; 12.09.2014
comment
Правилно, френската версия на Word, която използвам, пренебрегна грешката. Благодаря за корекцията :-) - person Vlince; 12.09.2014
comment
Благодаря ти Vlince. Позволи ми да разбера някои проблеми. Връщайки се към разликите между Model и ViewModel. Мисля, че те имитират малко по-различни неща: Модел - бизнес обект, ViewModel - избрани елементи от бизнес обект + някои допълнителни неща за краен потребител. - person WaltLift0; 12.09.2014