OK .. po całej dyskusji zmieniam nieco moje pytanie, aby lepiej odzwierciedlić konkretny przykład, z którym mam do czynienia.
Mam dwie klasy ModelOne
i klasy ModelTwo
te wykonują podobny typ funkcjonalności, ale nie są ze sobą powiązane. Mam jednak trzecią klasę, CommonFunc
która zawiera pewną funkcjonalność publiczną, która jest zaimplementowana zarówno ModelOne
i ModelTwo
została uwzględniona zgodnie z DRY
. Dwa modele są tworzone w obrębie ModelMain
klasy (która sama tworzy się na wyższym poziomie itp. - ale zatrzymuję się na tym poziomie).
Kontener IoC, którego używam, to Microsoft Unity . Nie udaję, że jestem w tym ekspertem, ale rozumiem, że rejestrujesz krotkę interfejsu i klasy w kontenerze, a kiedy chcesz konkretnej klasy, pytasz kontener IoC o dowolny obiekt pasujący do określonego interfejsu. Oznacza to, że dla każdego obiektu, który chcę utworzyć z Unity, musi istnieć pasujący interfejs. Ponieważ każda z moich klas wykonuje inną (i nie nakładającą się) funkcjonalność, oznacza to, że istnieje stosunek 1: 1 między interfejsem a klasą 1 . Nie oznacza to jednak, że niewolniczo piszę interfejs dla każdej klasy, którą piszę.
Zatem pod względem kodu kończę na 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 { .. }
Pytanie dotyczy tego, jak zorganizować moje rozwiązanie. Czy powinienem trzymać klasę i interfejs razem? Czy powinienem trzymać klasy i interfejsy razem? NA PRZYKŁAD:
Opcja 1 - zorganizowane według nazwy klasy
MySolution
|
|-MyProject
| |
|-Models
| |
|-Common
| |
| |-CommonFunc.cs
| |-ICommonFunc.cs
|
|-Main
| |
| |-IModelMain.cs
| |-ModelMain.cs
|
|-One
| |
| |-IModelOne.cs
| |-ModelOne.cs
|
|-Two
|
|-IModelTwo.cs
|-ModelTwo.cs
|
Opcja 2 - uporządkowane według funkcjonalności (głównie)
MySolution
|
|-MyProject
| |
|-Models
| |
|-Common
| |
| |-CommonFunc.cs
| |-ICommonFunc.cs
|
|-IModelMain.cs
|-IModelOne.cs
|-IModelTwo.cs
|-ModelMain.cs
|-ModelOne.cs
|-ModelTwo.cs
|
Opcja 3 - Interfejs oddzielający i implementacja
MySolution
|
|-MyProject
|
|-Interfaces
| |
| |-Models
| | |
| |-Common
| | |-ICommonFunc.cs
| |
| |-IModelMain.cs
| |-IModelOne.cs
| |-IModelTwo.cs
|
|-Classes
|
|-Models
| |
|-Common
| |-CommonFunc.cs
|
|-ModelMain.cs
|-ModelOne.cs
|-ModelTwo.cs
|
Opcja 4 - Dalszy przykład funkcjonalności
MySolution
|
|-MyProject
| |
|-Models
| |
|-Components
| |
| |-Common
| | |
| | |-CommonFunc.cs
| | |-ICommonFunc.cs
| |
| |-IModelOne.cs
| |-IModelTwo.cs
| |-ModelOne.cs
| |-ModelTwo.cs
|
|-IModelMain.cs
|-ModelMain.cs
|
Nie podoba mi się opcja 1 z powodu nazwy klasy na ścieżce. Ale ponieważ mam tendencję do stosunku 1: 1 ze względu na mój wybór / użycie IoC (i to może być dyskusyjne), ma to zaletę w widzeniu związku między plikami.
Opcja 2 jest dla mnie atrakcyjna, ale teraz zamazałem wody między podmodelami ModelMain
a nimi.
Opcja 3 działa w celu oddzielenia definicji interfejsu od implementacji, ale teraz mam te sztuczne przerwy w nazwach ścieżek.
Opcja 4. Wziąłem opcję 2 i poprawiłem ją, aby oddzielić komponenty od modelu nadrzędnego.
Czy istnieje dobry powód, aby preferować jeden od drugiego? Lub jakieś inne potencjalne układy, które przegapiłem?
1. Frank skomentował, że stosunek 1: 1 nawiązuje do dni C ++ plików .h i .cpp. Wiem skąd on pochodzi. Moje rozumienie Jedności wydaje się wprowadzać mnie w ten kąt, ale nie jestem nawet pewien, jak się z tego wydostać, jeśli również postępujesz zgodnie z przysłowiem Program to an interface
Ale to dyskusja na inny dzień.
2. Pominąłem szczegóły każdego konstruktora obiektów. Tutaj kontener IoC wstrzykuje obiekty zgodnie z wymaganiami.
Client1
trzeba IBase
, zapewnia Derived1
. W razie Client2
potrzeby IBase
IoC zapewnia Derived2
.
interface
. interface
Jest naprawdę klasą abstrakcyjną ze wszystkimi członkami wirtualnych.