KEMBALI KE DASAR

Rahasia Prinsip Tanggung Jawab Tunggal

Temukan rahasia tentang Prinsip Tanggung Jawab Tunggal (SRP) dari Prinsip SOLID.

Hampir semua pengembang yang bekerja dengan bahasa Pemrograman Berorientasi Objek (OOP) mengetahui prinsip SOLID.

Prinsip PADAT

  • SPrinsip Tanggung Jawab Tunggal
  • Prinsip Open-tertutup
  • L Prinsip Substitusi iskov
  • Sayamenghadapi Prinsip Segregasi
  • DPrinsip Pembalikan ketergantungan

Dalam artikel ini, kami akan menjelaskan S dari SOLID, Prinsip Tanggung Jawab Tunggal, namun apa yang akan Anda baca di sini berbeda…



Apa yang dimaksud dengan Prinsip Tanggung Jawab Tunggal

Menurut Wikipedia:

Istilah ini diperkenalkan oleh Robert C. Martin dalam artikelnya “The Principles of OOD” sebagai bagian dari Principles of Object Oriented Design, yang dipopulerkan oleh bukunya tahun 2003 Agile Software Development, Prinsip, Pola, dan Praktek.

Martin mendeskripsikannya berdasarkan prinsip kohesi, seperti dijelaskan oleh Tom DeMarco dalam bukunya Analisis Terstruktur dan Spesifikasi Sistem, dan Meilir Page-Jones dalam Panduan Praktis untuk Desain Sistem Terstruktur.

Pada tahun 2014 Martin menerbitkan postingan blog berjudul “Prinsip Tanggung Jawab Tunggal” dengan tujuan untuk memperjelas apa yang dimaksud dengan frasa “alasan perubahan”.

Dan artinya:

Robert C. Martin mengungkapkan prinsip tersebut sebagai, “Sebuah kelas seharusnya hanya memiliki satu alasan untuk berubah”. Karena kebingungan seputar kata “akal” dia juga mengklarifikasi dengan mengatakan bahwa “prinsip adalah tentang manusia.” Dalam beberapa pembicaraannya, ia juga berpendapat bahwa prinsip tersebut khususnya mengenai peran atau aktor.

Misalnya, meskipun mereka adalah orang yang sama, peran akuntan berbeda dengan administrator database. Oleh karena itu, setiap modul harus bertanggung jawab atas setiap peran.

Jadi sekarang cukup dengan pembicaraan di Wikipedia, mari kita perjelas beberapa poin.

Definisi utama Prinsip Tanggung Jawab Tunggal adalah bahwa suatu kelas hanya boleh memiliki satu alasan untuk berubah.

Orang mungkin bingung tentang apa yang dimaksud dengan alasan dan saya sangat mengerti dari mana asalnya.

Izinkan saya menjelaskannya…

Catatan penting

Untuk mengarahkan fokus Anda ke topik utama yang sedang kita diskusikan di sini, beberapa praktik terbaik kode akan dihilangkan. Ini berarti lebih sedikit antarmuka, abstraksi, konstruktor implementasi,… kecuali diperlukan untuk demonstrasi.

Kebingungan

Beberapa pengembang cenderung mengatakan bahwa jika suatu kelas melakukan terlalu banyak hal, hal itu sebenarnya melanggar Prinsip Tanggung Jawab Tunggal.

Bagus, tapi tetap saja, apa yang dimaksud dengan terlalu banyak? Bagaimana cara mengetahui apakah suatu kelas melakukan terlalu banyak hal atau tidak? Jika suatu kelas melakukan 2 hal, apakah ini terlalu banyak? Bagaimana dengan 3? Bagaimana dengan 4? …

Menurut pendapat saya, menurut saya definisi ini membingungkan dan saya tidak dapat menyalahkan Anda jika Anda merasakan hal yang sama. Istilah “terlalu banyak” tidak dapat diukur atau dimengerti.

Saya dapat mendengar Anda sekarang berkata:

Lalu bagaimana, apakah kita sepakat bahwa tidak ada istilah yang tepat untuk menggambarkan Prinsip Tanggung Jawab Tunggal? Haruskah kita menjatuhkannya saja?

Sebenarnya tidak. Saya memiliki sesuatu yang dapat membuatnya lebih jelas, jadi izinkan saya menjelaskannya lebih lanjut.

Dalam perangkat lunak, suatu metode -atau suatu fungsi, apa pun sebutannya- memiliki dua faktor untuk mendeskripsikannya:

  • Pengetahuan diperlukan untuk melakukan tugasnya.
  • Pencapaian selesai setelah selesai.

Kedua faktor ini berbeda, tidak sama. Kita harus membedakan satu sama lain karena ada banyak konsekuensi berdasarkan skala masing-masing konsekuensi tersebut.

Sekarang, izinkan saya memandu Anda langkah demi langkah.

Pengetahuan Metode

Mengacu pada pengetahuan yang dibutuhkan metode agar dapat melakukan tugasnya. Dengan kata lain, ini mengacu pada detail internal dan langkah-langkah yang perlu diketahui metode agar dapat menyelesaikan tugasnya.

Sebagai contoh, mari kita lihat metode ini:

public int Add(int a, int b)
{
  return a + b;
}

Metode Add harus mengetahui cara menjumlahkan dua angka. Ia melakukannya dengan menggunakan operator + yang disediakan oleh .NET Framework.

Sekarang, jika pengembang .NET Framework memutuskan untuk mengubah implementasi internal operator + atau cara menerjemahkannya pada tingkat kode mesin, hal ini tidak akan memengaruhi metode Add karena tidak peduli. Itu hanya mendelegasikan metodologi menambahkan dua bilangan bulat ke .NET Framework.

Sekarang, mari kita asumsikan bahwa persyaratan sistem yang kita kembangkan diubah sehingga kita perlu menambahkan margin tambahan pada metode Add.

Jadi, kodenya harus seperti berikut:

private const int Margin = 10;

public int Add(int a, int b)
{
  return a + b + Margin;
}

Sekarang, ini berbeda.

Setelah penerapan metode Add yang baru ini, pengetahuan tentang metode itu sendiri telah berubah, dan pengetahuan telah berubah karena sekarang metode tersebut perlu mengetahui tentang penambahan margin ekstra yang sebelumnya tidak ada.

Metode Pencapaian

Mengacu pada pekerjaan yang akan dilakukan ketika metode selesai, terlepas dari apakah metode tersebut memiliki pengetahuan mutlak dalam setiap langkah pekerjaan ini atau tidak.

Sebagai contoh, mari kita lihat metode ini:

public class EmployeeManager
{
  private readonly EmployeeRepository _mEmployeeRepository;
  private readonly TaxCalculator _mTaxCalculator;
  private readonly MailingGroupsManager _mMailingGroupsManager;
  private readonly HolidaysCalculator _mHolidaysCalculator;

  public async Task<Employee> HireEmployee(Employee employee)
  {
    // Add Employee entry with basic info in DB
    var updatedEmployee = await _mEmployeeRepository.Add(employee);
    
    // Add Emplyee to mailing groups
    updatedEmployee = await _mMailingGroupsManager.Add(updatedEmployee);
    
    // Calculate tax scheme
    decimal tax = await _mTaxCalculator.Calculate(updatedEmployee);
    
    // Update tax scheme in DB
    updatedEmployee = await _mEmployeeRepository.UpdateTax(updatedEmployee, tax);
    
    // Calculate holidays
    byte holidaysCount = await _mHolidaysCalculator.Calculate(updatedEmployee);
    
    // Update holidays in DB
    return await _mEmployeeRepository.UpdateHolidays(updatedEmployee, holidaysCount);
  }
}

Seperti yang bisa kita lihat di sini, jumlah pekerjaan yang akan dicapai setelah metode ini selesai akan sangat besar. Namun, bisakah kita mengatakan hal yang sama mengenai pengetahuan? Saya kira tidak demikian…

Satu-satunya pengetahuan yang dimiliki metode ini adalah pengetahuan tentang langkah-langkah dan urutan tindakan yang diperlukan untuk mendapatkan Employee dipekerjakan, tidak lebih.

Anda mungkin berpendapat bahwa metode ini mengetahui lebih dari itu tetapi sebenarnya tidak. Ya, ketika metode HireEmployee dimulai, seorang karyawan akan ditambahkan ke database, tetapi sebenarnya, ia tidak tahu bagaimana hal ini dilakukan, metode Add dari kelas EmployeeRepository adalah yang memiliki pengetahuan ini.

Hal yang sama berlaku untuk semua metode lainnya dan ini membuat metode HireEmployee lebih sederhana dari apa yang kita harapkan sebelum menyadarinya, bukan?

Oleh karena itu, sekarang mari kita menganalisis bagaimana kedua faktor ini dapat berdampak pada definisi Prinsip Tanggung Jawab Tunggal.

Saat ini, sudah jelas bahwa ketika kita mengevaluasi apakah suatu kelas mematuhi Prinsip Tanggung Jawab Tunggal atau tidak, kita harus lebih mementingkan pengetahuan daripada pencapaiannya.

Hal ini karena semakin banyak pengetahuan yang dimiliki suatu kelas, semakin besar kemungkinan kelas tersebut melanggar Prinsip Tanggung Jawab Tunggal.

Biarkan saya menjelaskan lebih lanjut…

Momen Kebenaran

Apakah Anda ingat kelas EmployeeManager yang kita bahas di atas, katakanlah kita menerapkannya secara berbeda.

Anggap saja kodenya adalah sebagai berikut:

public class EmployeeManager
{
  public async Task<Employee> HireEmployee(Employee employee)
  {
    // Add Employee entry with basic info in DB
    // Assume that here we are actually doing the following:
    // 1. Open a connection to the database
    // 2. Build a SQL query to insert records in the database
    // 3. Execute the query
    // 4. Close connection
    
    // Add Emplyee to mailing groups
    // Assume that here we are actually doing the following:
    // 1. Open a connection to the mailing server
    // 3. Do whatever needed to add records to the mailing groups
    // 4. Close connection
    
    // Calculate tax scheme
    // Assume that here we are actually doing the following:
    // 1. Do the mathematical operations required
    
    // Update tax scheme in DB
    // Assume that here we are actually doing the following:
    // 1. Open a connection to the database
    // 2. Build a SQL query to insert records in the database
    // 3. Execute the query
    // 4. Close connection
    
    // Calculate holidays
    // Assume that here we are actually doing the following:
    // 1. Do the mathematical operations required
    
    // Update holidays in DB
    // Assume that here we are actually doing the following:
    // 1. Open a connection to the database
    // 2. Build a SQL query to insert records in the database
    // 3. Execute the query
    // 4. Close connection
  }
}

Seperti yang bisa kita lihat di sini, pengetahuan yang dibutuhkan sangat besar. Metode HireEmployee perlu mengetahui banyak hal tentang struktur database, cara membuka/menutup koneksi, cara melakukan operasi matematika untuk menghitung pajak dan hari libur, cara menghubungkan/memutuskan sambungan ke/dari server surat, cara menambahkan ke grup surat,…

Pengetahuan yang sangat besar seperti ini merupakan beban yang ditanggung oleh metode HireEmployee.

Jika perubahan baru diterapkan pada tabel database Employee atau tabel terkait lainnya, metode HireEmployee perlu diperbarui dan ini berarti kelas EmployeeManager juga akan diperbarui.

Jika perubahan baru diterapkan pada server surat, metode HireEmployee perlu diperbarui dan ini berarti kelas EmployeeManager juga akan diperbarui.

Dan seterusnya…

Pada akhirnya, kita dapat menyimpulkan bahwa kelas EmployeeManager akan memiliki terlalu banyak alasan untuk berubah yang merupakan indikasi jelas bahwa kelas tersebut melanggar Prinsip Tanggung Jawab Tunggal.

Sekarang saya dapat mendengar Anda berkata:

Oke, sekarang saya mengerti tetapi saya masih belum tahu cara memperbaikinya. Apa itu mungkin?

Ya, tentu saja itu mungkin. Mari ku tunjukkan…

Cara yang lebih baik

Sekali lagi, kembali ke kelas EmployeeManager. Jika kita ingin menerapkannya dengan benar agar mematuhi Prinsip Tanggung Jawab Tunggal, kita dapat mengikuti beberapa langkah seperti yang saya tunjukkan.

Pertama, kita perlu kembali ke versi yang lebih baik -tetapi belum menjadi yang terbaik-:

public class EmployeeManager
{
  private readonly EmployeeRepository _mEmployeeRepository;
  private readonly TaxCalculator _mTaxCalculator;
  private readonly MailingGroupsManager _mMailingGroupsManager;
  private readonly HolidaysCalculator _mHolidaysCalculator;

  public async Task<Employee> HireEmployee(Employee employee)
  {
    // Add Employee entry with basic info in DB
    var updatedEmployee = await _mEmployeeRepository.Add(employee);
    
    // Add Emplyee to mailing groups
    updatedEmployee = await _mMailingGroupsManager.Add(updatedEmployee);
    
    // Calculate tax scheme
    decimal tax = await _mTaxCalculator.Calculate(updatedEmployee);
    
    // Update tax scheme in DB
    updatedEmployee = await _mEmployeeRepository.UpdateTax(updatedEmployee, tax);
    
    // Calculate holidays
    byte holidaysCount = await _mHolidaysCalculator.Calculate(updatedEmployee);
    
    // Update holidays in DB
    return await _mEmployeeRepository.UpdateHolidays(updatedEmployee, holidaysCount);
  }
}

Seperti yang kami katakan sebelumnya, jumlah pengetahuan yang dibutuhkan di sini tidak sebesar yang terlihat pada pandangan pertama.

Namun, apakah ini yang terbaik yang bisa kita lakukan?

Sebenarnya tidak, kita bisa melakukan yang lebih baik sebagai berikut:

public class TaxManager
{
  private readonly EmployeeRepository _mEmployeeRepository;
  private readonly TaxCalculator _mTaxCalculator;

  public async Task<Employee> UpdateTax(Employee)
  {
    // Calculate tax scheme
    decimal tax = await _mTaxCalculator.Calculate(updatedEmployee);
    
    // Update tax scheme in DB
    return await _mEmployeeRepository.UpdateTax(updatedEmployee, tax);
  }
}

public class HolidaysManager
{
  private readonly EmployeeRepository _mEmployeeRepository;
  private readonly HolidaysCalculator _mHolidaysCalculator;

  public async Task<Employee> UpdateHolidays(Employee)
  {
    // Calculate holidays
    byte holidaysCount = await _mHolidaysCalculator.Calculate(updatedEmployee);
    
    // Update holidays in DB
    return await _mEmployeeRepository.UpdateHolidays(updatedEmployee, holidaysCount);
  }
}

public class EmployeeManager
{
  private readonly EmployeeRepository _mEmployeeRepository;
  private readonly TaxManager _mTaxManager;
  private readonly MailingGroupsManager _mMailingGroupsManager;
  private readonly HolidaysManager _mHolidaysManager;

  public async Task<Employee> HireEmployee(Employee employee)
  {
    // Add Employee entry with basic info in DB
    var updatedEmployee = await _mEmployeeRepository.Add(employee);
    
    // Add Emplyee to mailing groups
    updatedEmployee = await _mMailingGroupsManager.Add(updatedEmployee);
    
    // Update tax scheme
    updatedEmployee = await _mTaxManager.UpdateTax(updatedEmployee);
    
    // Update holidays
    return await _mHolidaysManager.UpdateHolidays(updatedEmployee);
  }
}

Apa yang kami lakukan di sini:

  • Mengabstraksi pengetahuan menghitung dan menambahkan skema pajak ke dalam kelas TaxManager terpisah.
  • Mengabstraksi pengetahuan menghitung dan menjumlahkan hari libur ke dalam kelas HolidaysManager tersendiri.

Ini berarti kelas EmployeeManager sekarang mengetahui lebih sedikit dibandingkan sebelumnya. Sekarang, ia tidak tahu bahwa untuk memperbarui skema pajak harus menggunakan kelas TaxCalculator terlebih dahulu, lalu menggunakan kelas EmployeeRespository. Hal yang sama berlaku untuk memperbarui hari libur.

Hal ini membuat kelas EmployeeManager memiliki lebih sedikit pengetahuan dan lebih sedikit alasan untuk berubah.

Sekarang saya dapat mendengar Anda berkata:

Namun, ketika ada perubahan yang mengharuskan kita menambahkan langkah baru, seperti menambahkan karyawan ke jaringan sosial perusahaan misalnya, kelas EmployeeManager perlu diubah.

Ya, saya sangat setuju dengan Anda, tetapi saya tidak melihatnya sebagai masalah.

Ini adalah sesuatu yang tidak dapat kita hindari karena ini adalah peran inti dari kelas EmployeeManager; itu menangani alur dan langkah-langkah yang harus dilakukan untuk mempekerjakan seorang karyawan.

Yang perlu selalu kita ingat adalah jika persyaratan berubah, beberapa kode akan berubah. Hal ini tidak bisa dihindari.

Namun, yang ingin kami lakukan adalah meminimalkan jumlah kode di sekitarnya yang perlu diubah atau bahkan disentuh.

Pikiran Terakhir

Dalam artikel ini, kita membahas Prinsip Tanggung Jawab Tunggal -yang juga disingkat SRP- dari Prinsip SOLID.

Terkait prinsip ini, banyak developer yang bingung antara mana yang lebih dan lebih sedikit. Itu sebabnya artikel ini memperjelasnya sekali dan selama-lamanya.

Perlu diingat, Anda perlu ingat bahwa dalam dunia perangkat lunak dan dengan semakin cepatnya perubahan, akan selalu ada beberapa perubahan yang memerlukan perubahan kode juga. Ini normal, ini tidak bisa dihindari, dan Anda tidak boleh melawannya, Anda harus beradaptasi dengannya.

Akhirnya, saya harap Anda menikmati membaca artikel ini seperti saya menikmati menulisnya.

Semoga konten ini bermanfaat bagi Anda. Jika Anda ingin mendukung:

▶ Jika Anda belum menjadi anggota Medium, Anda dapat menggunakan tautan rujukan saya sehingga saya dapat memperoleh sebagian biaya Anda dari Medium, Anda tidak perlu membayar tambahan apa pun.
▶ Berlangganan Buletin saya untuk mendapatkan praktik terbaik, tutorial, petunjuk, kiat, dan banyak hal keren lainnya langsung ke kotak masuk Anda.

Sumber Daya Lainnya

Ini adalah sumber daya lain yang mungkin berguna bagi Anda.











Pengodean Naik Level

Terima kasih telah menjadi bagian dari komunitas kami! Sebelum kamu pergi:

🚀👉 Bergabunglah dengan kumpulan bakat Level Up dan temukan pekerjaan luar biasa