นี่เป็นการใช้ค่าคงที่ที่เป็นสัญลักษณ์มากเกินไปหรือไม่?


34

ฉันค่อนข้างใหม่สำหรับวิศวกรรมซอฟต์แวร์และเพื่อเป็นแบบฝึกหัดการเรียนรู้ฉันเขียนเกมหมากรุก เพื่อนของฉันดูและชี้ให้เห็นว่ารหัสของฉันดูเหมือน

for (int i = 0; i < 8; i++){
    for (int j = 0; j < 8; j++){

ในขณะที่เขายืนยันว่ามันควรจะเป็นแทน

for (int i = 0; i < CHESS_CONST; i++){
    for (int j = 0; j < CHESS_CONST; j++){

ด้วยชื่อสัญลักษณ์ที่ดีกว่าที่ฉันไม่สามารถนึกได้ตอนนี้

ตอนนี้แน่นอนฉันรู้ว่าหลีกเลี่ยงการใช้หมายเลขเวทย์มนตร์ แต่ฉันรู้สึกเหมือนตั้งแต่

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

ไม่จำเป็นต้องมีค่าคงที่เชิงสัญลักษณ์

แล้วพวกคุณคิดอย่างไร overkill นี้หรือฉันควรจะไปกับการประชุมและใช้สัญลักษณ์?


46
CHESS_CONST นั้นแย่กว่าการใช้หมายเลข 8 แต่ค่าคงที่ที่มีชื่อที่สื่อความหมายจะเป็นการปรับปรุง คุณบอกว่าทุกคนควรรู้ว่า 8 หมายถึงอะไรในรหัส แต่สิ่งนี้ไม่เป็นความจริง ตัวอักษรจำนวนเต็มที่ไม่มีบริบทอาจหมายถึงจำนวนของสิ่งต่าง ๆ เช่นจำนวนการเคลื่อนไหวจำนวนชิ้นบนกระดานและอื่น ๆ ชื่อที่สื่อความหมายสำหรับค่าคงที่จะทำให้ความตั้งใจชัดเจนและด้วยเหตุนี้จึงทำให้เข้าใจรหัสได้ง่ายขึ้น
JacquesB

43
โดยส่วนตัวแล้วสิ่งที่ฉันพบว่าสั่นสะเทือนยิ่งกว่าจำนวนเวทย์มนตร์คือชื่อiและjตัวแปรลูป ฉันไม่สามารถใช้ชีวิตของฉันได้ว่าใครควรจะเป็นตัวแทนของอันดับและคนที่ควรจะเป็นตัวแทนของไฟล์ อันดับอยู่ในช่วง 1..8 และไฟล์มีตั้งแต่ a .. h แต่ในกรณีของคุณทั้งสองiและjอยู่ในช่วง 0..7 ดังนั้นมันจึงไม่ช่วยฉันดูว่าอันไหน มีวิกฤตการขาดแคลนจดหมายระหว่างประเทศที่ฉันไม่รู้หรือมีอะไรผิดปกติกับการเปลี่ยนชื่อพวกเขาเป็นrankและfile?
Jörg W Mittag

4
เล่นผู้สนับสนุนของปีศาจเป็นครั้งที่สอง; ลองนึกภาพการอ่านรหัสหมากรุกของใครบางคนที่พวกเขาใช้เวทมนตร์หมายเลข 8 คุณคิดว่าคุณรู้ไหมว่ามันใช้ทำอะไร? คุณมั่นใจได้อย่างไร 100% มีความเป็นไปได้ไหมที่มันจะมีความหมายอย่างอื่น? มันจะไม่ดีไปกว่านี้ถ้าคุณไม่จำเป็นต้องตั้งสมมติฐาน? คุณอาจใช้เวลาในการติดตามรหัสนานเท่าใดเพื่อดูว่าสมมติฐานของคุณถูกต้องหรือไม่ คุณจะใช้เวลาน้อยลงหรือไม่หากรหัสมีการจัดทำเอกสารด้วยตนเองมากกว่าโดยใช้ชื่อที่มีความหมายและลึกซึ้งแทน
Ben Cottrell

16
@JacquesB: แน่นอน มี 8 อันดับ 8 ไฟล์ 8 เบี้ย เอ็นจิ้นหมากรุกบางตัวใช้ระบบคะแนนซึ่งมีบางชิ้นบางฟิลด์และบางท่ามีคะแนนติดอยู่กับมันและเอ็นจิ้นเลือกการเคลื่อนที่ด้วยคะแนนสูงสุด 8 อาจเป็นคะแนนดังกล่าว 8 อาจเป็นความลึกการค้นหาเริ่มต้น มันอาจจะเป็นอะไรที่สวยมาก
Jörg W Mittag

9
ฉันต้องการพิจารณาโดยใช้ห่วง foreach foreach(var rank in Ranks)เช่น ฉันจะพิจารณาการรวมลูปทั้งสองเป็นหนึ่งเดียวโดยที่แต่ละองค์ประกอบเป็นอันดับ (ไฟล์, ไฟล์)
CodesInChaos

คำตอบ:


101

IMHO เพื่อนของคุณถูกต้องในการใช้ชื่อสัญลักษณ์แม้ว่าฉันคิดว่าชื่อควรมีความหมายมากกว่า (เหมือนBOARD_WIDTHแทนCHESS_CONST)

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

ดูโพสต์ SE.SEนี้ในอดีตสำหรับการสนทนาว่าจะเลือกชื่อสำหรับหมายเลขได้อย่างไร

ในฐานะที่เป็นหมายเหตุด้านข้างเนื่องจากมันถูกกล่าวถึงที่นี่ในความคิดเห็น : ถ้าในโค้ดของโปรแกรมจริงมันมีความสำคัญหากตัวแปรiอ้างถึงแถวและjคอลัมน์ของบอร์ดหรือในทางกลับกันก็แนะนำให้เลือกชื่อตัวแปรที่ ทำให้ความแตกต่างชัดเจนเช่นและrow colประโยชน์ของชื่อดังกล่าวคือพวกเขาทำให้โค้ดผิด


22
ฉันอยากจะเพิ่มถ้า OP ได้เขียนโปรแกรมหมากรุกที่ยอดเยี่ยมจริง ๆ แล้วต้องการขยายมันเพื่อรวมหมากรุก 3D หรือตัวแปรอื่น ๆ ดังนั้นสิ่งที่ 8s ที่ต้องเปลี่ยนจะเป็นสิ่งที่ท้าทาย
Steve Barnes

32
@SteveBarnes: ฉันพยายามหลีกเลี่ยงการโต้เถียงเช่นนี้เพราะมันนำไปสู่การโต้กลับที่ง่ายเกินไปเช่น"ฉันคิดว่ามันไม่เหมือนที่เคยทำให้โปรแกรมนี้เป็นเกมประเภทที่แตกต่างกันดังนั้นฉันจึงสามารถทิ้งเวทมนต์หมายเลข 8 ไว้ "
Doc Brown

4
@IllusiveBrian นั่นเป็นอาร์กิวเมนต์ "straw man" แบบคลาสสิคด้วยเหตุผลสองประการ: (1) การกำหนดค่าคงที่ไม่ได้หมายความว่าโปรแกรมเมอร์ยังไม่สามารถพิมพ์ "8" (ไม่ว่าจะโดยอุบัติเหตุการออกแบบหรือการปองร้าย!) และ (2) เพียงเพราะมีค่าคง BOARD_WIDTH = 8 ไม่ทำให้ BOARD_WIDTH เป็นค่าคงที่ที่ถูกต้องในการใช้งานในบางสถานที่ในโปรแกรม
alephzero

3
@Blrfl ... หรือจะนำไปสู่การ overengineering รหัส เป็นความรับผิดชอบของนักพัฒนาในการตระหนักถึงสิ่งที่สามารถเปลี่ยนแปลงได้ในอนาคตและรหัสตาม การเข้ารหัสเช่นข้อกำหนดจะไม่เปลี่ยนแปลงทำให้เกิดปัญหา แต่สิ่งอื่น ๆ ที่ไม่ดีขึ้น
Malcolm

4
@corsiKa เมื่อตัวแปรลูปสอดคล้องกับแกนทางกายภาพพวกเขาควรจะชื่อ x, y หรือแถว, col หรือสำหรับหมากรุก, ไฟล์, อันดับ
user949300

11

ตกลงนี่เป็นความเห็นที่ฉันมี:

กำจัดตัวเลขมายากลเป็นความคิดที่ดี มีแนวคิดที่รู้จักกันในชื่อ DRY ซึ่งมักจะมีการบิดเบือนความจริง แต่ความคิดคือคุณไม่ได้ทำซ้ำความรู้เกี่ยวกับแนวคิดในโครงการของคุณ ดังนั้นถ้าคุณมีคลาสที่เรียกว่า ChessBoard คุณสามารถคงค่าคงที่เรียกว่า BOARD_SIZE หรือ ChessBoard.SIZE ที่แนบมา วิธีนี้มีแหล่งเดียวสำหรับข้อมูลนี้ นอกจากนี้ยังช่วยให้สามารถอ่านได้ในภายหลัง:

for (int i = 0; i < ChessBoard.SIZE; i++){
  for (int j = 0; j < ChessBoard.SIZE; j++){

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

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


8
ดูเหมือนว่าจะทำซ้ำคะแนนที่ทำไว้แล้วและอธิบายในคำตอบที่ดีที่สุด
gnat

-7

สิ่งที่คุณต้องการคือการกำจัดอาการคลื่นไส้โฆษณาที่อ้างอิงถึงค่าคงที่ไม่ว่าพวกเขาจะตั้งชื่อหรือเปล่า:

for_each_chess_square (row, col) {
  /*...*/
}

หากคุณกำลังจริงจะเพิ่มจำนวนอย่างต่อเนื่องโดยการทำซ้ำเช่นลูปและ whatnot 8จะดีที่สุดที่จะติดกับ

8เป็นการอธิบายตนเอง ไม่ใช่มาโครที่หมายถึงอย่างอื่น

คุณไม่ได้เปลี่ยนเป็นโปรแกรมหมากรุก 9x9 และถ้าคุณทำการเพิ่มจำนวน 8 จะไม่เป็นปัญหาใหญ่

เราสามารถค้นหาฐานรหัส 150,000 บรรทัดสำหรับโทเค็น 8 และจำแนกว่าสิ่งที่เกิดขึ้นหมายถึงอะไรในไม่กี่วินาที

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

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

สมมติว่าในอนาคตคุณต้องการสนับสนุนขนาดกระดานทางเลือก ในกรณีที่ลูปเหล่านั้นจะมีการเปลี่ยนแปลงไม่ว่าจะใช้ชื่ออย่างต่อเนื่องหรือ8เพราะขนาดจะถูกเรียกโดยการแสดงออกบางอย่างเช่นและboard.width board.heightหากคุณมีBOARD_SIZEแทน8สถานที่เหล่านี้จะง่ายต่อการค้นหา นั่นคือความพยายามน้อยลง อย่างไรก็ตามคุณต้องไม่ลืมเกี่ยวกับความพยายามในการแทนที่8ด้วยBOARD_SIZEในสถานที่แรก ความพยายามโดยรวมไม่ได้ลดลง การส่งรหัสผ่านหนึ่งครั้งเพื่อเปลี่ยน8เป็นBOARD_SIZEแล้วอีกส่วนหนึ่งเพื่อสนับสนุนมิติทางเลือกนั้นไม่ได้ราคาถูกกว่า8การสนับสนุนมิติอื่น

เราสามารถดูได้จากการวิเคราะห์ความเสี่ยง / ผลประโยชน์ที่เป็นเป้าหมายอย่างเย็นชา โปรแกรมมีค่าคงที่เปลือยเปล่าในตอนนี้ หากสิ่งเหล่านี้ถูกแทนที่ด้วยค่าคงที่จะไม่มีประโยชน์ โปรแกรมเหมือนกัน การเปลี่ยนแปลงใด ๆ มีความเสี่ยงที่ไม่ใช่ศูนย์ ในกรณีนี้มันมีขนาดเล็ก แต่ถึงกระนั้นก็ไม่มีความเสี่ยงที่ควรได้รับโดยไม่มีประโยชน์ ในการ "ขาย" การเปลี่ยนแปลงในการเผชิญกับเหตุผลนี้เราต้องตั้งสมมติฐานผลประโยชน์: ผลประโยชน์ในอนาคตซึ่งจะช่วยให้มีโปรแกรมที่แตกต่างกัน: เวอร์ชันในอนาคตของโปรแกรมที่ไม่มีอยู่ในขณะนี้ หากมีการวางแผนโปรแกรมดังกล่าวสมมติฐานนี้และการใช้เหตุผลที่เกี่ยวข้องนั้นเป็นจริงโดยสุจริตและควรดำเนินการอย่างจริงจัง

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

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


13
8ไม่ใช่การอธิบายตัวเองมันเป็นตัวเลขที่อาจหมายถึงอะไรก็ได้ และบางทีพวกเขาต้องการทำเกมหมากรุกขนาด 9x9 ทำไมล่ะ? หากคุณมี 150,000 บรรทัดของรหัสไม่มีทางที่คุณจะสามารถจดจำความ8หมายของแต่ละวิธีในรหัสและแม้ว่าคุณจะทำได้ทำไมคุณจะ? นั่นเป็นเพียงความยุ่งยากมากเป็นพิเศษ เท่าที่การทำให้เป็นโมดูลนั้นการแทนที่8ด้วยบางสิ่งบางอย่างNUM_RANKSนั้นไม่ได้ส่งผลกระทบต่อความเป็นโมดูล แต่อย่างใดมันช่วยได้เพราะทำให้โค้ดง่ายขึ้นสำหรับคนจรจัด
Jerfov2

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

1
"แต่คุณต้องไม่ลืมเกี่ยวกับความพยายามของการแทนที่8ด้วยBOARD_SIZEในสถานที่แรก" - เวลาที่คุณต้องการใช้เวลา scrutinizing มากกว่ารหัสของคุณพยายามที่จะคิดสิ่งที่แต่ละคน8จะอยู่ในเดือนที่โปรแกรมของคุณตั้งแต่วันนี้ส่วนใหญ่จะเกินเวลาที่ใช้แทนที่8ด้วย ค่าคงที่ระดับโมดูลที่มีความหมาย
Christian Dean

1
@doppelganger สถานการณ์นั้นมีอยู่ที่นี่แล้ว ฉันไม่ได้พูดใช้โปรแกรมหมากรุกที่ใช้ค่าคงที่และแทนที่ด้วย 8 หรือฉันก็บอกว่า "วางแผนที่จะไม่ใช้ค่าคงที่ในโปรแกรมหมากรุกที่ยังไม่ได้เขียน"
Kaz

1
@Kaz ทำไมคุณต้องทำให้ตัวเองต้องอ่านรหัสทั้งหมดประมาณ 8 และบางทีบางครั้งก็ผิดบริบทเมื่อคุณสามารถใช้เวลาเพิ่มอีก 3 วินาทีในชื่อที่มีความหมาย? สำหรับการรู้ค่าที่แท้จริงของค่าคงที่มันจะง่ายกว่าการค้นหาค่าที่แน่นอนสำหรับตัวแปรมากกว่าการพยายามย้อนกลับ - วิศวกรว่าจำนวนเต็มมายากลในรหัสหมายความว่าอย่างไร
Jerfov2
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.