Kami memiliki cukup banyak tempat dalam kode sumber aplikasi kami, di mana satu kelas memiliki banyak metode dengan nama dan parameter yang berbeda. Metode-metode itu selalu memiliki semua parameter metode 'sebelumnya' plus satu lagi.
Ini adalah hasil dari evolusi yang panjang (kode warisan) dan pemikiran ini (saya percaya):
" Ada metode M yang melakukan hal A. Saya perlu melakukan A + B. OK, saya tahu ... Saya akan menambahkan parameter baru ke M, buat metode baru untuk itu, pindahkan kode dari M ke metode baru dengan satu parameter lagi, lakukan A + B di sana dan panggil metode baru dari M dengan nilai default dari parameter baru. "
Berikut ini sebuah contoh (dalam bahasa mirip Java):
class DocumentHome {
(...)
public Document createDocument(String name) {
// just calls another method with default value of its parameter
return createDocument(name, -1);
}
public Document createDocument(String name, int minPagesCount) {
// just calls another method with default value of its parameter
return createDocument(name, minPagesCount, false);
}
public Document createDocument(String name, int minPagesCount, boolean firstPageBlank) {
// just calls another method with default value of its parameter
return createDocument(name, minPagesCount, false, "");
}
public Document createDocument(String name, int minPagesCount, boolean firstPageBlank, String title) {
// here the real work gets done
(...)
}
(...)
}
Saya merasa ini salah. Tidak hanya itu kami tidak dapat terus menambahkan parameter baru seperti ini selamanya, tetapi kode sulit diperluas / diubah karena semua dependensi antara metode.
Berikut adalah beberapa cara untuk melakukan ini dengan lebih baik:
Memperkenalkan objek parameter:
class DocumentCreationParams { String name; int minPagesCount; boolean firstPageBlank; String title; (...) } class DokumentHome { public Document createDocument(DocumentCreationParams p) { // here the real work gets done (...) } }
Atur parameter ke
DocumentHome
objek sebelum kita memanggilcreateDocument()
@In DocumentHome dh = null; (...) dh.setName(...); dh.setMinPagesCount(...); dh.setFirstPageBlank(...); Document newDocument = dh.createDocument();
Pisahkan pekerjaan menjadi berbagai metode dan panggil mereka sesuai kebutuhan:
@In DocumentHome dh = null; Document newDocument = dh.createDocument(); dh.changeName(newDocument, "name"); dh.addFirstBlankPage(newDocument); dh.changeMinPagesCount(new Document, 10);
Pertanyaan saya:
- Apakah masalah yang dijelaskan benar-benar masalah?
- Apa pendapat Anda tentang solusi yang disarankan? Yang mana yang Anda pilih (berdasarkan pengalaman Anda)?
- Bisakah Anda memikirkan solusi lain?
Jawaban:
Mungkin mencoba pola pembangun ? (catatan: hasil Google cukup acak :)
Saya tidak dapat memberikan ikhtisar lengkap mengapa saya lebih suka builder daripada opsi yang Anda berikan, tetapi Anda telah mengidentifikasi masalah besar dengan banyak kode. Jika Anda berpikir Anda membutuhkan lebih dari dua parameter untuk suatu metode, Anda mungkin memiliki kode yang terstruktur secara salah (dan beberapa orang akan membantahnya!).
Masalah dengan objek params adalah (kecuali objek yang Anda buat benar-benar nyata), Anda hanya perlu mendorong masalah ke atas, dan Anda berakhir dengan sekelompok parameter yang tidak terkait yang membentuk 'objek'.
Upaya Anda yang lain terlihat bagi saya seperti seseorang meraih pola pembangun tetapi tidak cukup sampai di sana :)
sumber
DocumentoFactory
). Memilikibuilder
di tempat yang berbeda sulit untuk mengontrol perubahan masa depan pada konstruksi Dokumen (seperti menambahkan bidang wajib baru ke dokumen, misalnya) dan menambahkan kode boilerplate tambahan pada tes untuk memenuhi kebutuhan pembuat dokumen di kelas yang menggunakan pembangun.Menggunakan objek parameter adalah cara yang baik untuk menghindari kelebihan (berlebihan) metode:
Namun, saya tidak akan terlalu jauh dengan itu.
Memiliki kelebihan di sana-sini bukan hal yang buruk. Ini didukung oleh bahasa pemrograman, jadi gunakan untuk keuntungan Anda.
Saya tidak mengetahui pola pembangun, tetapi telah menggunakannya "secara tidak sengaja" pada beberapa kesempatan. Hal yang sama berlaku di sini: jangan berlebihan. Kode dalam contoh Anda akan mendapat manfaat dari itu, tetapi menghabiskan banyak waktu mengimplementasikannya untuk setiap metode yang memiliki metode kelebihan tunggal tidak terlalu efisien.
Hanya 2 sen saya.
sumber
Jujur saya tidak melihat masalah besar dengan kode. Dalam C # dan C ++ Anda dapat menggunakan parameter opsional, itu akan menjadi alternatif, tetapi sejauh yang saya tahu Java tidak mendukung parameter semacam itu.
Dalam C # Anda dapat membuat semua kelebihan beban menjadi pribadi dan satu metode dengan parameter opsional adalah publik untuk memanggil hal-hal tersebut.
Untuk menjawab pertanyaan Anda bagian 2, saya akan mengambil objek parameter atau bahkan kamus / HashMap.
Seperti itu:
Sebagai penafian, saya pertama-tama seorang programmer C # dan JavaScript dan kemudian seorang programmer Java.
sumber
Saya pikir ini adalah kandidat yang baik untuk pola pembangun. Pola pembangun berguna ketika Anda ingin membuat objek dengan tipe yang sama, tetapi dengan representasi yang berbeda.
Dalam kasus Anda, saya akan memiliki pembangun dengan metode berikut:
Anda kemudian dapat menggunakan pembuat dengan cara berikut:
Di samping catatan, saya tidak keberatan beberapa kelebihan sederhana - apa-apaan, .NET framework menggunakannya di semua tempat dengan bantuan HTML. Namun, saya akan mengevaluasi kembali apa yang saya lakukan jika saya harus melewati lebih dari dua parameter untuk setiap metode.
sumber
Saya pikir
builder
solusinya dapat bekerja pada sebagian besar skenario, tetapi pada kasus yang lebih kompleks pembangun Anda juga akan rumit untuk diatur , karena mudah untuk melakukan beberapa kesalahan pada urutan metode, metode apa yang perlu diungkapkan atau tidak , dll. Jadi, banyak dari kita akan lebih suka solusi yang paling sederhana.Jika Anda hanya membuat pembangun sederhana untuk membangun dokumen dan menyebarkan kode ini di berbagai bagian (kelas) aplikasi, akan sulit untuk:
Tapi ini tidak menjawab pertanyaan OP.
Alternatif untuk kelebihan beban
Beberapa alternatif:
createDocument
, seperti:createLicenseDriveDocument
,createDocumentWithOptionalFields
, dll Tentu saja, ini dapat menyebabkan Anda untuk nama metode raksasa, jadi ini bukan solusi untuk semua kasus.Document
, seperti:Document.createLicenseDriveDocument()
.createDocument(InterfaceDocument interfaceDocument)
dan membuat implementasi yang berbeda untukInterfaceDocument
. Per contoh:createDocument(new DocumentMinPagesCount("name"))
. Tentu saja Anda tidak memerlukan implementasi tunggal untuk setiap kasus, karena Anda dapat membuat lebih dari satu konstruktor pada setiap implementasi, mengelompokkan beberapa bidang yang masuk akal pada implementasi itu. Pola ini disebut konstruktor telescoping .Atau Hanya tinggal dengan solusi kelebihan . Bahkan, kadang-kadang, solusi jelek, tidak ada banyak kelemahan dalam menggunakannya. Dalam hal ini, saya lebih suka menggunakan metode overload pada kelas yang terpisah, seperti
DocumentoFactory
yang dapat disuntikkan sebagai ketergantungan pada kelas yang perlu membuat dokumen. Saya dapat mengatur dan memvalidasi bidang tanpa kerumitan membuat pembangun yang baik dan mempertahankan kode di satu tempat juga.sumber