2009-07-29 19 views
59

Stiamo costruendo un'applicazione HR abbastanza grande in ASP.NET MVC, e finora i nostri controllori stanno diventando piuttosto grandi. Ad esempio, disponiamo di un controller Employee e tutte le visualizzazioni dei dipendenti sono incluse (Informazioni personali, detrazioni dipendenti, dipendenti, ecc.). Ciascuna di queste viste potrebbe avere più azioni o sottoview (ad esempio CRUD). Ogni azione è relativamente piccola, ma i controller potrebbero avere dozzine di funzioni.Meglio avere controller enormi o molti controller in MVC?

Esistono procedure consigliate per suddividere i controller? Invece di avere un controller Employee con dozzine di viste, sarebbe meglio avere un controller per ogni sottotipo (cioè EmployeePersonalInfoController, EmployeeDeductionController, EmployeeDependentController)?

E infine, importa?

Aggiornato Chiarimento

La mia preoccupazione era originale con azioni CRUD. Ad esempio, prendiamo in considerazione Creazione ed eliminazione ...

azioni attuali in EmployeeController:

CreateEmployee() 
    DeleteEmployee() 
    CreateEmployeeDeduction() 
    DeleteEmployeeDeduction() 
    CreateDependent() 
    DeleteDependent() 
    etc. 

Se i controllori sono stati suddivisi:

EmployeeController 
    Create() 
    Delete() 
    EmployeeDeductionController 
    Create() 
    Delete() 
    EmployeeDependentController 
    Create() 
    Delete() 
    EmployeeBenefitController 
    Create() 
    Delete() 
    etc. 

Nel 1 ° scenario, il nostro ~ 100 gli schermi vengono suddivisi in 8-10 controller di grandi dimensioni. Nel secondo, probabilmente avrei ~ 50 controller.

risposta

12

Secondo il mio modesto parere, se si mantiene il codice nei controller in basso allora non importa.

La maggior parte del codice si sarebbe verificata in un livello aziendale da qualche parte, giusto? Se questo è il caso, tutto ciò che stai facendo veramente nel tuo controller è il ritorno dei dati alla vista. Come dovrebbe essere.

Non sono sicuro se sono un fan di separare i controller in sottotipi. Mentre dovresti mantenere la separazione delle preoccupazioni, penso che i sottotipi stiano andando un po 'troppo oltre.

Si potrebbe dare un'occhiata a questo post per vedere se aiuta. Same View Different Paths

Questa potrebbe essere una soluzione migliore rispetto all'utilizzo di un sottotipo di approccio suggerito.

+0

Non sono sicuro che "sottotipi" sia la migliore espressione da parte mia. Non implementerei le aree (raggruppandole in cartelle), semplicemente creando più di esse. Aggiornerò la domanda con qualche tipo di esempio per chiarire Grazie. –

+0

La realtà, in pratica, è che i controller MVC fanno molto di più del semplice rendering delle viste. Per lo meno, è necessario un get e post gestore separato per ogni pagina. Ognuno richiede input diversi. Se sei fortunato, il modello di visualizzazione che esegui è lo stesso modello di visualizzazione che viene pubblicato di nuovo. In un post, il controller deve almeno decomprimere il modello di visualizzazione in un DTO per passare al livello della tua business logic, e probabilmente dovrai fare una sorta di trasformazione su di esso, perché la suddivisione logica dei dati proviene dall'utente non è necessariamente uguale a ciò che viene inviato al livello della business logic. – Triynko

+0

Dopo aver passato i dati al livello aziendale per l'elaborazione, il controllore deve elaborare una condizione di esito positivo o negativo. In caso di errore, se hai un modello dati personalizzato (ad esempio, il rendering dei dati come una stringa JSON), lo stato del modello integrato è inutile e dovrai fare altri passi per assicurarti che ciò che l'utente ha postato sia consegnato sul display. In caso di successo, è necessario decidere dove inviare l'utente successivo. Tutto questo non è banale, e segue ancora la regola di base di non mettere la logica di business nel controller. I controller non sono così semplici come le persone li stanno facendo per essere. – Triynko

3

Perché non raggrupparli?

Avere una struttura come,

employee/payroll/ 
    employee/payroll/giveraise 
    employee/payroll/manage401k 

employee/general/ 
    employee/general/address 
    employee/general/emergencycontact 

ora è possibile avere uno gestire le azioni relative libro paga del controller del libro paga e un controllore generale che gestisce i dettagli regolari di un dipendente.

+1

Ci piacerebbe, ma nello standard ASP.NET MVC non esiste alcun concetto di aree (che credo sia quello che stai suggerendo). Potremmo aggiungere un'estensione che supporta le aree, ma non mi piace aggiungere un sacco di cose se non è necessario. –

+1

Penso che quello che Yogi Means è il libro paga è il controller e giveraise/manage401k è l'azione di quelli. Non è necessario avere alcuna estensione, basta aggiungere alcune regole di routing a global.asax funzionerebbe. – xandy

+1

@Jess et al - Il supporto FYI per aree ora esiste: http://msdn.microsoft.com/en-us/library/ee671793.aspx –

1

I controller sono pensati per essere contenitori per azioni in un contesto. OSSIA un controllore del cliente avrebbe azioni relative al controllo dei clienti. Questo è particolarmente adatto a CRUD. Vorrei andare con meno controller più grandi per questo motivo. Detto questo, spetta a te, in quanto architetto di applicazioni, scegliere il modo migliore per adattarsi al tuo codice e solo perché è più comune farlo in un modo non significa che devi farlo.

Se si dispone di grandi quantità di codice, suggerirei di esaminare le aree MVC ASP.NET.È possibile trovare post eccellenti su di esso Here in Scott Gu's blog e Here in Steve Sanderson's blog. Se hai così tanti controller, potrebbe essere adatto a te.

Appena avuto un pensiero dopo aver riletto il tuo post, ho il sospetto che il tuo esempio non si avvicini al livello di complicazioni che hai nel tuo codice. Forse potrebbe essere d'aiuto se tu pubblicassi una situazione in cui non eri sicuro se fosse una buona idea dividere il controller che è più specifico (e meno CRUDDY, perché CRUD è abbastanza semplice).

27

Partial classes consentono di diffondere la classe su più file. In questo modo puoi raggruppare le aree rilevanti del tuo controller in file separati, eppure faranno ancora parte dello stesso controller. per esempio.

EmployeeDeductionController.cs

public partial class EmployeeController 
{ 
    public ActionResult Deduct() 
    { 
    } 
    // etc 
} 

EmployeeBenefitController.cs

public partial class EmployeeController 
{ 
    public ActionResult GiveBenefit() 
    { 
    } 
    // etc 
} 
+1

Questo può funzionare abbastanza bene, è l'unico motivo per cui mi preoccuperei di una lezione parziale. –

+4

Buon pensiero ... ma per curiosità, come è più vantaggioso di suddividere il Controller in molti controller? –

+17

Un'idea interessante, ma penso che abusi un po 'la funzione di classe parziale. Le classi parziali sono state progettate principalmente per gli scenari di generazione del codice in modo che gli sviluppatori possano aggiungere a una classe generata e mantenere tali modifiche durante una rigenerazione. A meno che non fraintendano, penso che sia meglio creare controllori separati con una classe base condivisa piuttosto che usare i partial. –

10

non vorrei avere 50 controllori. In questo momento ho 16 nella mia domanda e questo sembra ok. Se disponi di 50 controller, avrai anche 50 cartelle di livello superiore per le visualizzazioni. Sarà difficile trovare la vista e il controller su cui lavorare. Come altri hanno menzionato le azioni sono in genere brevi e non è così male avere un paio di loro nel controller.

Ho provato ad avere 1 controller per parte di sistema. Definisco una parte del sistema prendendo il mio schema di database e disegnando una linea attorno alle tabelle che appartengono insieme.

1

Organizzerei i controller approssimativamente attorno ai casi d'uso e al loro raggruppamento logico. Per esempio. se si hanno più casi d'uso di tipo amministrativo/HR che sono probabilmente disponibili per un gruppo limitato di persone, raggrupparli in un unico controller. Altri controller possono essere organizzati attorno a specifici oggetti del modello di dominio, ad es. gestione del congedo self-service, domande salariali ecc. Non esiste una regola ferrea, bisogna creare un equilibrio tra non mettere troppa responsabilità in un singolo controllore rispetto al riutilizzo di strutture interne comuni.

Ricorda anche che per quanto possibile non dovresti avere la logica di business principale nei controller. Implementano davvero il comportamento front-end mentre le regole reali del sistema dovrebbero essere nel modello di dominio e nel livello di servizio. Finché mantieni le cose approssimativamente nello strato giusto e ragionevolmente disaccoppiato, non puoi sbagliare troppo nel modo in cui posizioni le singole operazioni all'interno dei tuoi controller.

2

Un altro approccio che abbiamo utilizzato è avere un controllerBase per mantenere i problemi trasversali in un luogo comune per le operazioni CRUD. Questo controller dichiara le operazioni comuni e include i punti di estensione per le entità specifiche. Abbiamo avuto troppe duplicazioni di codice senza qualcosa di simile.

Quindi, si eredita questo controller e ne crei uno per entità. E sì, ci sono molti controller ma con così tanti schermi, non penso che sarà il problema principale.

La maggior parte delle azioni accetta un modello complesso e suoniamo quindi con i raccoglitori modello per rimuovere il disordine dai controller. Puoi vedere un buon post su quello here.

Quindi, utilizzare aree come @Odd suggerisce è una buona idea, almeno per separare le viste perché quando ne hai molte è un disastro.

Si spera che l'ASP.NET MVC v2 ci porterà aree e visualizzazioni incapsulanti in diversi assembly (in realtà ciò può essere fatto estendendo ora la classe VirtualPathProvider).

Problemi correlati