Misalnya, untuk mengaktifkan CPU di Android, saya dapat menggunakan kode seperti ini:
PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();
tapi saya pikir variabel lokal powerManager
dan wakeLock
dapat dihilangkan:
((PowerManager)getSystemService(POWER_SERVICE))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
.acquire();
adegan serupa muncul di tampilan peringatan iOS, misalnya: dari
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"my title"
message:@"my message"
delegate:nil
cancelButtonTitle:@"ok"
otherButtonTitles:nil];
[alert show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[alertView release];
}
untuk:
[[[UIAlertView alloc]
initWithTitle:@"my title"
message:@"my message"
delegate:nil
cancelButtonTitle:@"ok"
otherButtonTitles:nil] show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[alertView release];
}
Apakah praktik yang baik untuk menghilangkan variabel lokal jika hanya digunakan satu kali dalam cakupan?
Jawaban:
Kode dibaca jauh lebih sering daripada yang tertulis, jadi Anda harus kasihan pada jiwa miskin yang harus membaca kode enam bulan dari sekarang (mungkin Anda) dan berusaha untuk kode yang paling jelas dan termudah untuk dipahami. Menurut pendapat saya, bentuk pertama, dengan variabel lokal, jauh lebih mudah dipahami. Saya melihat tiga tindakan pada tiga baris, bukan tiga tindakan pada satu baris.
Dan jika Anda pikir Anda mengoptimalkan apa pun dengan menyingkirkan variabel lokal, Anda tidak. Kompiler modern akan memasukkan
powerManager
register 1 , apakah variabel lokal digunakan atau tidak, untuk memanggilnewWakeLock
metode. Hal yang sama berlaku untukwakeLock
. Jadi Anda berakhir dengan kode terkompilasi yang sama dalam kedua kasus.1 Jika Anda memiliki banyak kode intervensi antara deklarasi dan penggunaan variabel lokal, mungkin ada di stack, tetapi ini adalah detail kecil.
sumber
Beberapa komentar yang sangat tersirat menyatakan hal ini, tetapi tidak ada jawaban yang saya lihat, jadi saya akan menambahkannya sebagai jawaban. Faktor utama Anda dalam memutuskan masalah ini adalah:
Debuggability
Seringkali, pengembang menghabiskan lebih banyak waktu dan upaya debugging daripada menulis kode.
Dengan variabel lokal, Anda dapat:
Breakpoint pada baris tempat ditugaskan (dengan semua dekorasi breakpoint lainnya, seperti breakpointing bersyarat, dll ...)
Periksa / saksikan / cetak / ubah-nilai-variabel lokal
Menangkap masalah yang muncul karena gips.
Memiliki jejak tumpukan yang dapat dibaca (jalur XYZ memiliki satu operasi alih-alih 10)
Tanpa variabel lokal, semua tugas di atas mungkin jauh lebih sulit, sangat sulit, atau benar-benar mustahil, tergantung pada debugger Anda.
Dengan demikian, ikuti pepatah terkenal (tulis kode dengan cara yang Anda inginkan seolah-olah pengembang berikutnya untuk mempertahankannya setelah Anda sendiri adalah orang gila gila yang tahu di mana Anda tinggal), dan berbuat salah di sisi debuggability yang lebih mudah , artinya gunakan variabel lokal .
sumber
Hanya jika itu membuat kode lebih mudah dimengerti. Dalam contoh Anda, saya pikir itu membuatnya lebih sulit untuk dibaca.
Menghilangkan variabel dalam kode yang dikompilasi adalah operasi sepele untuk setiap kompiler yang terhormat. Anda dapat memeriksa sendiri output untuk memverifikasi.
sumber
Pertanyaan Anda "apakah ini praktik yang baik untuk menghilangkan variabel lokal jika hanya digunakan satu kali dalam cakupan?" sedang menguji kriteria yang salah. Utilitas variabel lokal tidak tergantung pada berapa kali digunakan tetapi apakah itu membuat kode lebih jelas. Memberi label nilai menengah dengan nama yang bermakna dapat meningkatkan kejelasan dalam situasi seperti yang Anda hadirkan karena memecah kode menjadi potongan yang lebih kecil dan lebih mudah dicerna.
Dalam pandangan saya, kode yang tidak dimodifikasi yang Anda berikan lebih jelas daripada kode Anda yang dimodifikasi dan karenanya tidak akan berubah. Bahkan, saya akan mempertimbangkan mengeluarkan variabel lokal dari kode Anda yang dimodifikasi untuk meningkatkan kejelasan.
Saya tidak akan mengharapkan dampak kinerja dari variabel lokal, dan bahkan jika ada satu kemungkinan terlalu kecil untuk dipertimbangkan kecuali jika kode berada dalam lingkaran yang sangat ketat di bagian penting kecepatan program.
sumber
Mungkin.
Secara pribadi saya akan ragu menghilangkan variabel lokal jika ada typecast yang terlibat. Saya menemukan versi ringkas Anda kurang dapat dibaca karena jumlah tanda kurung mulai mendekati batas mental yang saya miliki. Bahkan memperkenalkan seperangkat tanda kurung baru yang tidak diperlukan dalam versi yang sedikit lebih verbose menggunakan variabel lokal.
Penyorotan sintaksis yang disediakan oleh editor kode dapat mengurangi kekhawatiran semacam itu sampai batas tertentu.
Bagi saya, ini adalah kompromi yang lebih baik:
Dengan demikian menjaga satu variabel lokal dan membuang variabel lainnya. Di C # saya akan menggunakan kata kunci var di baris pertama karena typecast sudah menyediakan informasi jenis.
sumber
Meskipun saya menerima validitas jawaban yang mendukung variabel lokal, saya akan berperan sebagai advokat iblis dan menyajikan pandangan pelawan.
Saya pribadi agak menentang menggunakan variabel lokal murni untuk jumlah yang untuk tujuan dokumentasi, meskipun alasan itu sendiri menunjukkan bahwa praktik itu memiliki nilai: variabel lokal secara efektif pseudo-mendokumentasikan kode.
Dalam kasus Anda, masalah utama adalah lekukan dan bukan tidak adanya variabel. Anda dapat (dan harus) memformat kode sebagai berikut:
Bandingkan dengan versi dengan variabel lokal:
Dengan variabel lokal: nama menambahkan beberapa informasi ke pembaca dan jenisnya ditentukan dengan jelas, tetapi panggilan metode aktual kurang terlihat dan (menurut saya) tidak dibaca dengan jelas.
Tanpa menggunakan variabel lokal: ini lebih ringkas dan pemanggilan metode lebih terlihat, tetapi Anda mungkin meminta informasi lebih lanjut tentang apa yang dikembalikan. Namun beberapa IDE dapat menunjukkan ini kepada Anda.
Tiga komentar lebih lanjut:
Menurut pendapat saya, menambahkan kode yang tidak memiliki penggunaan fungsional kadang-kadang dapat membingungkan karena pembaca harus menyadari bahwa itu memang tidak memiliki penggunaan fungsional dan hanya ada untuk "dokumentasi". Misalnya, jika metode ini panjangnya 100 baris, tidak akan jelas bahwa variabel lokal (dan karenanya hasil dari pemanggilan metode) tidak diperlukan di beberapa titik kemudian kecuali Anda membaca keseluruhan metode.
Menambahkan variabel lokal berarti bahwa Anda harus menentukan jenisnya, dan ini menimbulkan ketergantungan pada kode yang jika tidak maka tidak akan ada. Jika tipe pengembalian metode berubah sepele (misalnya, namanya diubah) Anda harus memperbarui kode Anda, sedangkan tanpa variabel lokal Anda tidak akan.
Debugging bisa lebih mudah dengan variabel lokal jika debugger Anda tidak menunjukkan nilai yang dikembalikan dari metode. Tetapi perbaikan untuk itu adalah untuk memperbaiki kekurangan pada debugger, bukan mengubah kode.
sumber
with
pernyataan. Ini akan menjadi konvensi pemformatan normal di Jawa.Ada ketegangan motivasi di sini. Pengenalan variabel sementara dapat membuat kode lebih mudah dibaca. Tetapi mereka juga dapat mencegah, dan membuatnya lebih sulit untuk melihat, refactoring lain yang mungkin, seperti Metode Ekstrak , dan Ganti Temp dengan Permintaan . Jenis refactoring yang terakhir ini, bila sesuai, seringkali memberikan manfaat yang jauh lebih besar daripada variabel temp.
Pada motivasi untuk refactoring terakhir ini, Fowler menulis :
Jadi, ya, gunakan temps jika mereka membuat kode lebih mudah dibaca, terutama jika itu adalah norma lokal untuk Anda dan tim Anda. Tetapi sangat berhati-hati bahwa melakukan hal itu kadang-kadang dapat membuat Anda lebih sulit menemukan peningkatan alternatif yang lebih besar. Jika Anda dapat mengembangkan kemampuan Anda untuk merasakan ketika pergi tanpa manfaat seperti itu, dan menjadi lebih nyaman ketika melakukannya, maka itu mungkin hal yang baik.
FWIW Saya pribadi menghindari membaca buku Fowler "Refactoring" selama sepuluh tahun karena saya membayangkan tidak banyak yang bisa dikatakan tentang topik-topik yang relatif langsung itu. Saya benar-benar salah. Ketika saya akhirnya membacanya, itu mengubah praktik pengkodean harian saya, jauh lebih baik.
sumber
Sebaiknya hilangkan variabel lokal jika Anda bisa membuat kode lebih mudah dibaca. Satu kalimat panjang Anda tidak dapat dibaca, tetapi kemudian mengikuti gaya OO yang sangat jelas. Jika Anda bisa menguranginya menjadi seperti
maka saya akan mengatakan itu mungkin ide yang bagus. Mungkin Anda bisa memperkenalkan metode pembantu untuk merebusnya menjadi sesuatu yang serupa; jika kode seperti ini muncul beberapa kali maka mungkin bermanfaat.
sumber
Mari pertimbangkan Hukum Demeter di sini. Dalam artikel Wikipedia tentang LoD berikut ini dinyatakan:
Salah satu konsekuensi dari mengikuti Undang-undang ini adalah Anda harus menghindari metode memanggil objek yang dikembalikan oleh metode lain dalam string bertitik-panjang, seperti yang ditunjukkan pada contoh kedua di atas:
Sangat sulit untuk mengetahui apa yang dilakukannya. Untuk memahaminya, Anda harus memahami apa yang dilakukan masing-masing prosedur, dan kemudian menguraikan fungsi yang dipanggil pada objek mana. Blok kode pertama
jelas menunjukkan apa yang Anda coba lakukan - Anda mendapatkan objek PowerManager, mendapatkan objek WakeLock dari PowerManager, lalu mendapatkan wakeLock. Aturan di atas mengikuti aturan # 3 dari LoD - Anda membuat instance objek-objek ini dalam kode Anda, dan dengan demikian dapat menggunakannya untuk menyelesaikan apa yang Anda butuhkan.
Mungkin cara lain untuk dipikirkan adalah dengan mengingat bahwa ketika membuat perangkat lunak Anda harus menulis untuk kejelasan, bukan untuk singkatnya. 90% dari semua pengembangan perangkat lunak adalah pemeliharaan. Jangan pernah menulis kode yang tidak akan Anda sukai.
Semoga berhasil.
sumber
Satu hal yang perlu diperhatikan adalah bahwa kode sering dibaca, untuk "kedalaman" yang berbeda. Kode ini:
mudah untuk "skim". Ada 3 pernyataan. Pertama kami datang dengan
PowerManager
. Lalu kami datang denganWakeLock
. Lalu kamiacquire
yangwakeLock
. Saya bisa melihatnya dengan sangat mudah hanya dengan melihat awal setiap baris; tugas variabel sederhana benar-benar mudah dikenali sebagian sebagai "Ketik varName = ..." dan hanya skim mental atas "...". Demikian pula pernyataan terakhir jelas bukan bentuk penugasan, tetapi hanya melibatkan dua nama, sehingga "inti utama" segera terlihat. Seringkali hanya itu yang perlu saya ketahui jika saya hanya mencoba menjawab "apa yang dilakukan kode ini?" pada level agak tinggi.Jika saya mengejar bug halus yang saya pikir ada di sini, maka jelas saya harus membahas ini lebih detail, dan akan benar-benar mengingat "...". Tetapi struktur pernyataan yang terpisah masih membantu saya melakukan pernyataan itu satu per satu (khususnya berguna jika saya perlu terjun lebih dalam ke dalam implementasi hal-hal yang dipanggil dalam setiap pernyataan; ketika saya kembali, saya sepenuhnya memahami "satu unit" dan kemudian dapat beralih ke pernyataan berikutnya).
Sekarang semuanya satu pernyataan. Struktur tingkat atas tidak mudah dibaca skim; dalam versi asli OP, tanpa linebreak dan indentasi untuk secara visual mengkomunikasikan struktur apa pun, saya harus menghitung tanda kurung untuk menerjemahkannya ke dalam urutan 3 langkah. Jika beberapa ekspresi multi-bagian bersarang di dalam satu sama lain alih-alih diatur sebagai rangkaian panggilan metode, maka itu masih bisa terlihat mirip dengan ini, jadi saya harus berhati-hati mempercayai itu tanpa menghitung tanda kurung. Dan jika saya benar-benar memercayai indentasi dan hanya melihat ke depan ke hal terakhir sebagai titik yang diduga dari semua ini, apa yang
.acquire()
saya katakan sendiri?Namun terkadang, itu bisa menjadi apa yang Anda inginkan. Jika saya menerapkan transformasi Anda setengah jalan dan menulis:
Sekarang ini berkomunikasi dengan skim cepat "dapatkan
WakeLock
, laluacquire
itu". Bahkan lebih sederhana dari versi pertama. Segera jelas bahwa hal yang diperoleh adalah aWakeLock
. Jika memperolehPowerManager
hanya sub-detail yang cukup signifikan untuk poin kode ini, tetapi yangwakeLock
penting, maka itu sebenarnya bisa membantu untuk menguburPowerManager
barang - barang jadi wajar saja untuk melewatinya jika Anda hanya mencoba dengan cepat mendapatkan ide tentang apa kode ini. Dan tidak penamaan itu berkomunikasi bahwa itu adalah hanya digunakan sekali, dan kadang-kadang itu yang penting (jika sisa cakupannya sangat panjang, saya harus membaca semua itu untuk mengetahui apakah itu pernah digunakan lagi; meskipun menggunakan sub-lingkup eksplisit dapat menjadi cara lain untuk mengatasinya, jika bahasa Anda mendukungnya).Yang memunculkan bahwa semuanya tergantung pada konteks dan apa yang ingin Anda komunikasikan. Seperti halnya menulis prosa dalam bahasa alami, selalu ada banyak cara untuk menulis sepotong kode tertentu yang pada dasarnya setara dalam hal konten informasi. Seperti halnya menulis prosa dalam bahasa alami, bagaimana Anda memilih di antara mereka umumnya tidak boleh menerapkan aturan mekanistik seperti "menghilangkan variabel lokal yang hanya terjadi sekali". Lebih tepatnya bagaimanaAnda memilih untuk menuliskan kode Anda akan menekankan hal-hal tertentu dan tidak menekankan yang lain. Anda harus berusaha keras untuk membuat pilihan-pilihan itu secara sadar (termasuk pilihan untuk menulis kode yang kurang mudah dibaca karena alasan teknis pada waktu tertentu), berdasarkan apa yang sebenarnya ingin Anda tekankan. Terutama pikirkan tentang apa yang akan melayani pembaca yang hanya perlu "mendapatkan intisari" dari kode Anda (di berbagai tingkatan), karena itu akan terjadi jauh lebih sering daripada pembacaan ekspresi-per-ekspresi yang sangat dekat.
sumber
getSystemService(POWER_SERVICE)
mendapatkan manajer kekuatan..newWakeLock
mendapat kunci bangun..acquire
memperolehnya. OK, saya tidak tahu semua tipe, tetapi saya dapat menemukannya di IDE jika saya perlu.return
secepat mungkin dari metode, untuk alasan yang sama.Ini bahkan merupakan antipattern dengan namanya sendiri: Train Wreck . Beberapa alasan untuk menghindari penggantian telah dinyatakan:
Pertimbangkan apakah metode ini tahu terlalu banyak dari objek lain. Metode chaining adalah alternatif yang bisa membantu Anda mengurangi kopling.
Juga ingat bahwa referensi ke objek sangat murah.
sumber
Pertanyaan yang dinyatakan adalah "Haruskah kita menghilangkan variabel lokal jika kita bisa"?
Tidak, Anda tidak harus menghilangkan hanya karena Anda bisa.
Anda harus mengikuti pedoman pengkodean di toko Anda.
Sebagian besar variabel lokal membuat kode lebih mudah dibaca dan di-debug.
Saya suka dengan apa yang Anda lakukan
PowerManager powerManager
. Bagi saya huruf kecil dari kelas berarti hanya digunakan satu kali.Ketika Anda seharusnya tidak, apakah variabel akan memegang sumber daya mahal. Banyak bahasa memiliki sintaks untuk variabel lokal yang perlu dibersihkan / dirilis. Dalam C # itu menggunakan.
sumber
using(new SQLConnection()) { /* ... */ }
tidak legal juga (apakah itu akan berguna adalah masalah yang berbeda :).Satu aspek penting belum disebutkan dalam jawaban lain: Setiap kali Anda menambahkan variabel, Anda memperkenalkan keadaan bisa berubah. Ini biasanya merupakan hal yang buruk karena membuat kode Anda lebih kompleks dan karenanya lebih sulit untuk dipahami dan diuji. Tentu saja, semakin kecil cakupan variabel, semakin kecil masalahnya.
Yang Anda inginkan sebenarnya bukan variabel yang nilainya dapat dimodifikasi tetapi konstanta sementara. Karena itu pertimbangkan untuk mengungkapkan ini dalam kode Anda jika bahasa Anda memungkinkan. Di Jawa Anda bisa menggunakan
final
dan di C ++ Anda bisa menggunakanconst
. Dalam sebagian besar bahasa fungsional, ini adalah perilaku default.Memang benar bahwa variabel lokal adalah jenis negara yang paling tidak berbahaya yang bisa berubah. Variabel anggota dapat menyebabkan lebih banyak masalah dan variabel statis bahkan lebih buruk. Masih saya merasa penting untuk mengekspresikan seakurat mungkin dalam kode Anda apa yang seharusnya dilakukan. Dan ada perbedaan besar antara variabel yang dapat dimodifikasi kemudian dan hanya nama untuk hasil antara. Jadi, jika bahasa Anda memungkinkan Anda mengekspresikan perbedaan ini, lakukan saja.
sumber
getFoo()
. Jika saya menghindari deklarasi lokal, saya akan berakhir denganif(getFoo() > 10) alert(getFoo());
Tapi getFoo () mungkin mengembalikan nilai yang berbeda pada dua panggilan yang berbeda. Saya dapat mengirimkan lansiran dengan nilai kurang dari atau sama dengan 10 yang paling membingungkan dan akan kembali kepada saya sebagai cacat. Hal semacam ini menjadi lebih penting dengan konkurensi. Tugas lokal adalah atomik.PowerManager
misalnya setelah memanggil metode ini? Biarkan saya memeriksa sisa metode .... mmm ok tidak. DanWakeLock
hal ini Anda dapatkan ... apa yang Anda lakukan dengan itu (memindai sisa metode lagi) ... mmm lagi tidak ada ... ok jadi mengapa mereka ada di sana? Oh ya seharusnya lebih mudah dibaca ... tapi tanpa mereka saya yakin Anda tidak menggunakannya lagi jadi saya tidak perlu membaca sisa metode.final
diperlukan pada variabel lokal dalam suatu metode, metode Anda terlalu panjang.