Хитрості C #: зменшення кількості контролерів

15 листопада 2014 року

(P) Закладки.dev - Диспетчер закладок із відкритим кодом та фрагментів коду для розробників та Co. Перегляньте наші посібники "Як додати", які допоможуть вам розпочати роботу. Загальнодоступні закладки Repo на Github - Star

кількості

Цей допис у блозі присвячений моїй колезі Семінді, яка експериментувала з тим, як створювати прості та потужні веб-програми. Дякую, що показала мені свої ідеї та обговорила зі мною вдосконалення, Семіндо.

Я вважаю, що багато програм C # мають набагато непотрібний код. Це особливо вірно, оскільки вага бізнес-логіки багатьох додатків переходить від внутрішньої до коду JavaScript на веб-сторінках. Коли робота вашої програми полягає у наданні даних інтерфейсу, важливо тримати їх в тонку.

У цій статті я намагався спростити стандартний контролер API MVC 4 шляхом узагальнення функціональних можливостей, централізації обробки винятків та додавання методів розширення до набору БД, який використовується для отримання моїх даних.

Якщо ви згенеруєте контролер API на основі існуючої сутності та видалите частину шуму, ваш код може виглядати так:

Цей код - спрощена версія того, що дасть вам майстер контролера API 4. Він включає метод GetPerson, який повертає людину за ідентифікатором, PostPerson, який зберігає нову особу, GetPeople, який повертає всіх людей у ​​базі даних, GetAdminsInCity, який фільтрує людей за містом та типом, і DeletePerson, який знаходить людину із зазначеним ідентифікатором та видаляє його.

Я замінив DbContext та IDbSet на інтерфейси замість конкретного підкласу DbContext, що полегшує створення тестів, які використовують подвійний для бази даних, наприклад MockDbSet.

Згенеруйте контролер

Це легко і безпечно, якщо все просто. Як загальну пораду, перейменуйте ваші методи на „Get”, „Post” та „Index”, а не „GetPerson”, „PostPerson” та „GetPeople”. Це дасть можливість узагальнити контролер таким чином:

Універсальний EntityController можна використовувати для будь-якого класу, яким керує EntityFramework.

Обробка винятків

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

Фактична обробка винятків повинна бути централізованою. Це одночасно полегшує читання коду та гарантує послідовну обробку винятків. У MVC 4 місце для цього має ExceptionFilterAttribute.

Таким чином, ми можемо спростити EntityController:

HandleApplicationException виглядає так:

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

Dbset як сховище

Але одна частина залишається в PersonController: Досить складне використання LINQ для виконання спеціалізованого запиту. Тут багато розробників запровадять сховище зі спеціалізованим “FindAdminsByCity” і, можливо, навіть окремим сервісним рівнем із методом “FindSummaryOfAdminsByCity”.

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

Натомість ви можете скористатися методами розширення C #:

Отриманий метод контролера стає приємним та інкапсульованим:

Це досить мінімально і просто!

Я продемонстрував три прийоми для зменшення складності ваших контролерів: По-перше, частини ваших контролерів можна узагальнити, особливо якщо ви уникаєте імені сутності в іменах методів дій; по-друге, обробка винятків може бути централізованою, усуваючи шум від основного потоку додатків та забезпечуючи узгодженість; нарешті, за допомогою методів розширення на IQueryable

надає моєму домену DbSet конкретні методи без необхідності реалізації додаткових шарів в архітектурі.

Я хотів би почути, чи використовуєте ви такий підхід, чи ви пробували щось подібне, але виявили, що цього бракує.