Saya sering menemukan diri saya berjuang untuk memutuskan mana dari dua cara ini untuk digunakan ketika saya harus menggunakan data umum di beberapa metode di kelas saya. Apa yang akan menjadi pilihan yang lebih baik?
Dalam opsi ini, saya dapat membuat variabel instan untuk menghindari keharusan mendeklarasikan variabel tambahan, dan juga untuk menghindari mendefinisikan parameter metode, tetapi mungkin tidak begitu jelas di mana variabel-variabel tersebut sedang dipakai / dimodifikasi:
public class MyClass {
private int var1;
MyClass(){
doSomething();
doSomethingElse();
doMoreStuff();
}
private void doSomething(){
var1 = 2;
}
private void doSomethingElse(){
int var2 = var1 + 1;
}
private void doMoreStuff(){
int var3 = var1 - 1;
}
}
Atau hanya instantiate variabel lokal dan meneruskannya sebagai argumen?
public class MyClass {
MyClass(){
int var1 = doSomething();
doSomethingElse(var1);
doMoreStuff(var1);
}
private int doSomething(){
int var = 2;
return var;
}
private void doSomethingElse(int var){
int var2 = var + 1;
}
private void doMoreStuff(int var){
int var3 = var - 1;
}
}
Jika jawabannya adalah keduanya benar, yang mana yang lebih sering dilihat / digunakan? Juga, jika Anda dapat memberikan pro / kontra tambahan untuk setiap opsi akan sangat berharga.
java
coding-style
carlossierra
sumber
sumber
Jawaban:
Saya terkejut ini belum disebutkan ...
Itu tergantung apakah
var1
sebenarnya bagian dari keadaan objek Anda .Anda berasumsi bahwa kedua pendekatan ini benar dan hanya masalah gaya. Anda salah.
Ini sepenuhnya tentang bagaimana model yang tepat.
Demikian pula,
private
metode instan ada untuk mengubah keadaan objek Anda . Jika bukan itu yang dilakukan metode Anda, maka itu seharusnyaprivate static
.sumber
transient
tidak ada hubungannya dengan ini, karenatransient
ini tentang keadaan persisten , seperti di bagian-bagian dari objek yang diselamatkan ketika Anda melakukan sesuatu seperti membuat serial objek. Misalnya, toko dukungan ArrayList adalahtransient
meskipun itu sangat penting untuk keadaan ArrayList, karena ketika Anda membuat serial ArrayList, Anda hanya ingin menyimpan bagian dari toko dukungan yang menyimpan elemen ArrayList yang sebenarnya, bukan ruang kosong di akhir disediakan untuk penambahan elemen lebih lanjut.var1
diperlukan untuk beberapa metode tetapi bukan bagian dari keadaanMyClass
, mungkin sudah waktunya untuk memasukkanvar1
dan metode tersebut ke kelas lain untuk digunakanMyClass
.Saya tidak tahu mana yang lebih umum, tetapi saya akan selalu melakukan yang terakhir. Ini lebih jelas mengkomunikasikan aliran data dan masa pakai, dan itu tidak mengasapi setiap instance kelas Anda dengan bidang yang hanya relevan seumur hidup selama inisialisasi. Saya akan mengatakan yang pertama hanya membingungkan, dan membuat tinjauan kode secara signifikan lebih sulit, karena saya harus mempertimbangkan kemungkinan bahwa metode apa pun dapat memodifikasi
var1
.sumber
Anda harus mengurangi cakupan variabel Anda sebanyak mungkin (dan masuk akal). Tidak hanya dalam metode, tetapi secara umum.
Untuk pertanyaan Anda, artinya tergantung apakah variabel tersebut merupakan bagian dari status objek. Jika ya, tidak apa-apa untuk menggunakannya dalam lingkup itu, yaitu seluruh objek. Dalam hal ini, pergi dengan opsi pertama. Jika tidak, gunakan opsi kedua karena mengurangi visibilitas variabel dan kompleksitas keseluruhan.
sumber
Ada gaya lain - gunakan konteks / negara.
Ada sejumlah manfaat dari pendekatan ini. Objek negara dapat berubah secara independen dari objek misalnya, memberikan banyak ruang gerak untuk masa depan.
Ini adalah pola yang juga berfungsi dengan baik dalam sistem server terdistribusi di mana beberapa detail harus dipertahankan di seluruh panggilan. Anda dapat menyimpan detail pengguna, koneksi basis data, dll di
state
objek.sumber
Ini tentang efek samping.
Bertanya apakah
var1
bagian dari negara meleset dari pertanyaan ini. Tentu jikavar1
harus bertahan, itu harus menjadi contoh. Salah satu pendekatan dapat dilakukan untuk bekerja apakah diperlukan kegigihan atau tidak.Pendekatan efek samping
Beberapa variabel instan hanya digunakan untuk berkomunikasi antara metode pribadi dari panggilan ke panggilan. Variabel instance semacam ini dapat di-refactored dari keberadaannya tetapi tidak harus demikian. Terkadang hal-hal menjadi lebih jelas. Tapi ini bukan tanpa risiko.
Anda membiarkan variabel keluar dari cakupannya karena digunakan dalam dua cakupan pribadi yang berbeda. Bukan karena itu diperlukan dalam ruang lingkup Anda menempatkannya. Ini bisa membingungkan. "Global itu jahat!" tingkat membingungkan. Ini bisa berhasil tetapi tidak akan skala dengan baik. Ini hanya berfungsi di yang kecil. Tidak ada benda besar. Tidak ada rantai pewarisan panjang. Jangan menyebabkan efek yo yo .
Pendekatan fungsional
Sekarang, bahkan jika
var1
harus bertahan tidak ada yang mengatakan Anda harus menggunakan jika untuk setiap nilai sementara mungkin diperlukan sebelum mencapai kondisi yang Anda inginkan dipertahankan antara panggilan publik. Itu berarti Anda masih dapat menetapkanvar1
contoh menggunakan metode yang lebih fungsional.Jadi bagian dari keadaan atau tidak, Anda masih bisa menggunakan pendekatan mana pun.
Dalam contoh-contoh ini, 'var1' tidak mengandung apa-apa selain debugger Anda tahu itu ada. Saya kira Anda melakukannya dengan sengaja karena Anda tidak ingin membuat kami bias. Untungnya saya tidak peduli yang mana.
Risiko efek samping
Yang mengatakan, saya tahu dari mana pertanyaan Anda berasal. Saya telah bekerja di bawah warisan yo yo ing menyedihkan yang mengubah variabel contoh di berbagai tingkatan dalam berbagai metode dan pergi dengan tupai mencoba mengikutinya. Inilah risikonya.
Ini adalah rasa sakit yang mendorong saya ke pendekatan yang lebih fungsional. Suatu metode dapat mendokumentasikan dependensi dan output dalam tanda tangannya. Ini adalah pendekatan yang kuat dan jelas. Ini juga memungkinkan Anda mengubah apa yang Anda lewati metode pribadi sehingga lebih dapat digunakan kembali di dalam kelas.
Kelebihan efek samping
Ini juga membatasi. Fungsi murni tidak memiliki efek samping. Itu bisa menjadi hal yang baik tetapi tidak berorientasi objek. Sebagian besar orientasi objek adalah kemampuan untuk merujuk pada konteks di luar metode. Melakukan itu tanpa membocorkan global di sini dan pergi adalah kekuatan OOP. Saya mendapatkan fleksibilitas global tetapi terkandung dengan baik di kelas. Saya dapat memanggil satu metode dan memutasikan setiap variabel instan sekaligus jika saya mau. Jika saya melakukan itu, saya berkewajiban untuk setidaknya memberikan nama metode yang membuat jelas apa yang terserah sehingga orang tidak akan terkejut ketika itu terjadi. Komentar dapat membantu juga. Terkadang komentar ini diformalkan sebagai "kondisi posting".
Kelemahan dari metode pribadi yang fungsional
Pendekatan fungsional membuat beberapa dependensi menjadi jelas. Kecuali jika Anda menggunakan bahasa fungsional murni, itu tidak dapat mengesampingkan dependensi tersembunyi. Anda tidak tahu, hanya melihat tanda tangan metode, bahwa itu tidak menyembunyikan efek samping dari Anda di sisa kode itu. Anda tidak melakukannya.
Posting kondisional
Jika Anda, dan semua orang di tim, andal mendokumentasikan efek samping (kondisi sebelum / pasca) dalam komentar, maka keuntungan dari pendekatan fungsional jauh lebih sedikit. Ya saya tahu, teruslah bermimpi.
Kesimpulan
Secara pribadi saya cenderung ke arah metode privat fungsional dalam kedua kasus jika saya bisa, tapi jujur itu sebagian besar karena komentar efek sampingan pra / pasca bersyarat tidak menyebabkan kesalahan kompiler ketika mereka sudah ketinggalan zaman atau ketika metode yang disebut rusak. Kecuali saya benar-benar membutuhkan kelenturan efek samping, saya lebih baik mengetahui bahwa semuanya berjalan baik.
sumber
var1
sebagai variabel status dengan mengubah paradigma. Lingkup kelas BUKAN hanya di mana negara disimpan. Ini juga merupakan ruang lingkup penutup. Itu berarti ada dua kemungkinan motivasi untuk meletakkan variabel di tingkat kelas. Anda dapat mengklaim melakukan itu hanya untuk lingkup tertutup dan tidak menyatakan bahwa itu jahat, tetapi saya katakan itu adalah pertukaran dengan kesucian yang juga jahat. Saya tahu ini karena saya harus menjaga kode yang melakukan ini. Beberapa dilakukan dengan baik. Beberapa adalah mimpi buruk. Garis antara keduanya bukan negara. Ini keterbacaan.Varian pertama terlihat tidak intuitif dan berpotensi berbahaya bagi saya (bayangkan untuk alasan apa pun seseorang membuat metode pribadi Anda menjadi publik).
Saya lebih suka instantiate variabel Anda pada konstruksi kelas, atau meneruskannya sebagai argumen. Yang terakhir memberi Anda pilihan untuk menggunakan idiom fungsional dan tidak bergantung pada keadaan objek yang mengandung.
sumber
Sudah ada jawaban yang berbicara tentang keadaan objek dan ketika metode kedua lebih disukai. Saya hanya ingin menambahkan satu use case umum untuk pola pertama.
Pola pertama benar-benar valid ketika semua yang dilakukan kelas Anda adalah bahwa ia merangkum sebuah algoritma . Satu kasus penggunaan untuk ini adalah bahwa jika Anda menulis algoritma ke metode tunggal itu akan terlalu besar. Jadi Anda memecahnya menjadi metode yang lebih kecil menjadikannya kelas dan membuat sub metode pribadi.
Sekarang melewati semua keadaan algoritma melalui parameter mungkin membosankan sehingga Anda menggunakan bidang pribadi. Ini juga sesuai dengan aturan di paragraf pertama karena pada dasarnya adalah keadaan instance. Anda hanya perlu mengingat dan mendokumentasikan dengan baik bahwa algoritme tidak reentrant jika Anda menggunakan bidang pribadi untuk ini . Ini seharusnya tidak menjadi masalah sebagian besar waktu tetapi mungkin bisa menggigit Anda.
sumber
Mari kita coba contoh yang melakukan sesuatu. Maafkan saya karena ini javascript bukan java. Intinya harus sama.
Kunjungi https://blockly-games.appspot.com/pond-duck?lang=en , klik tab javascript, dan rekatkan ini:
Anda harus memperhatikan itu
dir
,,wid
dandis
tidak sering diedarkan. Anda juga harus memperhatikan bahwa kode dalam fungsi yanglock()
mengembalikan sangat mirip dengan kode semu. Yah itu kode aktual. Namun sangat mudah dibaca. Kita dapat menambahkan passing dan penetapan tetapi itu akan menambah kekacauan yang tidak akan pernah Anda lihat dalam kode semu.Jika Anda ingin berargumen bahwa tidak melakukan penetapan dan passing tidak apa-apa karena ketiga vars tersebut merupakan kondisi persisten, maka pertimbangkan desain ulang yang menetapkan
dir
nilai acak setiap loop. Tidak gigih sekarang, kan?Tentu, sekarang kita bisa drop-
dir
down dalam lingkup sekarang tetapi tidak tanpa dipaksa untuk mengacaukan kode pseudo like kita dengan passing dan setting.Jadi tidak, nyatakan bukan mengapa Anda memutuskan untuk menggunakan atau tidak menggunakan efek samping daripada lewat dan kembali. Efek samping juga tidak berarti kode Anda tidak dapat dibaca. Anda tidak mendapatkan manfaat dari kode fungsional murni . Tetapi dilakukan dengan baik, dengan nama-nama baik, mereka sebenarnya bisa menyenangkan untuk dibaca.
Itu tidak berarti mereka tidak bisa berubah menjadi spageti seperti mimpi buruk. Tetapi, apa yang tidak bisa?
Selamat berburu bebek.
sumber