ASP.NET MVC - La logica di business dovrebbe esistere nei controller?


97

Derik Whitaker ha pubblicato un paio di giorni fa un articolo che ha colpito un punto che mi incuriosiva da tempo: la logica di business dovrebbe esistere nei controller?

Finora tutte le demo di ASP.NET MVC che ho visto hanno inserito l'accesso al repository e la logica di business nel controller. Alcuni addirittura inseriscono la convalida anche lì. Ciò si traduce in controller abbastanza grandi e gonfiati. È davvero questo il modo di utilizzare il framework MVC? Sembra che questo finirà con un sacco di codice e logica duplicati distribuiti su diversi controller.


Il collegamento all'articolo è morto - web.archive.org/web/20150906064521/http://devlicio.us/blogs/… è una copia da archive.org per chiunque sia interessato.
Stuart Moore

Risposte:


75

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:

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

Ciò presuppone che l'imposta venga calcolata da un servizio esterno e richiede che il modello conosca le interfacce dei servizi esterni.

Questo renderebbe il tuo controller simile a:

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.


1
Quindi inietteresti servizi nei tuoi controller invece che nei repository? Come entra in gioco il principio dell'unità di lavoro in questo caso?
Kevin Pang,

Ho scritto altre cose, spero che questo abbia più senso. Potresti leggere anche: weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model Anche se si tratta di Rails è ancora molto applicabile.
jonnii

Personalmente definirei un repository un servizio.
Brad Wilson,

Sono sicuramente una sorta di servizio, ma sono specifici per l'accesso ai dati. È solo una convenzione che uso, non qualcosa che sostengo specificamente.
jonnii

1
Questo renderà il tuo modello strettamente accoppiato con ITaxService. Se si desidera riutilizzare il modello in un altro progetto o in un'altra dll, è necessario disporre di un'implementazione o di un riferimento ITaxService, altrimenti il ​​modello verrà danneggiato, il che si tradurrà in una violazione dei principi SOLID. ITaxService dovrebbe avere un riferimento del tuo modello. In questo modo, puoi riutilizzare il tuo modello in un altro progetto senza bisogno del riferimento ITaxService.
Mehmet Ali Sert

65

Mi piace il diagramma presentato da Microsoft Patterns & Practices . E credo nell'adagio "Un'immagine vale più di mille parole".

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


6
È davvero utile! Potresti dirmi dove su quel sito hai trovato questo diagramma?
Rob Church

2
Questo è tratto da "Implementazione lato server" di Microsoft msdn.microsoft.com/en-us/library/hh404093.aspx
Justin

OK, ma in un'app MVC, dove va la logica aziendale? Sembra che abbiamo bisogno di un livello di servizio aggiuntivo o qualcosa del genere ?!
niico

14

Questa è una domanda affascinante.

Penso che sia interessante che un gran numero di applicazioni MVC di esempio non riescano effettivamente a seguire il paradigma MVC nel senso di collocare veramente la "logica di business" interamente nel modello. Martin Fowler ha sottolineato che MVC non è uno schema nel senso della Gang Of Four. Piuttosto, è paradigma che il programmatore deve aggiungere modelli di se che stanno creando qualcosa al di là di un app giocattolo.

Quindi, la risposta breve è che la "logica di business" in effetti non dovrebbe risiedere nel controller, poiché il controller ha la funzione aggiuntiva di gestire la vista e le interazioni dell'utente e noi vogliamo creare oggetti con un solo scopo.

Una risposta più lunga è che è necessario riflettere sulla progettazione del livello del modello prima di spostare semplicemente 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 evitare che il tuo modello si gonfi.


14

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

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


2
Questa è la risposta più corretta. Personalmente sostengo inoltre di non esporre i servizi al controller, scegliendo invece di utilizzare un concetto ViewModel come si trova nel pattern MVVM. Immagina uno scenario in cui desideri scrivere un'app aziendale con un'interfaccia desktop (ad esempio, Windows Form o WPF) e anche un'interfaccia web. Risolvendo questo problema si arriva al pattern "skinny controller", come viene sostenuto anche qui. In conclusione: non inserire mai la logica di business in un modello o in un controller e non inserire nulla in un controller che non hai anche tu.
Sam

9

La logica aziendale non deve essere contenuta nei controller. I controller dovrebbero essere il più magri possibile, idealmente seguire il picchiettio:

  1. Trova entità di dominio
  2. Agisci sull'entità di dominio
  3. Preparare i dati per visualizzare / restituire i risultati

Inoltre, i controller possono contenere una certa logica dell'applicazione.

Allora dove metto la mia logica aziendale? Nel modello.

Cos'è il modello? Questa è una bella domanda. Consulta l' articolo Microsoft Patterns and Practices (complimenti ad AlejandroR per l'eccellente ricerca). Qui ci sono tre categorie di modelli:

  • Modello di visualizzazione : si tratta semplicemente di un contenitore di dati, con una logica minima, se del caso, per passare i dati da e alle visualizzazioni, contiene la convalida dei campi di base.
  • Modello di dominio : modello grasso con logica di business, opera su una o più entità di dati (ovvero entità A in un determinato stato rispetto all'azione sull'entità B)
  • Modello di dati : modello compatibile con l' archiviazione, la logica contenuta in una singola entità si riferisce solo a quell'entità (cioè se il campo a allora il campo b)

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

Oggi, MVC e MVP (Model-View-Presenter) simili sono modelli di progettazione Separation of Concerns che si applicano esclusivamente al livello di presentazione di un sistema più grande. In scenari semplici MVC può rappresentare il progetto primario 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 / livello di servizio o dati. Questo è tutto sull'architettura client-server


-1

Se usi gli iniettori di dipendenza, la tua logica aziendale andrà a loro e quindi otterrai controller ordinati e puliti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.