Menu
CoddyTech

Dasar-Dasar Dependency Injection

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan C# di Coddy. Pelajaran 46 dari 70.

Dependency Injection (DI) adalah teknik saat sebuah class menerima dependensinya dari luar, bukan membuatnya sendiri. Dengan begitu, kodemu menjadi lebih fleksibel, mudah diuji, dan memiliki keterkaitan yang lebih longgar.

Tanpa DI, sebuah class membuat dependensinya sendiri, sehingga sulit diubah atau diuji:

public class OrderService
{
    private EmailSender sender = new EmailSender();  // Saling bergantung erat
    
    public void PlaceOrder() => sender.Send("Order placed");
}

Dengan DI, dependency diteruskan melalui constructor:

public interface IMessageSender
{
    void Send(string message);
}

public class EmailSender : IMessageSender
{
    public void Send(string message) => Console.WriteLine("Email: " + message);
}

public class OrderService
{
    private IMessageSender sender;
    
    public OrderService(IMessageSender sender)
    {
        this.sender = sender;
    }
    
    public void PlaceOrder() => sender.Send("Order placed");
}

Sekarang OrderService tidak tahu atau peduli apakah ia menggunakan email, SMS, atau pengirim mock untuk pengujian. Dependensi tersebut "diinjeksi" saat object dibuat:

IMessageSender emailSender = new EmailSender();
OrderService service = new OrderService(emailSender);
service.PlaceOrder();  // Email: Pesanan dibuat

Pola ini mengikuti prinsip bergantung pada abstraksi (interface), bukan implementasi konkret. Pola ini memungkinkan penggantian implementasi tanpa mengubah class yang menggunakannya, yang penting untuk pengujian unit dan mempertahankan arsitektur yang fleksibel.

challenge icon

Tantangan

Mudah

Mari kita bangun sistem pencatatan log yang menunjukkan keunggulan dependency injection. Alih-alih menetapkan secara langsung cara penulisan log, kamu akan membuat class Logger yang fleksibel dan dapat bekerja dengan tujuan pencatatan apa pun, konsol, simulasi file, atau lainnya, tanpa mengetahui detailnya.

Kamu akan mengatur kodemu dalam tiga file:

  • ILogWriter.cs: Definisikan interface bernama ILogWriter di namespace Logging. Interface ini mewakili kontrak untuk tujuan pencatatan log apa pun dan harus memiliki satu method Write(string message) yang mengembalikan string yang menjelaskan ke mana pesan ditulis.
  • LogWriters.cs: Buat dua implementasi konkret dari ILogWriter di namespace Logging:
    • ConsoleLogWriter, method Write-nya mengembalikan Console: {message}
    • FileLogWriter, menerima nama file melalui constructornya dan method Write-nya mengembalikan File[{filename}]: {message}
  • Logger.cs: Buat class Logger di namespace Logging yang menerima dependensinya melalui constructor injection. Logger harus:
    • Menerima ILogWriter melalui constructornya dan menyimpannya dalam field privat
    • Memiliki method Log(string message) yang meneruskan pemanggilan ke writer yang di-inject dan mengembalikan hasilnya
  • Program.cs: Tunjukkan dependency injection dengan membuat dua logger yang berbeda, satu dengan ConsoleLogWriter dan satu dengan FileLogWriter. Tunjukkan bagaimana class Logger yang sama berperilaku berbeda, bergantung pada dependensi yang di-inject.

Kamu akan menerima dua input:

  • Nama file untuk logger file
  • Pesan yang akan dicatat

Buat Logger dengan ConsoleLogWriter lalu catat pesannya. Kemudian buat Logger lain dengan FileLogWriter (menggunakan nama file dari input) lalu catat pesan yang sama. Cetak setiap hasil pada barisnya sendiri.

Contohnya, jika inputnya adalah app.log dan System started, outputnya akan seperti ini:

Console: System started
File[app.log]: System started

Perhatikan bahwa class Logger tidak pernah berubah, class ini bekerja dengan implementasi ILogWriter apa pun. Inilah inti dependency injection: Logger bergantung pada abstraksi (interface), dan implementasi konkretnya "disuntikkan" dari luar. Kamu dapat dengan mudah menambahkan DatabaseLogWriter atau CloudLogWriter nanti tanpa mengubah class Logger sama sekali!

Coba sendiri

using System;
using Logging;

class Program
{
    public static void Main(string[] args)
    {
        // Baca input
        string filename = Console.ReadLine();
        string message = Console.ReadLine();

        // TODO: Buat Logger dengan ConsoleLogWriter dan catat pesan tersebut
        // Cetak hasilnya

        // TODO: Buat Logger lain dengan FileLogWriter (menggunakan filename) dan catat pesan yang sama
        // Cetak hasilnya
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler C# online