เหตุใดจึงต้องประกาศตัวแปรใกล้กับตำแหน่งที่ใช้


10

ฉันเคยได้ยินคนพูดว่าควรจะประกาศตัวแปรที่ใกล้เคียงกับการใช้งานมากที่สุด ฉันไม่เข้าใจสิ่งนี้

ตัวอย่างเช่นนโยบายนี้จะแนะนำให้ฉันทำ:

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

แต่นี่หมายถึงค่าโสหุ้ยในการสร้างสิ่งใหม่intเกิดขึ้นในทุก ๆ การวนซ้ำ มันจะไม่ดีกว่าที่จะใช้:

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

ได้โปรดอธิบายใครสักคน


3
มันจะเป็นภาษาที่น่าสงสารน่าสงสารมากที่ให้ทั้งสองกรณีแตกต่างกัน
Paul Tomblin

5
คุณเริ่มต้นจากหลักฐานเท็จ โปรดดูคำตอบของฉันสำหรับคำถามนี้: stackoverflow.com/questions/6919655/…
CesarGon

8
หากคุณคิดเช่นนั้นคุณไม่เหมาะสำหรับการปรับให้เหมาะสมหรือพิจารณาผลกระทบด้านประสิทธิภาพโดยทั่วไป การใช้ภาษานั้นฉลาดและถ้าคุณคิดว่ามันไม่ได้พิสูจน์ด้วยข้อมูลที่ได้จากการวัดที่เป็นกลางและมีเหตุผล

4
หากตัวอย่างโค้ดทั้งสองมีความหมายแตกต่างกันอย่างมีนัยสำคัญแสดงว่าพวกเขาทำสิ่งต่าง ๆ คุณควรใช้อันที่ทำในสิ่งที่คุณต้องการ กฎเกี่ยวกับตำแหน่งที่คุณประกาศตัวแปรจะใช้กับกรณีที่ไม่มีความแตกต่างทางความหมาย
David Schwartz

4
พิจารณาจุดสิ้นสุดฝั่งตรงข้าม - ทุกอย่างเป็นตัวแปรระดับโลก แน่นอน 'ประกาศใกล้ใช้' เป็นจุดสิ้นสุดที่ดีกว่าของสเปกตรัมนี้หรือไม่
JBRWilkinson

คำตอบ:


27

นี่เป็นกฎลักษณะเดียวในหมู่คนจำนวนมากและไม่จำเป็นต้องเป็นกฎที่สำคัญที่สุดของกฎที่เป็นไปได้ทั้งหมดที่คุณควรพิจารณา ตัวอย่างของคุณเนื่องจากมี int ไม่น่าสนใจมาก แต่คุณอาจมีวัตถุที่มีราคาแพงในลูปนั้นและอาจเป็นอาร์กิวเมนต์ที่ดีสำหรับการสร้างวัตถุนอกลูป อย่างไรก็ตามนั่นไม่ได้ทำให้มันเป็นข้อโต้แย้งที่ดีกับกฎนี้ตั้งแต่แรกมีสถานที่อื่น ๆ อีกมากมายที่สามารถนำไปใช้ที่ไม่เกี่ยวข้องกับการสร้างวัตถุที่มีราคาแพงในลูปและที่สองเป็นเครื่องมือเพิ่มประสิทธิภาพที่ดี C # ดังนั้นคุณมีเครื่องมือเพิ่มประสิทธิภาพที่ดี) สามารถยกการเริ่มต้นออกจากลูป

เหตุผลที่แท้จริงสำหรับกฎนี้ก็เป็นเหตุผลที่คุณไม่เห็นว่าทำไมจึงเป็นกฎ ผู้คนเคยเขียนฟังก์ชั่นที่มีความยาวหลายร้อยแม้กระทั่งหลายพันบรรทัดและใช้ในการเขียนในตัวแก้ไขข้อความธรรมดา (คิดว่า Notepad) โดยไม่ต้องมี Visual Studio รองรับ ในสภาพแวดล้อมนั้นการประกาศตัวแปรหลายร้อยบรรทัดห่างจากจุดที่ใช้หมายความว่าคนอ่าน

if (flag) limit += factor;

ไม่มีเงื่อนงำมากมายเกี่ยวกับธงขีด จำกัด และปัจจัยอะไร อนุสัญญาการตั้งชื่อเช่นสัญกรณ์ฮังการีได้ถูกนำมาใช้เพื่อช่วยในเรื่องนี้และดังนั้นจึงมีกฎเกณฑ์เช่นประกาศสิ่งต่าง ๆ ใกล้เคียงกับที่ใช้ แน่นอนว่าทุกวันนี้ทุกอย่างเกี่ยวกับการปรับโครงสร้างใหม่และฟังก์ชั่นโดยทั่วไปจะมีความยาวน้อยกว่าหนึ่งหน้าทำให้เป็นการยากที่จะได้ระยะห่างระหว่างจุดที่มีการประกาศสิ่งต่างๆ คุณกำลังดำเนินการในช่วง 0-20 และเล่นโวหารที่อาจ 7 ก็โอเคในกรณีนี้โดยเฉพาะในขณะที่คนที่ทำกฎจะต้องรักที่จะได้รับ 7 บรรทัดและพยายามที่จะพูดคุยกับใครบางคนจาก 700 และ ด้านบนนั้นใน Visual Studio คุณสามารถวางเมาส์เหนือสิ่งใดและดูประเภทของมันเป็นตัวแปรสมาชิกและอื่น ๆ นั่นหมายถึงความจำเป็นที่จะต้องเห็นบรรทัดที่ประกาศว่ามันลดลง

มันยังคงเป็นกฎที่ดีพอสมควรจริง ๆ แล้วมันค่อนข้างยากที่จะทำลายวันนี้และที่ไม่มีใครเคยสนับสนุนเป็นเหตุผลในการเขียนรหัสช้า มีเหตุผลเหนือสิ่งอื่นใด


ขอบคุณสำหรับคำตอบ. แต่แน่นอนโดยไม่คำนึงถึงชนิดข้อมูลอินสแตนซ์ใหม่จะถูกสร้างขึ้นในการวนซ้ำทุกครั้ง ในกรณีที่สองเราไม่ขออ้างอิงหน่วยความจำใหม่ทุกครั้ง หรือฉันได้พลาดจุด? และคุณกำลังบอกว่าเครื่องมือเพิ่มประสิทธิภาพ C # จะปรับปรุงโค้ดของฉันโดยอัตโนมัติเมื่อรวบรวมหรือไม่ ฉันไม่รู้ว่า!
James

2
ค่าใช้จ่ายในการสร้าง int นั้นเล็กมาก หากคุณกำลังสร้างบางสิ่งที่ซับซ้อนค่าใช้จ่ายจะเป็นเรื่องใหญ่
Kate Gregory

17
มันไม่ได้เป็นเพียงคำถามเกี่ยวกับความสามารถในการดูประเภทและประเภทของมัน นอกจากนี้ยังเป็นคำถามของอายุการใช้งาน หากตัวแปร "wibble" ถูกประกาศ 30 บรรทัดก่อนที่จะใช้ครั้งแรกมี 30 บรรทัดที่การใช้ "wibble" ที่ผิดพลาดอาจส่งผลให้เกิดข้อผิดพลาด หากมีการประกาศทันทีก่อนใช้งานการใช้ "wibble" ใน 30 บรรทัดก่อนหน้านี้จะไม่ส่งผลให้เกิดข้อบกพร่อง มันจะทำให้เกิดข้อผิดพลาดของคอมไพเลอร์แทน
Mike Sherrill 'Cat Recall'

ในกรณีนี้อินสแตนซ์ใหม่จะไม่ถูกสร้างขึ้นทุกลูป ตัวแปรระดับบนสุดเดียวถูกสร้างและใช้สำหรับการวนซ้ำทุกครั้ง (ดูที่ IL) แต่นั่นเป็นรายละเอียดการใช้งาน
thecoop

"ใน Visual Studio คุณสามารถเลื่อนเมาส์ไปที่อะไรก็ได้และดู" เป็นต้นนอกจากนี้ยังมีการนำทางไปยังการกำหนดซึ่งมีทางลัดF12ที่ขาดไม่ได้
StuperUser

15

การกำหนดตัวแปรภายในลูปทำให้สามารถมองเห็นโลคัลกับลูปนั้นเท่านั้น สิ่งนี้มีข้อดีอย่างน้อย 3 ข้อสำหรับผู้อ่าน:

  1. คำจำกัดความของตัวแปรและความคิดเห็นที่เกี่ยวข้องนั้นหาได้ง่าย
  2. ผู้อ่านรู้ว่าไม่เคยใช้ตัวแปรนี้ในที่อื่น (ไม่ต้องพึ่งพา)
  3. เมื่อโค้ดถูกเขียนหรือแก้ไขจะไม่มีโอกาสที่คุณจะใช้ชื่อตัวแปรเดียวกันนอกลูปเพื่ออ้างถึงตัวแปรนั้นมิฉะนั้นคุณอาจได้รับข้อผิดพลาด

สำหรับบิตประสิทธิภาพคอมไพเลอร์เป็นสมาร์ทในการสร้างคำนิยามนอกลูปในโค้ดที่ปรับให้เหมาะสม ตัวแปรจะไม่ถูกสร้างซ้ำทุกการวนซ้ำ


4

ผู้คนบอกว่าใกล้เคียงกับการใช้งานมากที่สุดพวกเขาไม่ได้บอกว่าคุณควรทำอย่างนั้นตลอดเวลาเพราะบางครั้งการประกาศตัวแปรในขอบเขตอย่างน้อยจะทำให้เกิดค่าใช้จ่ายบางส่วนเหตุผลหลักของคำสั่งนั้นคือความสามารถในการอ่าน ขอบเขตที่เล็กที่สุดที่คุณสามารถทำได้


4

แม้ว่ามันจะช่วยในการอ่าน แต่การอ่านไม่ได้เป็นข้อพิจารณาเบื้องต้นในกรณีนี้และ IDE ที่ทันสมัยไม่ได้ขัดกับความต้องการของกฎนี้

ความกังวลหลักคือตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้น หากคุณประกาศตัวแปรที่ไกลเกินไปจากการเริ่มต้นมันจะเปิดคุณถึงปัญหาที่อาจเกิดขึ้นทุกชนิด คุณอาจพบว่าตัวเองทำงานกับสิ่งที่เคยเกิดขึ้นใน RAM มาก่อนโดยบังเอิญหรือผลลัพธ์จากการคำนวณที่สูงขึ้นในฟังก์ชั่นหรือการกำหนดค่าเริ่มต้นจำลอง (เช่น 0) ที่มีคนใส่ไว้เพื่อไม่ให้คอมไพเลอร์บ่น ผู้คนจะแทรกรหัสในระหว่างการประกาศและการใช้งานของคุณโดยไม่ทราบถึงเงื่อนไขเบื้องต้นของตัวแปรนั้น ในกรณีที่เลวร้ายที่สุดการใช้งานนั้นจะเกิดขึ้นกับการทดสอบของคุณ แต่ล้มเหลวในสนาม

การประกาศตัวแปรของคุณในขอบเขตที่เล็กที่สุดเท่าที่จะเป็นไปได้และการกำหนดค่าเริ่มต้นให้เป็นค่าที่เหมาะสม ณ จุดประกาศจะช่วยหลีกเลี่ยงการปวดหัวในการบำรุงรักษามากมาย ความจริงที่ว่ามันบังคับให้อ่านง่ายขึ้นเป็นเพียงผลข้างเคียงที่ดี


1

มันไม่ใช่ "ต้อง" เป็นเพียงความเห็นฉันจะทำอะไรบางอย่าง ตัวอย่างเช่นฉันต้องการประกาศ vars ทั้งหมดในบรรทัดแรกของวิธีการเพื่อให้ฉันสามารถแสดงความคิดเห็นสิ่งที่ฉันจะทำกับ vars นั้น (แน่นอนยกเว้นว่าพวกเขาเป็นเคาน์เตอร์) คนอื่น ๆ ตามที่คุณได้ยินต้องการให้พวกเขาใกล้เคียงกับการใช้งานมากที่สุดเท่าที่จะทำได้ (ดังในตัวอย่างที่สองที่คุณเขียน) อย่างไรก็ตามตัวอย่างแรกที่คุณให้นั้นย่อมเป็น "ข้อผิดพลาด" (ในแง่ที่ว่ามันจะทำให้เกิดค่าใช้จ่ายตามที่คุณเข้าใจ)

คุณต้องเลือกวิธีการของคุณและทำตาม


2
มันไม่ใช่แค่ความเห็นใช่ไหม? การวิจัยวิศวกรรมซอฟต์แวร์ไม่ได้บันทึกความสัมพันธ์ระหว่างเวลาสดกับจำนวนของบั๊กตั้งแต่อย่างน้อย 1980
Mike Catrill 'Cat Recall'

1

ตัวอย่างทั้งสองของคุณนั้นเป็นรหัสที่แตกต่างกันไป (ตัวอย่างที่ถูกตัดทอนของคุณทิ้งความแตกต่างไว้โดยไม่มีความแตกต่าง แต่ในโค้ดที่ไม่สำคัญมันทำให้เกิดความแตกต่าง) ไซต์ที่กฎของคุณอยู่ภายใต้การพิจารณาที่กำหนดไว้ตามที่ระบุโดย "... เท่าที่จะทำได้"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.