Menurut Robert C. Martin, SRP menyatakan bahwa:
Seharusnya tidak ada lebih dari satu alasan bagi kelas untuk berubah.
Namun, dalam bukunya Clean Code , bab 3: Functions, ia menunjukkan blok kode berikut:
public Money calculatePay(Employee e) throws InvalidEmployeeType {
switch (e.type) {
case COMMISSIONED:
return calculateCommissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
}
}
Dan kemudian nyatakan:
Ada beberapa masalah dengan fungsi ini. Pertama, itu besar, dan ketika tipe karyawan baru ditambahkan, itu akan tumbuh. Kedua, sangat jelas melakukan lebih dari satu hal. Ketiga, itu melanggar Prinsip Tanggung Jawab Tunggal (SRP) karena ada lebih dari satu alasan untuk itu berubah . [penekanan milikku]
Pertama, saya pikir SRP didefinisikan untuk kelas, tetapi ternyata itu juga berlaku untuk fungsi. Kedua, bagaimana fungsi ini memiliki lebih dari satu alasan untuk berubah ? Saya hanya bisa melihatnya berubah karena perubahan pada Karyawan.
Jawaban:
Satu detail yang sering terlewatkan dari Prinsip Tanggung Jawab Tunggal adalah bahwa "alasan untuk perubahan" dikelompokkan oleh aktor-aktor kasus penggunaan (Anda dapat melihat penjelasan lengkap di sini ).
Jadi, dalam contoh Anda,
calculatePay
metode ini perlu diubah setiap kali tipe Karyawan baru diperlukan. Karena satu jenis karyawan mungkin tidak ada hubungannya dengan yang lain, itu akan menjadi pelanggaran prinsip jika Anda tetap bersama, karena perubahan akan mempengaruhi kelompok pengguna yang berbeda (atau aktor kasus penggunaan) dalam sistem.Sekarang, tentang apakah prinsip berlaku untuk fungsi: Bahkan jika Anda memiliki pelanggaran hanya dalam satu metode, Anda masih mengubah kelas karena lebih dari satu alasan, jadi itu masih merupakan pelanggaran SRP.
sumber
Pada halaman 176, Bab 12: Munculnya, di bagian berjudul Kelas dan Metode Minimal buku ini memberikan sedikit koreksi, dengan menyatakan:
dan
Jelas, dia berbicara tentang dogmatisme dalam mengikuti SRP untuk memecah metode-metode kecil yang tidak bersalah seperti di
calculatePay()
atas.sumber
Ketika Tn. Martin menerapkan SRP ke suatu fungsi, dia secara implisit memperluas definisi tentang SRP. Karena SRP adalah kata-kata spesifik OO dari prinsip umum, dan karena itu ide yang bagus ketika diterapkan pada fungsi, saya tidak melihat masalah dengan itu (walaupun mungkin lebih baik jika dia secara eksplisit memasukkannya dalam definisi).
Saya juga tidak melihat lebih dari satu alasan untuk berubah, dan saya tidak percaya bahwa memikirkan SRP dalam hal "tanggung jawab" atau "alasan untuk berubah" sangat membantu. Pada dasarnya apa yang didapat SRP adalah bahwa entitas perangkat lunak (fungsi, kelas, dll.) Harus melakukan satu hal dan melakukannya dengan baik.
Jika Anda melihat definisi saya, itu tidak kurang kabur dari kata-kata SRP yang biasa. Masalah dengan definisi biasa dari SRP bukanlah bahwa mereka terlalu kabur, tetapi mereka mencoba untuk terlalu spesifik tentang sesuatu yang pada dasarnya tidak jelas.
Jika Anda melihat apa yang
calculatePay
dilakukan, itu jelas melakukan satu hal: pengiriman berdasarkan tipe. Karena Java memiliki cara built-in untuk melakukan pengiriman berbasis tipe,calculatePay
tidak elok dan non-idiomatis, sehingga harus ditulis ulang, tetapi tidak untuk alasan yang disebutkan.sumber
Anda benar @ Enrique. Tidak masalah apakah itu fungsi atau metode kelas, SRP berarti bahwa dalam blok kode itu Anda hanya melakukan satu hal.
Pernyataan 'alasan untuk mengubah' kadang-kadang agak menyesatkan, tetapi jika Anda mengubah
calculateSalariedPay
ataucalculateHourlyPay
atau enumEmployee.type
Anda harus mengubah metode ini.Dalam contoh Anda, fungsinya:
Menurut pendapat saya itu bukan pelanggaran SRP secara langsung, karena sakelar dan panggilan tidak dapat ditulis lebih pendek, jika Anda memikirkan Karyawan dan metode yang sudah ada. Pokoknya itu adalah pelanggaran prinsip terbuka-tertutup (OCP) yang jelas karena Anda harus menambahkan pernyataan 'kasus' jika Anda menambahkan jenis karyawan, jadi ini adalah implementasi yang buruk: refactor it.
Kami tidak tahu bagaimana 'Uang' harus dihitung, tetapi cara termudah adalah dengan memiliki
Employee
antarmuka dan beberapa implementasi konkret dengangetMoney
metode. Dalam hal ini seluruh fungsi tidak perlu.Jika lebih rumit untuk menghitungnya, orang dapat menggunakan pola pengunjung yang juga bukan 100% SRP tetapi lebih banyak OCP daripada switch case.
sumber