Гаразд .. після усієї дискусії я трохи змінюю своє питання, щоб краще відобразити конкретний приклад, з яким я маю справу.
У мене є два класи, ModelOne
і ModelTwo
ці класи виконують аналогічні функції, але не пов'язані між собою. Однак у мене є третій клас, CommonFunc
який містить деяку публічну функціональність, яка реалізована в обох, ModelOne
і ModelTwo
розроблена як відповідно DRY
. Дві моделі є примірниками в межах ModelMain
класу (який сам інстанціюється на більш високому рівні і т. Д. - але я зупиняюся на цьому рівні).
Контейнер IoC, який я використовую, - це Microsoft Unity . Я не претендую на те, що я є експертом у цьому, але я розумію, що ви реєструєте кордон інтерфейсу та класу з контейнером, і коли вам потрібно конкретний клас, ви запитаєте контейнер IoC про те, що об'єкт відповідає конкретному інтерфейсу. Це означає, що для кожного об'єкта, який я хочу створити з Unity, повинен бути відповідний інтерфейс. Оскільки кожен з моїх занять виконує різні (і не перекриваються) функціональні можливості, це означає, що між інтерфейсом та класом 1 існує співвідношення 1: 1 . Однак це не означає, що я по-рабськи пишу інтерфейс для кожного класу, який я пишу.
Таким чином, код мудрий я закінчую з 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 { .. }
Питання полягає в тому, як організувати своє рішення. Чи слід тримати клас та інтерфейс разом? Або я повинен тримати класи та інтерфейси разом? EG:
Варіант 1 - Організоване за назвою класу
MySolution
|
|-MyProject
| |
|-Models
| |
|-Common
| |
| |-CommonFunc.cs
| |-ICommonFunc.cs
|
|-Main
| |
| |-IModelMain.cs
| |-ModelMain.cs
|
|-One
| |
| |-IModelOne.cs
| |-ModelOne.cs
|
|-Two
|
|-IModelTwo.cs
|-ModelTwo.cs
|
Варіант 2 - Організований за функціональністю (в основному)
MySolution
|
|-MyProject
| |
|-Models
| |
|-Common
| |
| |-CommonFunc.cs
| |-ICommonFunc.cs
|
|-IModelMain.cs
|-IModelOne.cs
|-IModelTwo.cs
|-ModelMain.cs
|-ModelOne.cs
|-ModelTwo.cs
|
Варіант 3 - роздільний інтерфейс та реалізація
MySolution
|
|-MyProject
|
|-Interfaces
| |
| |-Models
| | |
| |-Common
| | |-ICommonFunc.cs
| |
| |-IModelMain.cs
| |-IModelOne.cs
| |-IModelTwo.cs
|
|-Classes
|
|-Models
| |
|-Common
| |-CommonFunc.cs
|
|-ModelMain.cs
|-ModelOne.cs
|-ModelTwo.cs
|
Варіант 4 - Додавання додаткового прикладу функціональності
MySolution
|
|-MyProject
| |
|-Models
| |
|-Components
| |
| |-Common
| | |
| | |-CommonFunc.cs
| | |-ICommonFunc.cs
| |
| |-IModelOne.cs
| |-IModelTwo.cs
| |-ModelOne.cs
| |-ModelTwo.cs
|
|-IModelMain.cs
|-ModelMain.cs
|
Мені не подобається варіант 1 через назву класу на шляху. Але оскільки я прагну до співвідношення 1: 1 через свій вибір / використання IoC (і це може бути дискусійним), це має переваги в баченні зв’язку між файлами.
Варіант 2 мені подобається, але зараз я затуманив води між ModelMain
та підмоделями.
Варіант 3 працює на відокремлення визначення інтерфейсу від реалізації, але тепер у мене є ці штучні перерви в назвах шляхів.
Варіант 4. Я взяв варіант 2 і змінив його, щоб відокремити компоненти від батьківської моделі.
Чи є вагомі причини для того, щоб віддавати перевагу одному перед іншим? Або будь-які інші потенційні макети, які я пропустив?
1. Френк прокоментував, що співвідношення 1: 1 повертається до C ++ днів файлів .h та .cpp. Я знаю, звідки він родом. Моє розуміння Єдності, здається, поставило мене в цей кут, але я також не впевнений, навіть як вийти з нього, якщо ви також слідкуєте за прислів’ям Program to an interface
Але це дискусія ще один день.
2. Я покинув деталі кожного конструктора об'єктів. Тут контейнер IoC вводить об'єкти за потребою.
Client1
потребує IBase
, він надає Derived1
. Коли Client2
потребує IBase
, IoC надає Derived2
.
interface
. interface
Дійсно просто абстрактний клас з усіма віртуальними членами.