Prinsip KERING (Jangan Ulangi Diri Sendiri) telah lama jelas bagi semua orang dan dicintai oleh banyak programmer. Dan banyak yang setuju bahwa Copy / Paste tidak keren sama sekali. Pada artikel ini saya ingin memberikan contoh ketika dalam pemrograman industri penggunaan Copy / Paste lebih tepat dan membantu menerapkan prinsip Open-Closed dari SOLID.
Biarkan saya mengingatkan Anda bahwa prinsip Terbuka-tertutup mendorong pemrogram untuk merancang kelas sehingga mereka terbuka untuk perpanjangan, tetapi pada saat yang sama ditutup untuk modifikasi. Mengubah kelas hanya diperbolehkan jika kesalahan terdeteksi di kelas. Jika Anda ingin menambahkan fungsionalitas, maka prinsip tersebut memanggil untuk membuat kelas baru dan menggunakan warisan atau implementasi dari antarmuka yang sama.
Misalnya, ada sistem manajemen parsel. Misalkan, tugas telah datang untuk menambahkan kemampuan untuk membuat, di samping paket-paket sederhana, juga yang mendesak.
Kami memiliki kelas Parcel yang menjelaskan cara kerja paket reguler:
public interface IParcel { string Barcode {get; set;} } public class Parcel: IParcel { public string Barcode {get; set;} }
Sangat menggoda untuk hanya menambahkan bidang ke kelas Parcel lama dan antarmuka IParcel:
public interface IParcel { string Barcode {get; set;} bool IsUrgent {get; set;} } public class Parcel: IParcel { public string Barcode {get; set;} public bool IsUrgent {get; set;} }
Namun, kode tersebut tidak boleh melewati CodeReview! Pemeriksa kode yang ketat dan berpengalaman harus mengembalikannya dengan komentar: "implementasi seperti itu melanggar prinsip Terbuka-tertutup."
Jauh lebih baik untuk membuat kelas UrgentParcel baru, dan Anda tidak perlu mengubah antarmuka atau kelas Parcel. File kelas dan antarmuka akan tetap tidak tersentuh:
public class UrgentParcel: IParcel { public string Barcode {get; set;} }
Ini akan mematuhi prinsip Terbuka-tertutup, dan kode tersebut tidak akan menerima komentar dengan CodeReview.
Sekarang mari kita kembali ke KERING dan cara yang membuatnya sulit untuk menerapkan prinsip Terbuka-tertutup.
Bayangkan bahwa di kelas Parcel kita memiliki bidang "status paket" dan beberapa logika untuk mengubah status ini:
public class Parcel: IParcel { public string Barcode {get; set;}
Apakah logika ini perlu disalin ke kelas UrgentParcel? Prinsip KERING mengatakan itu tidak berarti. Adalah jauh lebih baik bahwa kelas UrgentParcel hanya mewarisi dari kelas Parcel, yang memecahkan masalah dan tidak harus menyalin / menempelkan tubuh metode ArrivedToRecipient ke kelas UrgentParcel.
Namun, jika Anda tidak menyalin kode, tetapi mewarisinya, maka perubahan pada metode ArrivedToRecipient di kelas Parcel akan segera menyebabkan perubahan perilaku kelas UrgentParcel, yang akan melanggar prinsip Terbuka-tertutup. Ini benar-benar pelanggaran, karena tugas dengan paket mendesak (implementasi kelas UrgentParcel) telah dikirim, diuji dan, sebagai hasilnya, bekerja "dalam pertempuran". Jadi, logika ini, diimplementasikan dalam metode UrgentParcel.ArrivedToRecipient dan diterapkan pada paket yang mendesak, cocok untuk semua orang dan TIDAK boleh berubah ketika pekerjaan jenis paket lain berubah. Jadi, prinsip Terbuka-tertutup dirancang secara tepat untuk melindungi sistem dari tindakan seperti itu oleh programmer junior yang tidak berpengalaman yang, sambil menyelesaikan tugas, seperti biasa "berhadapan", belum menyadari semua dependensi, dan perubahan mereka di satu tempat mempengaruhi banyak area fungsional lainnya .
Biasanya, salah satu argumen utama yang mendukung DRY adalah fakta bahwa jika kesalahan ditemukan dalam metode ArrivedToRecipient, maka itu harus diperbaiki di mana pun ia disalin. Jadi ini tidak perlu dilakukan. Jika kesalahan ditemukan dalam metode ArrivedToRecipient ketika bekerja dengan paket reguler, maka perlu untuk memperbaiki pekerjaan paket biasa. Tapi tidak ada yang mengeluh tentang pekerjaan paket yang mendesak dan, mungkin, semua orang senang dengan pekerjaan paket yang mendesak.
Untuk perfeksionis, kepada siapa saya juga menganggap diri saya, saya akan menyarankan meninggalkan komentar yang memungkinkan kita untuk tidak melupakan semua tempat di mana metode ini disalin, dan membantu mengajukan pertanyaan: apakah metode ini bekerja dengan benar untuk paket yang mendesak?
Berikut ini contoh komentar semacam itu:
public class Parcel: IParcel{ ...
Sangat menarik adalah pendapat masyarakat tentang masalah ini. Terima kasih sebelumnya atas komentar Anda.