OK .. dopo tutta la discussione sto cambiando leggermente la mia domanda per riflettere meglio un esempio concreto di cui mi sto occupando.
Ho due classi ModelOne
e ModelTwo
, Queste classi eseguono un tipo simile di funzionalità ma non sono correlate tra loro. Tuttavia, ho una terza classe CommonFunc
che contiene alcune funzionalità pubbliche implementate sia in ModelOne
che in ModelTwo
e sono state scomposte per DRY
. I due modelli sono istanziati all'interno della classe ModelMain
(che a sua volta è istanziata a un livello superiore ecc. - ma mi fermo a questo livello).
Il contenitore IoC che sto utilizzando è Microsoft Unity . Non pretendo di essere un esperto in questo, ma la mia comprensione di questo è che si registra una tupla di interfaccia e classe con il contenitore e quando si desidera una classe concreta si chiede al contenitore IoC qualsiasi oggetto corrisponda a un'interfaccia specifica. Ciò implica che per ogni oggetto che voglio istanziare da Unity, ci deve essere un'interfaccia di corrispondenza. Poiché ciascuna delle mie classi esegue funzionalità diverse (e non sovrapposte), ciò significa che esiste un rapporto 1: 1 tra l'interfaccia e la classe 1 . Comunque non significa che sto scrivendo pedissequamente un'interfaccia per ogni classe che scrivo.
Quindi il codice saggio finirà con 2 :
public interface ICommonFunc
{
}
public interface IModelOne
{
ICommonFunc Common { get; }
..
}
public interface IModelTwo
{
ICommonFunc Common { get; }
..
}
public interface IModelMain
{
IModelOne One { get; }
IModelTwo Two { get; }
..
}
public class CommonFunc : ICommonFunc { .. }
public class ModelOne : IModelOne { .. }
public class ModelTwo : IModelTwo { .. }
public class ModelMain : IModelMain { .. }
La domanda riguarda come organizzare la mia soluzione. Devo tenere insieme la classe e l'interfaccia? O dovrei tenere insieme le classi e le interfacce? EG:
Opzione 1 : organizzata per nome della classe
MySolution
|
|-MyProject
| |
|-Models
| |
|-Common
| |
| |-CommonFunc.cs
| |-ICommonFunc.cs
|
|-Main
| |
| |-IModelMain.cs
| |-ModelMain.cs
|
|-One
| |
| |-IModelOne.cs
| |-ModelOne.cs
|
|-Two
|
|-IModelTwo.cs
|-ModelTwo.cs
|
Opzione 2 - Organizzato per funzionalità (principalmente)
MySolution
|
|-MyProject
| |
|-Models
| |
|-Common
| |
| |-CommonFunc.cs
| |-ICommonFunc.cs
|
|-IModelMain.cs
|-IModelOne.cs
|-IModelTwo.cs
|-ModelMain.cs
|-ModelOne.cs
|-ModelTwo.cs
|
Opzione 3 - Interfaccia e implementazione sepa- ratrice
MySolution
|
|-MyProject
|
|-Interfaces
| |
| |-Models
| | |
| |-Common
| | |-ICommonFunc.cs
| |
| |-IModelMain.cs
| |-IModelOne.cs
| |-IModelTwo.cs
|
|-Classes
|
|-Models
| |
|-Common
| |-CommonFunc.cs
|
|-ModelMain.cs
|-ModelOne.cs
|-ModelTwo.cs
|
Opzione 4 - Prendendo ulteriormente l'esempio di funzionalità
MySolution
|
|-MyProject
| |
|-Models
| |
|-Components
| |
| |-Common
| | |
| | |-CommonFunc.cs
| | |-ICommonFunc.cs
| |
| |-IModelOne.cs
| |-IModelTwo.cs
| |-ModelOne.cs
| |-ModelTwo.cs
|
|-IModelMain.cs
|-ModelMain.cs
|
Ho una sorta di antipatia opzione 1 a causa del nome della classe nel percorso. Ma dato che ho un rapporto 1: 1 a causa della mia scelta / utilizzo IoC (e che può essere discutibile) questo ha dei vantaggi nel vedere la relazione tra i file.
L'opzione 2 mi piace, ma ora ho confuso le acque tra ModelMain
e sotto-modelli.
L'opzione 3 funziona per separare la definizione dell'interfaccia dall'implementazione, ma ora ho queste interruzioni artificiali nei nomi dei percorsi.
Opzione 4. Ho preso l'Opzione 2 e l'ho ottimizzata per separare i componenti dal modello principale.
C'è una buona ragione per preferire uno rispetto all'altro? O qualsiasi altro potenziale layout che mi è sfuggito?
1. Frank ha fatto un commento sul fatto che il rapporto 1: 1 si riferisce ai giorni C ++ di file .h e .cpp. So da dove viene. La mia comprensione dell'Unità sembra mettermi in questo angolo, ma non sono nemmeno sicuro di come uscirne se si segue anche l'adagio di Program to an interface
Ma questa è una discussione per un altro giorno.
2. Ho omesso i dettagli di ogni costruttore di oggetti. È qui che il contenitore IoC inietta gli oggetti come richiesto.