Basis kode kami sudah lama dan programmer baru, seperti saya, cepat belajar melakukannya dengan cara yang dilakukan demi keseragaman. Berpikir bahwa kita harus mulai dari suatu tempat, saya mengambilnya sendiri untuk mereformasi kelas pemegang data sebagai berikut:
- Metode setter yang dihapus dan membuat semua bidang
final
(saya ambil "final
baik" secara aksiomatis). Setter hanya digunakan dalam konstruktor, ternyata, jadi ini tidak memiliki efek samping. - Memperkenalkan kelas Builder
Kelas Builder diperlukan karena konstruktor (yang pertama kali diminta refactoring) mencakup sekitar 3 baris kode. Ini memiliki banyak parameter.
Seperti keberuntungan, rekan satu tim saya sedang mengerjakan modul lain dan kebetulan membutuhkan setter, karena nilai-nilai yang diperlukannya tersedia di berbagai titik dalam aliran. Jadi kodenya tampak seperti ini:
public void foo(Bar bar){
//do stuff
bar.setA(stuff);
//do more stuff
bar.setB(moreStuff);
}
Saya berpendapat bahwa ia harus menggunakan pembangun sebagai gantinya, karena menyingkirkan setter memungkinkan bidang tetap tidak berubah (mereka telah mendengar saya mengomel tentang ketidakberubahan sebelumnya), dan juga karena pembangun memungkinkan pembuatan objek menjadi transaksional. Saya membuat sketsa pseudocode berikut:
public void foo(Bar bar){
try{
bar.setA(a);
//enter exception-throwing stuff
bar.setB(b);
}catch(){}
}
Jika pengecualian itu kebakaran, bar
akan memiliki data korup, yang seharusnya dihindari dengan pembangun:
public Bar foo(){
Builder builder=new Builder();
try{
builder.setA(a);
//dangerous stuff;
builder.setB(b);
//more dangerous stuff
builder.setC(c);
return builder.build();
}catch(){}
return null;
}
Rekan satu tim saya menjawab bahwa pengecualian yang dimaksud tidak akan pernah menyala, yang cukup adil untuk area kode tertentu, tetapi saya yakin tidak ada hutan untuk pohon itu.
Kompromi adalah untuk kembali ke solusi lama, yaitu menggunakan konstruktor tanpa parameter dan mengatur semuanya dengan setter yang diperlukan. Alasannya adalah bahwa solusi ini mengikuti prinsip KISS, yang dilanggar oleh tambang.
Saya baru di perusahaan ini (kurang dari 6 bulan) dan sepenuhnya menyadari bahwa saya kehilangan yang ini. Pertanyaan yang saya miliki adalah:
- Apakah ada argumen lain untuk menggunakan Builder alih-alih "cara lama"?
- Apakah perubahan yang saya usulkan bahkan benar-benar layak?
tapi sungguh,
- Apakah Anda punya tips untuk menyajikan argumen seperti itu dengan lebih baik ketika menganjurkan mencoba sesuatu yang baru?
setA
?Jawaban:
Di sinilah terjadi kesalahan - Anda membuat perubahan arsitektur utama pada basis kode sedemikian rupa sehingga menjadi sangat berbeda dengan yang diharapkan. Anda mengejutkan kolega Anda. Kejutan hanya baik jika itu melibatkan pesta, prinsip kejutan paling tidak adalah emas (bahkan jika itu melibatkan pesta, maka aku akan tahu memakai celana dalam yang bersih!)
Sekarang jika Anda menganggap perubahan ini bermanfaat, akan jauh lebih baik untuk membuat sketsa kode semu yang menunjukkan perubahan dan menyampaikannya kepada kolega Anda (atau setidaknya siapa pun yang memiliki peran paling dekat dengan arsitek) dan lihat apa yang mereka pikirkan sebelum melakukan sesuatu. Karena, Anda menjadi nakal, berpikir seluruh basis kode adalah milik Anda untuk bermain sesuai keinginan Anda. Seorang pemain di tim, bukan pemain tim!
Saya mungkin sedikit kasar pada Anda, tetapi saya berada di tempat yang berlawanan: lihat beberapa kode dan pikirkan "WTF terjadi di sini ?!", hanya untuk menemukan pria baru (hampir selalu pria baru) memutuskan untuk berubah banyak hal berdasarkan apa yang menurutnya seharusnya "jalan yang benar". Sekrup dengan sejarah SCM juga yang merupakan masalah besar lainnya.
sumber
Seperti dijelaskan, saya tidak melihat apa yang membuat kode membutuhkan seter. Saya mungkin tidak cukup tahu tentang use-case, tetapi mengapa tidak menunggu sampai semua parameter diketahui sebelum instantiate objek?
Sebagai alternatif, jika situasinya membutuhkan setter: tawarkan cara untuk membekukan kode Anda sehingga seter melempar kesalahan pernyataan (alias kesalahan programmer) jika Anda mencoba mengubah bidang setelah objek siap.
Saya pikir menghapus setter dan menggunakan final adalah cara yang "tepat" untuk melakukannya, serta menegakkan keabadian, tetapi apakah itu benar-benar apa yang harus Anda habiskan bersama?
Kiat umum
Lama = buruk, baru = baik, caraku, caramu ... diskusi semacam ini tidak konstruktif.
Saat ini, cara objek Anda digunakan mengikuti beberapa aturan implisit. Ini adalah bagian dari spesifikasi kode Anda yang tidak tertulis dan tim Anda mungkin berpikir bahwa tidak ada banyak risiko untuk bagian lain dari kode yang menyalahgunakannya. Apa yang ingin Anda lakukan di sini adalah membuat aturan lebih eksplisit dengan Builder dan waktu kompilasi cek.
Dalam beberapa hal, kode refactoring dikaitkan dengan teori Jendela Rusak : Anda merasa benar untuk memperbaiki masalah apa pun seperti yang Anda lihat (atau membuat catatan untuk beberapa pertemuan "peningkatan kualitas" nanti) sehingga kode selalu terlihat menyenangkan untuk dikerjakan, aman dan bersih. Anda dan tim Anda tidak memiliki gagasan yang sama tentang apa yang "cukup baik". Apa yang Anda lihat sebagai peluang untuk berkontribusi dan menjadikan kode lebih baik, dengan itikad baik, mungkin terlihat berbeda dari tim yang ada.
Ngomong-ngomong, tim Anda tidak boleh dianggap menderita inersia, kebiasaan buruk, kurang pendidikan, ... yang terburuk yang bisa Anda lakukan adalah memproyeksikan gambar orang yang tahu segalanya yang ada di sana untuk menunjukkan kepada mereka cara membuat kode. Misalnya, ketidakmampuan bukanlah sesuatu yang baru , rekan-rekan Anda mungkin sudah membaca tentang hal itu tetapi hanya karena topik ini menjadi populer di blog tidak cukup untuk meyakinkan mereka untuk menghabiskan waktu mengubah kode mereka.
Bagaimanapun, ada banyak cara untuk meningkatkan basis kode yang ada, tetapi membutuhkan waktu dan uang. Saya bisa melihat kode Anda, menyebutnya "lama" dan menemukan hal-hal yang perlu diperhatikan. Sebagai contoh: ada spesifikasi formal, tidak cukup menegaskan, mungkin tidak cukup komentar atau tes, tidak cukup cakupan kode, algoritma tidak optimal, terlalu banyak penggunaan memori, tidak menggunakan pola desain "terbaik" mungkin dalam setiap kasus, dll memuakkan . Tetapi untuk sebagian besar poin yang akan saya bahas, Anda akan berpikir: tidak apa-apa, kode saya berfungsi, tidak perlu menghabiskan lebih banyak waktu untuk itu.
Mungkin tim Anda berpikir bahwa apa yang Anda sarankan sudah melewati titik pengembalian yang semakin berkurang. Bahkan jika Anda telah menemukan yang sebenarnya contoh dari bug karena jenis contoh Anda menunjukkan (dengan pengecualian) mereka mungkin hanya akan memperbaikinya sekali dan tidak ingin refactor kode.
Jadi pertanyaannya adalah bagaimana menghabiskan waktu dan energi Anda, mengingat mereka terbatas ? Ada perubahan terus-menerus yang dilakukan untuk perangkat lunak, tetapi umumnya ide Anda mulai dengan skor negatif sampai Anda dapat memberikan argumen yang bagus untuk itu. Sekalipun Anda benar mengenai manfaatnya, itu sendiri bukanlah argumen yang cukup, karena ia akan berakhir di keranjang " Bagus untuk dimiliki, suatu hari ... ".
Ketika Anda mengajukan argumen, Anda harus melakukan beberapa pemeriksaan "kewarasan": apakah Anda mencoba menjual ide itu atau diri Anda sendiri? Bagaimana jika ada orang lain yang memberikan ini kepada tim? Apakah Anda menemukan beberapa kekurangan dalam alasan mereka? Apakah Anda mencoba menerapkan beberapa praktik terbaik umum atau apakah Anda mempertimbangkan secara spesifik kode Anda?
Kemudian, Anda harus memastikan tidak muncul sebagai-jika Anda mencoba untuk memperbaiki "kesalahan" masa lalu tim Anda. Ini membantu untuk menunjukkan bahwa Anda bukan ide Anda tetapi dapat menerima umpan balik secara wajar. Semakin banyak Anda melakukan ini, semakin banyak saran Anda akan memiliki kesempatan untuk diikuti.
sumber
Kamu tidak.
Jika konstruktor Anda memiliki 3 baris parameter, itu terlalu besar dan terlalu rumit. Tidak ada pola desain yang akan memperbaikinya.
Jika Anda memiliki kelas yang datanya tersedia pada waktu yang berbeda, itu haruslah dua objek yang berbeda, atau konsumen Anda harus mengumpulkan komponen dan kemudian membangun objek. Mereka tidak perlu pembangun untuk melakukan itu.
sumber
String
dan primitif lainnya. Tidak ada logika di mana pun, bahkan tidak memeriksanull
s dll. Jadi itu hanya ukuran semata, bukan kompleksitas per se. Saya pikir melakukan sesuatu sepertibuilder.addA(a).addB(b); /*...*/ return builder.addC(c).build();
itu akan jauh lebih mudah di mata.Anda tampaknya lebih fokus untuk menjadi benar daripada bekerja dengan baik dengan orang lain. Lebih buruk lagi, Anda menyadari bahwa apa yang Anda lakukan adalah perebutan kekuasaan namun gagal memikirkan bagaimana perasaan orang-orang yang pengalaman dan wewenangnya Anda tantang.
Balikkan itu.
Fokus pada bekerja dengan orang lain. Kerangka pemikiran Anda sebagai saran dan ide. Dapatkan mereka untuk berbicara melalui ide-ide mereka sebelum mengajukan pertanyaan untuk membuat mereka berpikir tentang Anda. Hindari konfrontasi langsung, dan secara lahiriah mau menerima bahwa melanjutkan melakukan hal-hal dengan cara kelompok (untuk saat ini) lebih produktif daripada berjuang dalam perjuangan berat untuk mengubah kelompok. (Meskipun membawa hal-hal kembali.) Jadikan bekerja dengan Anda sukacita.
Lakukan ini secara konsisten dan Anda harus mengurangi konflik, dan temukan lebih banyak ide Anda diadopsi oleh orang lain. Kita semua menderita ilusi bahwa argumen logis yang sempurna akan membuat orang lain kagum dan menang. Dan jika tidak bekerja seperti itu, kami pikir itu harus .
Tapi itu bertentangan langsung dengan kenyataan. Sebagian besar argumen hilang sebelum titik logis pertama dibuat. Bahkan di antara orang-orang yang konon logis, psikologi mengalahkan akal. Meyakinkan orang adalah tentang melewati rintangan psikologis untuk didengarkan dengan benar, dan bukan tentang memiliki logika yang sempurna.
sumber
Frame your thoughts as suggestions and ideas. Get THEM to talk through THEIR ideas before asking questions to make them think about yours
Namun +1 untuk itu"Ketika kamu memiliki palu baru, semuanya akan terlihat seperti paku." - ini adalah apa yang saya pikirkan ketika saya membaca pertanyaan Anda.
Jika saya adalah rekan Anda, saya akan bertanya kepada Anda "mengapa tidak menginisialisasi seluruh objek di konstruktor?" Bagaimanapun juga itulah fungsionalitasnya. Mengapa menggunakan pola builder (atau desain lainnya)?
Sulit untuk mengetahui dari cuplikan kode kecil itu. Mungkin itu - Anda dan kolega Anda perlu mengevaluasinya.
Ya, pelajari lebih lanjut tentang topik tersebut sebelum membahasnya. Persenjatai diri Anda dengan argumen dan alasan yang baik sebelum memasuki diskusi.
sumber
Saya berada dalam situasi di mana saya direkrut untuk keterampilan saya. Ketika saya melihat kode, well .. itu lebih mengerikan. Ketika kemudian mencoba untuk membersihkannya, seseorang yang sudah ada di sana lagi selalu menekan perubahan, karena mereka tidak melihat manfaatnya. Kedengarannya seperti sesuatu yang Anda gambarkan. Itu berakhir dengan saya berhenti dari posisi itu dan sekarang saya dapat berkembang jauh lebih baik di perusahaan yang memiliki praktik yang lebih baik.
Saya tidak berpikir Anda hanya harus berperan bersama dengan yang lain dalam tim karena mereka sudah ada di sana lebih lama. Jika Anda melihat anggota tim Anda menggunakan praktik buruk dalam proyek tempat Anda bekerja, itu adalah tanggung jawab Anda untuk menunjukkannya, seperti yang Anda miliki. Jika tidak, maka Anda bukan sumber yang sangat berharga. Jika Anda menunjukkan semuanya berulang kali, namun tidak ada yang mendengarkan, minta manajemen Anda untuk mengganti atau mengganti pekerjaan. Sangat penting bagi Anda untuk tidak membiarkan diri Anda beradaptasi dengan praktik buruk yang ada.
Untuk pertanyaan aktual
Mengapa menggunakan benda yang tidak bisa diubah? Karena Anda tahu apa yang Anda hadapi.
Katakanlah Anda memiliki koneksi db yang diteruskan yang memungkinkan Anda untuk mengubah host melalui setter, maka Anda tidak tahu koneksi apa itu. Menjadi abadi, maka Anda tahu.
Namun katakanlah bahwa Anda memiliki struktur data yang dapat diambil dari ketekunan dan kemudian kembali dengan data baru, maka masuk akal bahwa struktur ini tidak dapat diubah. Entitas yang sama, tetapi nilainya dapat berubah. Alih-alih menggunakan objek nilai yang tidak berubah sebagai argumen.
Apa yang menjadi fokus pertanyaan adalah pola pembangun untuk menghilangkan dependensi dalam konstruktor. Saya katakan TIDAK besar untuk ini. Contoh sudah jelas untuk kompleks. Jangan coba sembunyikan, perbaiki!
Tl; dr
Menghapus setter bisa benar, tergantung pada kelas. Pola pembangun tidak menyelesaikan masalah, hanya menyembunyikannya. (Kotoran di bawah karpet masih ada bahkan jika Anda tidak bisa melihatnya)
sumber
Sementara semua jawaban lainnya sangat berguna (akan lebih berguna daripada yang akan saya dapatkan), ada properti pembangun yang belum Anda sebutkan: dengan mengubah pembuatan objek menjadi suatu proses, Anda dapat menerapkan batasan logis yang kompleks.
Anda dapat memberi mandat misalnya bahwa bidang-bidang tertentu diatur bersama, atau dalam urutan tertentu. Anda bahkan dapat mengembalikan implementasi objek target yang berbeda tergantung pada keputusan itu.
Ini adalah contoh noddy yang tidak masuk akal tetapi menunjukkan ketiga properti: karakter selalu ditetapkan terlebih dahulu, batas rentang selalu ditetapkan dan divalidasi bersama, dan Anda memilih implementasi Anda saat membangun.
Sangat mudah untuk melihat bagaimana hal ini dapat mengarah pada kode pengguna yang lebih mudah dibaca dan dapat diandalkan tetapi seperti yang Anda juga lihat, ada kerugiannya: banyak dan banyak kode pembangun (dan saya bahkan meninggalkan konstruktor untuk mempersingkat cuplikan). Jadi Anda mencoba menghitung pertukaran, dengan mengajukan pertanyaan seperti:
Rekan Anda hanya memutuskan bahwa pertukaran tidak akan bermanfaat. Anda harus mendiskusikan alasan secara terbuka dan jujur, lebih disukai tanpa menggunakan prinsip-prinsip abstrak, tetapi berkonsentrasi pada implikasi praktis dari solusi ini atau itu.
sumber
Kedengarannya kelas ini sebenarnya lebih dari satu kelas, disatukan dalam definisi file / kelas yang sama. Jika itu adalah DTO, maka itu harus dimungkinkan untuk instantiate dalam sekali jalan dan agar tidak berubah. Jika Anda tidak menggunakan semua bidang / properti dalam satu transaksi, maka hampir pasti melanggar prinsip Tanggung Jawab Tunggal. Mungkin saja memecahnya menjadi kelas-kelas DTO yang lebih kecil, lebih kohesif, dan abadi dapat membantu. Pertimbangkan untuk membaca Kode Bersih jika Anda belum melakukannya sehingga Anda dapat mengartikulasikan masalah dengan lebih baik, dan manfaat membuat perubahan.
Saya tidak berpikir Anda dapat merancang kode pada tingkat ini dengan komite, kecuali jika Anda benar-benar pemrograman massa (tidak terdengar seperti Anda berada di tim semacam itu), jadi saya pikir tidak apa-apa untuk melakukan perubahan berdasarkan pada Anda penilaian terbaik, dan kemudian mengambil dagu jika ternyata Anda salah menilai.
Namun, selama Anda dapat mengartikulasikan masalah potensial dengan kode seperti itu, maka Anda masih dapat memperdebatkan bahwa solusi diperlukan , bahkan jika Anda bukan yang diterima. Orang-orang kemudian bebas untuk menawarkan alternatif.
" Pendapat yang kuat, dipegang dengan lemah " adalah prinsip yang baik - Anda terus maju dengan keyakinan berdasarkan apa yang Anda ketahui, tetapi jika Anda menemukan beberapa informasi baru yang bertentangan, itu, bersikaplah sederhana dan mundurlah dan masuk ke sebuah diskusi tentang apa solusi yang benar harus menjadi. Satu-satunya jawaban yang salah adalah membiarkannya menjadi lebih buruk.
sumber