Quando una classe o un modulo dovrebbe trovarsi in un assembly / DLL separato?


22

Ci sono delle linee guida per decidere quando una classe dovrebbe trovarsi nel proprio assembly / DLL? Vedo spesso due scuole di pensiero:

1) Ogni "raggruppamento" di classi appartiene alla propria DLL, ad esempio repository, servizi, DTO, infrastruttura, ecc.

2) Tutto dovrebbe essere in una singola DLL ma separato da spazi dei nomi / cartelle, ad esempio avere una DLL "Core" con spazi dei nomi aggiuntivi, ad esempio Core.Repositories, Core.Services, Core.DTO, ecc.

Al lavoro, raccogliamo tutto in un'unica Assemblea chiamata "Business". Ci sono alcune cartelle ma non c'è una vera separazione: gli oggetti business (con la logica, alcuni dei quali non dovrebbero nemmeno essere classi) sono raggruppati in una cartella "BusinessObjects" senza cura. Le cose utilizzate in più di una classe si trovano in una cartella "Core". I programmi di utilità si trovano in una cartella "Programmi di utilità", l'infrastruttura di accesso ai dati è una cartella "Dati".

Per un nuovo modulo su cui sto lavorando, voglio / ho bisogno di avere un livello di accesso ai dati separato (pensate a un'implementazione di repository rudimentale) ma non voglio semplicemente buttarlo nella cartella "BusinessObjects" con l'altro 160 (!) lezioni lì. Allo stesso tempo, sono preoccupato per la creazione di una nuova libreria di classi poiché tutti sono abituati a riempire una classe nella singola libreria; una cartella / spazio dei nomi potrebbe funzionare comunque.

Risposte:


12

Trovo che sia meglio avere più progetti (es. Assiemi) con classi divise per categoria in ciascun progetto rispetto a un progetto con tutte queste classi in spazi dei nomi separati. Dovresti mirare a che i tuoi progetti siano riutilizzabili e che rappresentino diversi livelli in un'applicazione. È quindi possibile riutilizzare in modo fattibile questi progetti in applicazioni future senza dover includere un sacco di classi non necessarie.

Ad esempio, in base a ciò che hai menzionato, avrei sicuramente i seguenti progetti:

  • Nucleo
  • Dati
  • Dominio (o BusinessObjects)
  • Servizi
  • Utilità (o aiutanti)

2
Purtroppo non posso votare la risposta. Questo è esattamente ciò che è consigliato nella nostra azienda. Di conseguenza, con circa 6 progetti, ad esempio per un sito Web di medie dimensioni, non è possibile mantenere una gerarchia di directory basata su funzionalità, ecc. Di conseguenza, si finisce con sei progetti con ognuno di essi è un grande disordinato impossibile navigare tra i file. Di solito le persone che lo consigliano non hanno mai provato la struttura dei progetti basata su funzionalità su progetti relativamente grandi (scusate il giudizio diretto ma trattare i risultati di tale eccessiva preoccupazione è un vero dolore). La risposta jammycakes consiglia un approccio corretto.
alehro,

Dividere le classi per categoria è ciò che porta al caos in grandi progetti. Dividili per caratteristica / aspetto. Quindi gli spazi dei nomi rispecchieranno questa divisione. E l'intera struttura rispecchierà il lessico dalle specifiche. Dividere le classi per categoria è come aggiungere abbreviazioni di tipo ai nomi delle variabili - di solito è un cattivo odore.
alehro,

È facile abusare di entrambe le soluzioni proposte (ovvero troppi progetti o troppo pochi). Trovare un buon equilibrio in cui si tenga presente la riusabilità e il basso accoppiamento dovrebbe portare a qualcosa di più verificabile e mantenibile.
Bernard,

16

"Zio Bob" Martin di Clean Code, la fama dei principi SOLID ha delineato tre principi qui :

  • Il principio di equivalenza del riutilizzo del rilascio: il granulo del riutilizzo è il granulo del rilascio.
  • Il principio di chiusura comune: le classi che cambiano insieme sono raggruppate insieme.
  • Il principio di riutilizzo comune: le classi che vengono usate insieme sono raggruppate insieme.

La regola generale è che il numero di progetti nella soluzione dovrebbe essere il più basso possibile. Suddividili solo se hai bisogno di farlo per implementare una o più storie utente specifiche o se avere un singolo assembly causa problemi di prestazioni misurabili (in genere una volta che arrivano a diversi megabyte di dimensioni).


2
+1 questi principi sono buone linee guida. La separazione delle classi in diversi assiemi introduce ulteriori considerazioni di progettazione (ad esempio quali versioni di ciascun assieme possono lavorare insieme) aumentando la base di codice generale, aumentando così i costi di manutenzione.
Ben

1
Tuttavia, oltre a questi principi, aggiungerei che spesso è una buona idea impacchettare il codice che probabilmente verrà sostituito o scambiato in un assembly separato. Questo codice trarrà vantaggio dalle considerazioni aggiuntive necessarie per l'accoppiamento di assiemi separati e la sua separazione renderà più semplice testare e confrontare le diverse versioni.
Ben

4
Sì, ma assicurati che ci sia un vero requisito per la sua sostituzione o sostituzione. Ad esempio, i framework e le librerie di terze parti - pacchetti NuGet e simili - di solito devono supportare più contenitori IOC e più framework di registrazione. Per il codice userland, d'altra parte, tali astrazioni sono di solito puramente speculative, inutili e ostruttive e non risolvono mai alla fine nelle rare occasioni in cui sono effettivamente necessarie.
Jammycakes,

"Suddividili solo se hai bisogno di farlo per implementare una o più storie utente specifiche, o se avere un singolo assembly sta causando problemi di prestazioni misurabili (in genere una volta che arrivano a diversi megabyte di dimensione)." - totalmente casuale e non fondato sui consigli di realtà
hyankov,

1
Mi dispiace, ma cosa è esattamente "totalmente casuale e non fondato sulla realtà"? Ho pubblicato questa risposta dopo anni di lavoro su soluzioni che sono state suddivise in molti più progetti del necessario per nessun motivo diverso da quello che si suppone sia necessario. Il risultato? Tempi di compilazione glaciali e un inferno di inferno di dipendenza (specialmente nei giorni pre-NuGet). Suddividere le cose in assiemi separati ha un costo e, se non vi è alcun vantaggio nel compensare tale costo, è solo un caso di furto dall'azienda.
Jammycakes,

4

Alcuni altri principi guida con cui lavoro:

  • Pensi di riutilizzare questo codice in altri progetti? Per un gruppo di applicazioni Web correlate, disponevamo di un modulo relativo all'account utente utilizzato da tutte le applicazioni, poiché utilizzavano tutti lo stesso modello per account utente e accessi. Ho fatto cose simili con le librerie di geometria e matematica e le ho riutilizzate in più applicazioni, includendo semplicemente la DLL.

  • Vuoi essere in grado di modificare / distribuire questo codice senza ridistribuire / ricompilare l'intero progetto? A volte è stato utile ricostruire il modulo, distribuire e riavviare l'applicazione Web.

Sembra che nel tuo caso un repository generico e di base potrebbe essere utile in futuro, potrebbe valerne la pena separarlo in una nuova DLL se puoi.


Penso che il tuo secondo punto sia veramente ragionevole. La suddivisione in moduli dovrebbe aiutare i tempi di sviluppo / test e compilazione.
WM,
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.