Oke .. setelah semua diskusi saya mengubah pertanyaan saya sedikit untuk lebih mencerminkan contoh nyata yang saya hadapi.
Saya memiliki dua kelas ModelOne
dan ModelTwo
, kelas-kelas ini melakukan jenis fungsi yang serupa tetapi tidak saling berhubungan. Namun saya memiliki kelas ketiga CommonFunc
yang berisi beberapa fungsi publik yang diimplementasikan di keduanya ModelOne
dan ModelTwo
dan telah difaktorkan sesuai DRY
. Dua model ini dipakai di dalam ModelMain
kelas (yang itu sendiri adalah instantiated di tingkat yang lebih tinggi dll - tapi saya berhenti di tingkat ini).
Kontainer IoC yang saya gunakan adalah Microsoft Unity . Saya tidak berpura-pura menjadi ahli di dalamnya, tetapi pemahaman saya tentang hal itu adalah bahwa Anda mendaftarkan tuple antarmuka dan kelas dengan wadah dan ketika Anda menginginkan kelas konkret Anda meminta wadah IoC untuk objek apa pun yang cocok dengan antarmuka tertentu. Ini menyiratkan bahwa untuk setiap objek yang ingin saya instantiate dari Unity, harus ada antarmuka yang cocok. Karena setiap kelas saya melakukan fungsionalitas yang berbeda (dan -tidak tumpang tindih) ini berarti ada rasio 1: 1 antara antarmuka dan kelas 1 . Namun itu tidak berarti bahwa saya dengan kasar menulis sebuah antarmuka untuk setiap kelas yang saya tulis.
Jadi kode bijak saya berakhir dengan 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 { .. }
Pertanyaannya adalah bagaimana mengatur solusi saya. Haruskah saya menjaga kelas dan antarmuka bersama? Atau haruskah saya menjaga kelas dan antarmuka bersama? MISALNYA:
Opsi 1 - Diorganisasikan berdasarkan nama kelas
MySolution
|
|-MyProject
| |
|-Models
| |
|-Common
| |
| |-CommonFunc.cs
| |-ICommonFunc.cs
|
|-Main
| |
| |-IModelMain.cs
| |-ModelMain.cs
|
|-One
| |
| |-IModelOne.cs
| |-ModelOne.cs
|
|-Two
|
|-IModelTwo.cs
|-ModelTwo.cs
|
Opsi 2 - Diatur berdasarkan fungsionalitas (kebanyakan)
MySolution
|
|-MyProject
| |
|-Models
| |
|-Common
| |
| |-CommonFunc.cs
| |-ICommonFunc.cs
|
|-IModelMain.cs
|-IModelOne.cs
|-IModelTwo.cs
|-ModelMain.cs
|-ModelOne.cs
|-ModelTwo.cs
|
Opsi 3 - Memisahkan Antarmuka dan Implementasi
MySolution
|
|-MyProject
|
|-Interfaces
| |
| |-Models
| | |
| |-Common
| | |-ICommonFunc.cs
| |
| |-IModelMain.cs
| |-IModelOne.cs
| |-IModelTwo.cs
|
|-Classes
|
|-Models
| |
|-Common
| |-CommonFunc.cs
|
|-ModelMain.cs
|-ModelOne.cs
|-ModelTwo.cs
|
Opsi 4 - Mengambil contoh fungsionalitas lebih lanjut
MySolution
|
|-MyProject
| |
|-Models
| |
|-Components
| |
| |-Common
| | |
| | |-CommonFunc.cs
| | |-ICommonFunc.cs
| |
| |-IModelOne.cs
| |-IModelTwo.cs
| |-ModelOne.cs
| |-ModelTwo.cs
|
|-IModelMain.cs
|-ModelMain.cs
|
Saya agak tidak suka opsi 1 karena nama kelas di jalan. Tetapi karena saya cenderung rasio 1: 1 karena pilihan / penggunaan IoC saya (dan itu mungkin bisa diperdebatkan) ini memiliki keuntungan dalam melihat hubungan antara file.
Opsi 2 menarik bagi saya, tetapi sekarang saya telah mengeruhkan air antara ModelMain
dan sub-model.
Opsi 3 berfungsi untuk memisahkan definisi antarmuka dari implementasi, tetapi sekarang saya memiliki jeda buatan ini di nama path.
Opsi 4. Saya mengambil Opsi 2 dan men-tweak untuk memisahkan komponen dari model induk.
Adakah alasan yang baik untuk lebih memilih yang satu daripada yang lain? Atau kemungkinan tata letak lain yang saya lewatkan?
1. Frank membuat komentar yang memiliki rasio 1: 1 kembali ke C ++ hari dari file .h dan .cpp. Saya tahu dari mana dia berasal. Pemahaman saya tentang Persatuan tampaknya menempatkan saya pada sudut ini, tetapi saya juga tidak yakin bagaimana cara keluar darinya jika Anda juga mengikuti pepatah Program to an interface
Tapi itu diskusi untuk hari lain.
2. Saya telah meninggalkan detail masing-masing konstruktor objek. Di sinilah wadah IoC menyuntikkan objek sesuai kebutuhan.
Client1
membutuhkan IBase
, itu menyediakan Derived1
. Ketika Client2
membutuhkan IBase
, IoC menyediakan a Derived2
.
interface
. An interface
benar-benar hanya kelas abstrak dengan semua anggota virtual.