Senaryo: E-posta Gönderme İşlemi
Bir EmailService
sınıfımız olsun ve bu sınıf doğrudan bir somut sınıf olan SmtpClient
'a bağımlı olsun. Bu durumda, SmtpClient
'ı değiştirmek ya da farklı bir e-posta gönderme servisi eklemek istediğimizde, EmailService
sınıfında değişiklik yapmak zorunda kalırız.
1. DIP'yi İhlal Eden Durum (Sıkı Bağlantı)
public class EmailService
{
private SmtpClient _smtpClient;
public EmailService()
{
_smtpClient = new SmtpClient(); // Direkt olarak SmtpClient'a bağlı.
}
public void SendEmail(string to, string subject, string body)
{
_smtpClient.Send(to, subject, body);
}
}
public class SmtpClient
{
public void Send(string to, string subject, string body)
{
Console.WriteLine($"E-posta gönderildi: {to}, {subject}, {body}");
}
}
Sıkı Bağlantı Sorunu:
Şu anki yapımızda, EmailService
sınıfı doğrudan SmtpClient
sınıfına bağlıdır. Bu durumda, EmailService
'in işlevselliğini değiştirmek istesek (örneğin, e-posta gönderme yöntemini değiştirmek veya başka bir e-posta servisi kullanmak gibi), EmailService
sınıfında mutlaka değişiklik yapmamız gerekir.
Diyelim ki, yeni bir SendGridEmailClient eklemek istiyoruz ve EmailService
'in SmtpClient
'a olan bağımlılığını değiştirmemiz gerekiyor.
2. Değişiklik Yapma Zorunluluğu (Bağımlılıklar Sıkıdır)
Eğer EmailService
doğrudan SmtpClient
'a bağlıysa ve biz SendGrid kullanmaya karar verirsek, o zaman EmailService
sınıfını değiştirmemiz gerekecek.
public class SendGridEmailClient
{
public void Send(string to, string subject, string body)
{
Console.WriteLine($"E-posta gönderildi (SendGrid): {to}, {subject}, {body}");
}
}
public class EmailService
{
private SendGridEmailClient _sendGridEmailClient;
public EmailService()
{
_sendGridEmailClient = new SendGridEmailClient(); // SendGrid'e geçiş yapıyoruz.
}
public void SendEmail(string to, string subject, string body)
{
_sendGridEmailClient.Send(to, subject, body);
}
}
Değişiklikler:
-
EmailService
'i değiştirmek zorunda kaldık çünküSmtpClient
'a olan bağımlılığı doğrudan yerleştirmiştik. - Ayrıca
EmailService
'i test etmek ya da başka bir servise entegre etmek için bu tür bağımlılıkları değiştirmeniz gerekecek.
3. DIP'yi Uygulayan Durum (Esnek ve Soyutlamalı)
Eğer DIP'yi uygularsak, EmailService
sadece bir soyutlama olan IEmailClient
'e bağlı olur ve somut sınıflar (SmtpClient
, SendGridEmailClient
) daha esnek bir şekilde değiştirilebilir.
public interface IEmailClient
{
void Send(string to, string subject, string body);
}
public class SmtpEmailClient : IEmailClient
{
public void Send(string to, string subject, string body)
{
Console.WriteLine($"E-posta gönderildi (SMTP): {to}, {subject}, {body}");
}
}
public class SendGridEmailClient : IEmailClient
{
public void Send(string to, string subject, string body)
{
Console.WriteLine($"E-posta gönderildi (SendGrid): {to}, {subject}, {body}");
}
}
public class EmailService
{
private readonly IEmailClient _emailClient;
// Dependency Injection ile bağımlılık ekleniyor.
public EmailService(IEmailClient emailClient)
{
_emailClient = emailClient;
}
public void SendEmail(string to, string subject, string body)
{
_emailClient.Send(to, subject, body);
}
}
Esneklik Kazanma:
- Şimdi,
EmailService
sınıfı sadece soyutlama olanIEmailClient
'a bağlıdır. -
EmailService
'i değiştirmek zorunda kalmadan, farklı bir e-posta servis sağlayıcısı kullanabiliriz. MeselaSendGridEmailClient
veyaSmtpEmailClient
gibi servisleri sadeceIEmailClient
'i implement eden sınıfları sağlayarak değiştirebiliriz.
public class Program
{
public static void Main()
{
IEmailClient emailClient = new SendGridEmailClient(); // Ya da SmtpEmailClient
var emailService = new EmailService(emailClient);
emailService.SendEmail("test@example.com", "Konu", "E-posta içeriği");
}
}
Sonuç:
DIP'yi ihlal ettiğimizde,
EmailService
sınıfını değiştirmek zorunda kalırız çünkü doğrudan somut sınıfa bağımlıdır. Yeni bir e-posta servisi eklediğimizde, bu servisin işlevini değiştirebilmek içinEmailService
'i de güncellememiz gerekir.DIP'yi uyguladığımızda, soyutlamalar sayesinde
EmailService
sınıfını değiştirmeden yeni bir e-posta servisi ekleyebiliriz. Yüksek seviye modüller (iş mantığı) ve düşük seviye modüller (somut sınıflar) arasında bağımlılık yoktur, sadece soyutlama üzerinden iletişim vardır. Bu da daha esnek ve bakım kolaylığı sağlar.
Bu şekilde, bağımlılıkların sıkı olduğu durumlarda, değişiklik yaparken diğer sınıflarda da değişiklik yapmanız kaçınılmaz hale gelir. DIP, bu tür sorunları önleyerek yazılımın daha sürdürülebilir ve esnek olmasını sağlar.