ASP.NET MVC – La logica aziendale dovrebbe esistere nei controller?

Derik Whitaker ha pubblicato un articolo un paio di giorni fa che ha colpito un punto di cui sono stato curioso da un po ‘di tempo: la logica aziendale dovrebbe esistere nei controller?

Finora tutte le dimostrazioni MVC di ASP.NET che ho visto hanno messo l’accesso al repository e la logica aziendale nel controller. Alcuni addirittura lanciano la convalida anche lì. Ciò si traduce in controller abbastanza grandi e gonfiati. È davvero questo il modo di usare il framework MVC? Sembra che questo stia per finire con un sacco di codice duplicato e logica sparsi su diversi controller.

La logica aziendale dovrebbe davvero essere nel modello. Dovresti mirare a modelli grassi, controller magri.

Ad esempio, invece di avere:

public interface IOrderService{ int CalculateTotal(Order order); } 

Preferirei avere:

 public class Order{ int CalculateTotal(ITaxService service){...} } 

Ciò presuppone che la tassa sia calcasting da un servizio esterno e richiede al modello di conoscere le interfacce per i servizi esterni.

Ciò renderebbe il controller simile a qualcosa:

 public class OrdersController{ public OrdersController(ITaxService taxService, IOrdersRepository ordersRepository){...} public void Show(int id){ ViewData["OrderTotal"] = ordersRepository.LoadOrder(id).CalculateTotal(taxService); } } 

O qualcosa di simile.

Mi piace il diagramma presentato da Microsoft Patterns & Practices . E credo nel motto “Un’immagine vale più di mille parole”.

Il diagramma mostra l'architettura di MVC e dei livelli dei servizi aziendali

Questa è una domanda affascinante.

Penso che sia interessante il fatto che un gran numero di applicazioni MVC di esempio non riescono a seguire il paradigma MVC nel senso di posizionare veramente la “logica aziendale” interamente nel modello. Martin Fowler ha sottolineato che MVC non è un modello nel senso di Gang Of Four. Piuttosto, è paradigma che il programmatore debba aggiungere dei pattern se sta creando qualcosa al di là di un’app giocattolo.

Quindi, la risposta breve è che la “logica di business” non dovrebbe effettivamente vivere nel controller, poiché il controller ha la funzione aggiuntiva di gestire la vista e le interazioni dell’utente e vogliamo creare oggetti con un solo scopo.

Una risposta più lunga è che è necessario riflettere sul design del layer del modello prima di spostare la logica dal controller al modello. Forse puoi gestire tutta la logica dell’app usando REST, nel qual caso il design del modello dovrebbe essere abbastanza chiaro. In caso contrario, dovresti sapere quale approccio utilizzerai per mantenere gonfio il tuo modello.

Puoi controllare questo fantastico tutorial di Stephen Walther che mostra Convalida con un livello di servizio .

Scopri come spostare la logica di convalida dalle azioni del controller e in un livello di servizio separato. In questo tutorial, Stephen Walther spiega come mantenere una netta separazione delle preoccupazioni isolando il livello di servizio dal livello del controller.

Business Logic non dovrebbe essere contenuto nei controller. I controller dovrebbero essere il più magri ansible, idealmente seguire il patter:

  1. Trova l’entity framework del dominio
  2. Agire sull’ quadro di dominio
  3. Preparare i dati per i risultati di visualizzazione / restituzione

Inoltre i controller possono contenere alcune logiche dell’applicazione.

Allora, dove metto la mia logica aziendale? Nel modello.

Cos’è il modello? Questa è una buona domanda. Si prega di consultare l’articolo di Microsoft Patterns and Practices (kudos to AlejandroR per la ricerca eccellente). Qui ci sono tre categorie di modelli:

  • Visualizza modello : si tratta semplicemente di un sacchetto di dati, con una logica minima, se non nulla, per passare i dati da e verso le viste, contiene la convalida del campo di base.
  • Modello di dominio : modello grasso con logica aziendale, opera su una singola o più entity framework di dati (vale a dire l’entity framework A in un determinato stato rispetto all’azione sull’ quadro B)
  • Modello di dati : il modello che riconosce lo storage, la logica contenuta in una singola quadro si riferisce solo a quell’entity framework (cioè se il campo a è quindi il campo b)

Ovviamente MVC è un paradigma disponibile in diverse varietà. Quello che descrivo qui è MVC che occupa solo lo strato superiore, guarda questo articolo su Wikipedia

Oggi MVC e simili model-view-presenter (MVP) sono modelli di progettazione di Separation of Concerns che si applicano esclusivamente al livello di presentazione di un sistema più grande. In scenari semplici, MVC può rappresentare il progetto principale di un sistema, raggiungendo direttamente il database; tuttavia, nella maggior parte degli scenari, il controller e il modello in MVC hanno una dipendenza libera da un livello di servizio o di dati / livello. Questo è tutto sull’architettura Client-Server

Se usi gli Iniettori di Dipendenza, la tua logica aziendale andrà da loro e quindi otterrai controller accurati e puliti.