Saya ingin memastikan bahwa saya memahami konsep injeksi ketergantungan (DI). Yah, saya benar-benar mengerti konsepnya, DI tidak rumit: Anda membuat antarmuka lalu melewati implementasi antarmuka saya ke kelas yang menggunakannya. Cara umum untuk melewatinya adalah dengan konstruktor tetapi Anda juga dapat melewatinya dengan setter atau metode lain.
Yang saya tidak yakin untuk mengerti adalah kapan harus menggunakan DI.
Penggunaan 1: Tentu saja menggunakan DI jika Anda memiliki beberapa implementasi antarmuka Anda tampaknya logis. Anda memiliki repositori untuk SQL Server Anda kemudian yang lain untuk database Oracle Anda. Keduanya berbagi antarmuka yang sama dan Anda "menyuntikkan" (ini adalah istilah yang digunakan) yang Anda inginkan saat runtime. Ini bahkan bukan DI, ini adalah pemrograman OO dasar di sini.
Penggunaan 2: Ketika Anda memiliki lapisan bisnis dengan banyak layanan dengan semua metode spesifiknya, praktik terbaiknya adalah membuat antarmuka untuk setiap layanan dan juga menyuntikkan implementasinya walaupun ini unik. Karena ini lebih baik untuk pemeliharaan. Ini penggunaan kedua yang tidak saya mengerti.
Saya memiliki sekitar 50 kelas bisnis. Tidak ada yang umum di antara mereka. Beberapa repositori mendapatkan atau menyimpan data dalam 3 database berbeda. Beberapa membaca atau menulis file. Beberapa melakukan tindakan bisnis murni. Ada juga validator dan pembantu khusus. Tantangannya adalah manajemen memori karena beberapa kelas dipasang dari lokasi yang berbeda. Validator dapat memanggil beberapa repositori dan validator lain yang dapat memanggil repositori yang sama lagi.
Contoh: Lapisan bisnis
public class SiteService : Service, ICrud<Site>
{
public Site Read(Item item, Site site)
{
return beper4DbContext.Site
.AsNoTracking()
.SingleOrDefault(y => y.SiteId == site.Id && y.ItemId == item.Id)
}
public Site Read(string itemCode, string siteCode)
{
using (var itemService = new ItemService())
{
var item = itemService.Read(itemCode);
return Read(item, site);
}
}
}
public class ItemSiteService : Service, ICrud<Site>
{
public ItemSite Read(Item item, Site site)
{
return beper4DbContext.ItemSite
.AsNoTracking()
.SingleOrDefault(y => y.SiteId == site.Id && y.ItemId == item.Id)
}
public ItemSite Read(string itemCode, string siteCode)
{
using (var itemService = new ItemService())
using (var siteService = new SiteService())
{
var item = itemService.Read(itemCode);
var site = siteService.Read(itemCode, siteCode);
return Read(item, site);
}
}
}
Pengendali
public class ItemSiteController : BaseController
{
[Route("api/Item/{itemCode}/ItemSite/{siteCode}")]
public IHttpActionResult Get(string itemCode, string siteCode)
{
using (var service = new ItemSiteService())
{
var itemSite = service.Read(itemCode, siteCode);
return Ok(itemSite);
}
}
}
Contoh ini sangat mendasar tetapi Anda melihat bagaimana saya dapat dengan mudah membuat 2 instance itemService untuk mendapatkan itemSite. Kemudian juga setiap layanan datang dengan konteks DB-nya. Jadi panggilan ini akan membuat 3 DbContext. 3 Koneksi.
Ide pertama saya adalah membuat singleton untuk menulis ulang semua kode ini seperti di bawah. Kode lebih mudah dibaca dan yang paling penting sistem singleton hanya membuat satu instance dari setiap layanan yang digunakan dan membuatnya pada panggilan pertama. Sempurna, kecuali saya masih memiliki konteks berbeda tetapi saya dapat melakukan sistem yang sama untuk konteks saya. Sudah selesai.
Lapisan bisnis
public class SiteService : Service, ICrud<Site>
{
public Site Read(Item item, Site site)
{
return beper4DbContext.Site
.AsNoTracking()
.SingleOrDefault(y => y.SiteId == site.Id && y.ItemId == item.Id)
}
public Site Read(string itemCode, string siteCode)
{
var item = ItemService.Instance.Read(itemCode);
return Read(item, site);
}
}
public class ItemSiteService : Service, ICrud<Site>
{
public ItemSite Read(Item item, Site site)
{
return beper4DbContext.ItemSite
.AsNoTracking()
.SingleOrDefault(y => y.SiteId == site.Id && y.ItemId == item.Id)
}
public ItemSite Read(string itemCode, string siteCode)
{
var item = ItemService.Instance.Read(itemCode);
var site = SiteService.Instance.Read(itemCode, siteCode);
return Read(item, site);
}
}
Pengendali
public class ItemSiteController : BaseController
{
[Route("api/Item/{itemCode}/ItemSite/{siteCode}")]
public IHttpActionResult Get(string itemCode, string siteCode)
{
var itemSite = service.Instance.Read(itemCode, siteCode);
return Ok(itemSite);
}
}
Beberapa orang mengatakan kepada saya sesuai dengan praktik yang baik saya harus menggunakan DI dengan contoh tunggal dan menggunakan singleton adalah praktik yang buruk. Saya harus membuat antarmuka untuk setiap kelas bisnis dan instantiate dengan bantuan wadah DI. Betulkah? DI ini menyederhanakan kode saya. Sulit untuk dipercaya.