Mengapa mendeklarasikan variabel dekat dengan tempat mereka digunakan?


10

Saya telah mendengar orang mengatakan bahwa variabel harus dideklarasikan sedekat mungkin dengan penggunaannya. Saya tidak mengerti ini.

Misalnya, kebijakan ini menyarankan saya untuk melakukan ini:

foreach (var item in veryLongList) {
  int whereShouldIBeDeclared = item.Id;
  //...
}

Tapi tentu saja ini berarti overhead untuk menciptakan yang baru intterjadi pada setiap iterasi. Bukankah lebih baik menggunakan:

int whereShouldIBeDeclared;
foreach (var item in veryLongList) {
  whereShouldIBeDeclared = item.Id;
  //...
}

Tolong bisakah seseorang menjelaskan?


3
Ini akan menjadi bahasa yang sangat buruk yang memperlakukan kedua kasus itu secara berbeda.
Paul Tomblin

5
Anda seorang pemula dari premis yang salah. Silakan lihat jawaban saya untuk pertanyaan ini: stackoverflow.com/questions/6919655/…
CesarGon

8
Jika Anda berpikir seperti itu, Anda tidak cocok untuk mengoptimalkan atau bahkan mempertimbangkan dampak kinerja secara umum. Implementasi bahasa cerdas, dan jika Anda pikir tidak, buktikan dengan data keras yang diperoleh melalui tolok ukur realistis dan tidak bias.

4
Jika dua contoh kode memiliki perbedaan semantik yang signifikan, maka mereka melakukan hal yang berbeda. Anda harus menggunakan yang melakukan apa yang ingin Anda lakukan. Aturan tentang tempat Anda mendeklarasikan variabel hanya berlaku untuk kasus di mana tidak ada perbedaan semantik.
David Schwartz

4
Pertimbangkan ujung skala yang berlawanan - semuanya menjadi variabel global. Tentunya 'menyatakan penggunaan dekat' adalah akhir yang lebih baik dari spektrum ini?
JBRWilkinson

Jawaban:


27

Ini adalah satu aturan gaya di antara banyak aturan, dan ini belum tentu aturan terpenting dari semua aturan yang mungkin bisa Anda pertimbangkan. Contoh Anda, karena termasuk int, tidak super menarik, tetapi Anda tentu bisa memiliki objek yang mahal untuk dikonstruksi di dalam loop itu, dan mungkin argumen yang bagus untuk membangun objek di luar loop. Namun, itu tidak menjadikannya argumen yang bagus terhadap aturan ini sejak pertama, ada banyak tempat lain yang bisa diterapkan yang tidak melibatkan pembuatan objek mahal dalam satu lingkaran, dan kedua, pengoptimal yang baik (dan Anda telah menandai C #, sehingga Anda memiliki pengoptimal yang baik) dapat mengangkat inisialisasi keluar dari loop.

Alasan sebenarnya untuk aturan ini juga adalah alasan Anda tidak melihat mengapa itu aturan. Orang biasa menulis fungsi yang panjangnya ratusan, bahkan ribuan baris dan mereka biasa menulisnya di editor teks biasa (pikirkan Notepad) tanpa jenis dukungan yang disediakan Visual Studio. Dalam lingkungan itu, mendeklarasikan variabel ratusan baris dari tempat itu digunakan berarti orang tersebut membaca

if (flag) limit += factor;

tidak memiliki banyak petunjuk tentang apa bendera, batas dan faktor itu. Konvensi penamaan seperti notasi Hungaria diadopsi untuk membantu dengan ini, dan begitu juga aturan seperti menyatakan hal-hal yang dekat dengan tempat mereka digunakan. Tentu saja, hari-hari ini, ini semua tentang refactoring, dan fungsi umumnya kurang dari satu halaman, membuatnya sulit untuk mendapatkan jarak yang sangat jauh antara di mana hal-hal dinyatakan dan di mana mereka digunakan. Anda beroperasi dalam kisaran 0-20 dan kebawelan bahwa mungkin 7 adalah ok dalam contoh khusus ini, sementara orang yang membuat aturan akan DICINTAI untuk mendapatkan 7 baris jauhnya dan mencoba untuk berbicara dengan seseorang turun dari 700. Dan pada Selain itu, di Visual Studio, Anda dapat mengarahkan mouse ke apa saja dan melihat tipenya, apakah itu variabel anggota, dan sebagainya. Itu berarti kebutuhan untuk melihat garis yang menyatakan itu berkurang.

Ini masih aturan yang cukup baik, yang sebenarnya cukup sulit untuk dilanggar hari ini, dan yang tidak ada yang menganjurkan sebagai alasan untuk menulis kode lambat. Masuk akal, di atas segalanya.


Terima kasih atas jawaban anda. Tapi tentu saja terlepas dari tipe data, contoh baru dibuat pada setiap iterasi, dengan cara apa pun saya melakukannya? Hanya saja dalam kasus kedua kami tidak meminta referensi memori baru setiap kali. Atau apakah saya melewatkan intinya? Dan apakah Anda mengatakan bahwa pengoptimal C # akan secara otomatis meningkatkan kode saya saat dikompilasi? Saya tidak tahu itu!
James

2
Biaya pembuatan int adalah kecil. Jika Anda membangun sesuatu yang rumit, biaya overhead akan menjadi lebih besar.
Kate Gregory

17
Bukan hanya pertanyaan untuk bisa melihat jenisnya dan semacamnya. Ini juga pertanyaan seumur hidup. Jika variabel "wibble" dinyatakan 30 baris sebelum pertama kali digunakan, ada 30 baris di mana penggunaan "wibble" yang salah dapat menghasilkan bug. Jika dideklarasikan segera sebelum digunakan, menggunakan "wibble" di 30 baris sebelumnya tidak akan menghasilkan bug. Ini akan menyebabkan kesalahan kompiler sebagai gantinya.
Mike Sherrill 'Cat Recall'

Dalam hal ini, sebuah instance baru tidak dibuat setiap loop. Variabel tingkat atas tunggal dibuat dan digunakan untuk setiap iterasi (lihat IL). Tapi itu detail implementasi.
thecoop

"di Visual Studio, Anda dapat mengarahkan mouse ke apa saja dan melihat" dll. Ada juga Navigasi ke definisi, yang memiliki pintasan F12yang sangat diperlukan.
StuperUser

15

Menentukan variabel di dalam loop membuatnya hanya visibilitas ke loop itu saja. Ini memiliki setidaknya 3 keuntungan bagi pembaca:

  1. Definisi variabel dan komentar terkait mudah ditemukan
  2. Pembaca tahu bahwa variabel ini tidak pernah digunakan di tempat lain (tidak ada ketergantungan untuk diharapkan)
  3. Ketika kode ditulis atau diedit, tidak ada kemungkinan Anda bisa menggunakan nama variabel yang sama di luar loop untuk merujuk ke variabel itu jika tidak, Anda bisa mendapatkan kesalahan.

Adapun bit efisiensi, kompiler pintar untuk menghasilkan definisi di luar loop dalam kode yang dioptimalkan yang dihasilkan. Variabel tidak akan dibuat setiap iterasi loop.


4

Orang mengatakan sedekat mungkin dengan penggunaannya , Mereka tidak mengatakan Anda harus melakukan itu sepanjang waktu, karena mereka adalah beberapa kasus yang menyatakan variabel dalam lingkup paling sedikit akan menyebabkan beberapa overhead. Alasan utama pernyataan itu adalah Keterbacaan dan pemberian variabel ruang lingkup terkecil yang Anda bisa.


4

Meskipun membantu dengan keterbacaan, keterbacaan bukan pertimbangan utama dalam kasus ini, dan IDE modern tidak meniadakan kebutuhan akan aturan ini.

Perhatian utama adalah variabel tidak diinisialisasi. Jika Anda mendeklarasikan variabel yang terlalu jauh dari inisialisasi, itu akan membuka Anda untuk semua jenis masalah potensial. Anda mungkin menemukan diri Anda secara tidak sengaja bekerja dengan apa pun yang ada di RAM sebelumnya, atau hasil dari penghitungan fungsi yang lebih tinggi, atau inisialisasi tiruan (seperti 0) yang dimasukkan seseorang hanya agar kompiler tidak mengeluh. Orang-orang akan memasukkan kode di antara deklarasi dan penggunaan Anda tanpa mengetahui prasyarat implisit Anda untuk variabel itu. Dalam kasus terburuk, penggunaan itu hanya akan berfungsi dalam pengujian Anda tetapi gagal di lapangan.

Mendeklarasikan variabel Anda dalam ruang lingkup sekecil mungkin, dan menginisialisasi mereka ke nilai yang tepat pada saat deklarasi akan menghindari banyak sakit kepala pemeliharaan. Fakta bahwa itu mendorong peningkatan keterbacaan hanyalah efek samping yang bagus.


1

Itu bukan "keharusan". Itu hanya pendapat, saya cara untuk melakukan sesuatu. Sebagai contoh, saya suka mendeklarasikan semua vars di baris pertama metode sehingga saya bisa berkomentar apa yang akan saya lakukan dengan vars itu (tentu saja kecuali mereka adalah counter). Orang lain, seperti yang Anda dengar, ingin menempatkan mereka sedekat mungkin dengan penggunaannya (seperti pada contoh kedua yang Anda tulis). Bagaimanapun, contoh pertama yang Anda berikan tentu merupakan "kesalahan" (dalam arti bahwa itu akan menyebabkan overhead seperti yang Anda mengerti).

Anda cukup memilih cara Anda dan mengikutinya.


2
Bukan hanya opini, bukan? Bukankah penelitian rekayasa perangkat lunak mendokumentasikan hubungan antara waktu hidup dan jumlah bug sejak setidaknya tahun 1980-an?
Mike Sherrill 'Cat Recall'

1

Dua contoh Anda adalah kode yang berbeda secara fungsional, tidak dapat dipertukarkan. (Contoh stripped down Anda membuatnya menjadi perbedaan tanpa perbedaan, tetapi dalam kode non-sepele itu memang membuat perbedaan). Aturan situs Anda selalu tunduk pada pertimbangan pelingkupan, seperti yang ditunjukkan oleh "... mungkin".

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.