Використовуйте сервісний рівень з MVC


13

Якщо контролер стає занадто жирним, і інстанція моделі починає додаватися, може бути використаний сервісний шар.

  • Якщо я просто зафіксую логіку всередині класу обслуговування, я отримаю купу Служб одним / двома методами. Це відчувається як кодовий запах. Якісь найкращі практики щодо цього?

  • Чи може сервіс інстанціонувати моделі?

  • Якщо служба інстанціює моделі, послуги не можна перевірити. Вони можуть бути охоплені лише інтеграційними тестами?

Відповіді:


25

У "SOLID" "I" означає інтерфейсну сегрегацію. Вся ідея цього принципу полягає в розділенні великих інтерфейсів на більш дрібні, більш модульні. У сервісі MVC зазвичай є інтерфейс, на який покладається контролер. Ви не хочете, щоб ваші контролери знали про конкретну реалізацію цієї послуги. Тому купу послуг одним або двома методами - це добре.

Служби зазвичай повертають DTO у великих додатках або моделях домену безпосередньо в менших програмах. ЗНО зазвичай означає більше роботи, але краще розділення проблем. Типовий потік:

  • Служба дзвінків контролера
  • Служба повертає об'єкт (будь то DTO, модель домену чи щось інше)
  • Контролер відображає модель DTO / домен на модель перегляду

Картографування можна зробити вручну, але більшість розробників вважають за краще використовувати карту автоматичного картографування, наприклад, Automapper, оскільки нам не подобається писати сантехнічний код і ми можемо бути дуже лінивими :-)

http://en.wikipedia.org/wiki/Interface_segregation_principle

https://github.com/AutoMapper/AutoMapper

Одне з багатьох обговорень щодо stackoverflow щодо використання DTO та моделей доменів: /programming/2680071/dto-or-domain-model-object-in-the-view-layer


1
Мені слід бути обережним, використовуючи автоматичний картограф тут uglybugger.org/software/post/…
Daniel Little

AutoMapper оснащений вбудованою функцією тестування одиниць, яка дозволяє перевірити всі ваші підпрограми карти одним рядком. Автор цього повідомлення про це не згадував.
CodeART

Але він знає про це і цим користувався. Зауваження трохи впадають у цю проблему.
Даніель Літтл

2
Багато занять з одним або двома методами зазвичай означає, що вони не є згуртованими. Службовий шар, якщо він існує, повинен бути тонким з основною логікою, що знаходиться в моделях. Здається, безглуздо пов'язувати погляд на німий предмет, який є не що інше, як сумка власності. Модель у MVC повинна бути багатою доменною моделлю, а не анемічною однією martinfowler.com/bliki/AnemicDomainModel.html
Енді

3

У MVC Модель - це не просто DTO або набір менеджерів / служб, але це означає, що вони представляють концепції, які ваша програма моделює. Ви можете вважати це цілим доменом або бізнес-логікою, включаючи стан та поведінку. Тепер, враховуючи, що ми знаємо, що призначення контролера стає дещо чіткішим. Його завдання полягає в простому перекладі команд на Модель, а результат назад на види. Зазвичай це робиться у вигляді ViewModels, які відрізняються, але часто плутають з Model у MVC.

Якщо у вас немає чітко визначеної моделі, то, можливо, ви потрапили до того, що більшість цієї логіки зараз знаходиться в самих контролерах. У цей момент, щоб почати зменшувати розмір контролерів, ви можете почати перетягувати цю логіку назад в менеджер або сервісні об’єкти. Ці сервіси, як правило, повертаються та працюють на об'єктах типу DTO / Entity. Тоді контролер стає шаром відображення між цими службами та моделями перегляду. Кілька корисних порад щодо картографування ознайомтеся з цією статтею. Друзі не дозволяють друзям використовувати AutoMapper .

Що стосується ваших питань, то перше багато залежить від ваших заявок. Вам потрібно буде робити рефакторинг по шляху, який повинен стати більш очевидним, як тільки ви вилучите логіку з контролерів. Що стосується тестування, то тут немає проблем з інстанційними моделями всередині сервісів, але якщо вам здається, що тестування складно, це, мабуть, лише знак того, що вам потрібно розбити службу на більш дрібні частини, кожна з яких є однією відповідальністю.


3

Контролери повинні містити виклики до моделі (де відбувається логіка бізнесу) і на основі цих викликів призначати дані для перегляду (об'єкти інформації або повідомлення про помилки), тому контролерів буде досить мало навіть для дуже складної сторінки, якщо контролер все ще стає дуже великим, ви повинні подумати, що, можливо, цю сторінку слід розширити на більше сторінок.

Тим не менш, модель може бути досить великою ... рішення, яке я знайшов, було мати змінну всередині контролера, яка розповідає, яку модель потрібно завантажувати, і для конкретних завдань я завантажую конкретну модель.

Спробуйте дотримуватися чистої моделі контролера перегляду моделі:

  • представлення: відображає дані
  • контролер: збирає користувальницькі дані, запитує модель для запитуваних даних і повертає їх назад до перегляду
  • модель: взаємодіє з базою даних та виконує логічні дії з підготовки інформації

-1

Я вважаю сервіси дуже корисними для виконання логіки, яку може знадобитися виконувати більше одного контролера, або вона просто недостатньо конкретна, щоб бути частиною контролера, крім того, що це зупиняє мої контролери надто великими і важкими для читання .. .

Я особисто не погоджуюся з «ааа», коли він каже, що «модель (де трапляється логіка ділових ситуацій)», оскільки це вся причина у вас контролерів, на мою думку, моделі повинні бути простими абстракторами даних, щоб контролер міг виконувати необхідне завдання; знову послуги не повинні втягуватися у завдання з вилучення даних ...

просто кажу йо ...


1
Якщо ваша модель є лише даними, ви потрапили в анемічну модель домену antipattern martinfowler.com/bliki/AnemicDomainModel.html
Енді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.