มี / ทุกคนสามารถท้าทายลุงบ๊อบบนความรักของเขาในการลบ“ วงเล็บปีกกาที่ไร้ประโยชน์” หรือไม่?


94

ฉันเกลียดการอ้างอิงเนื้อหาที่ชำระเงินแล้ว แต่วิดีโอนี้แสดงสิ่งที่ฉันกำลังพูดถึง 12 นาทีอย่างแม่นยำใน Robert Martin ดูที่นี่:

บางรหัส

และกล่าวว่า "หนึ่งในสิ่งที่ฉันชอบทำคือกำจัดวงเล็บปีกกาที่ไร้ประโยชน์" เมื่อเขาเปลี่ยนมันเป็นสิ่งนี้:

รหัสเพิ่มเติม

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

เพื่อความเป็นธรรมกับลุงบ๊อบเขาได้ทำการปรับเปลี่ยนวิธีการจาวาแบบยาวลงไปสู่ฟังก์ชั่นเล็ก ๆ น้อย ๆ ที่ผมเห็นว่าสามารถอ่านได้ง่ายขึ้น เมื่อเขาเปลี่ยนมันเสร็จ (22.18) ดูเหมือนว่า:

ยังรหัสเพิ่มเติม

ฉันสงสัยว่าควรจะตรวจสอบการลบวงเล็บหรือไม่ ฉันคุ้นเคยกับแนวทางปฏิบัติที่ดีที่สุดแล้ว ลุงบ๊อบจะถูกท้าทายในประเด็นนี้หรือไม่? ลุงบ๊อบปกป้องความคิดนี้หรือไม่?


6
ฉันลงคะแนนเพื่อปิดคำถามนี้เป็นนอกหัวข้อเนื่องจากคำตอบใด ๆ ที่เป็นไปได้คือ "ไม่" หรือ "ใช่" และนี่คือการอ้างอิง
Blrfl

35
ให้เวลาสองสามปีบางทีเขาอาจลบ linebreak ที่ไร้ประโยชน์ด้วยและ "ถ้า (ดู (บางสิ่ง)) พูด (บางสิ่ง);" จริงจะเป็นบรรทัดของรหัส ;-)
สตีฟเจสซอพ

8
@SteveJessop ยินดีที่ได้ทราบว่าฉันปีต่อ ๆ ไป : D หากไม่มีบรรทัดใหม่ไม่มีความเสี่ยงของข้อบกพร่องที่น่าอับอาย การเพิ่ม / ลบวงเล็บปีกกาตามต้องการเป็นค่าใช้จ่ายเพิ่มเติม แต่จะได้รับการบันทึกมากขึ้นเมื่ออ่าน
maaartinus

9
ลุงบ๊อบทำคะแนนได้ดีในการทำ Clean Code ในหน้า 35 หากifบล็อกมีเพียงหนึ่งบรรทัดเท่านั้นมันไม่สำคัญ หากคุณต้องการเพิ่มบรรทัดมากขึ้นควรเป็นฟังก์ชั่นอื่นที่ช่วยลดการifบล็อกกลับเป็นหนึ่งบรรทัด (การเรียกใช้ฟังก์ชัน) หากคุณปฏิบัติตามนั้นการจัดฟันก็ไม่สำคัญ -เลย

13
เขาควรจะทำอย่างไรreturn (page==null) ? "" : includePage(mode,page);ถ้าเขาเป็นคนที่เข้าใจสั้น ๆ ... ฉันคิดว่าสไตล์ที่ไม่รั้งร่อนั้นเจ๋งจนฉันเริ่มพัฒนาแอพอย่างมืออาชีพ เสียงที่แตกต่างข้อผิดพลาดที่เป็นไปได้ ฯลฯ การจัดฟันอยู่ที่นั่นตลอดเวลาช่วยให้คุณประหยัดเวลาและค่าใช้จ่ายที่คุณจะต้องแนะนำในภายหลัง
vaxquis

คำตอบ:


47

การอ่านไม่ใช่เรื่องเล็ก

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

ฉันไม่เคยท้าทายใครที่นับถือศาสนาเกี่ยวกับการใช้เครื่องมือจัดฟันหลังจากความล้มเหลวเล็กน้อยนั้น

ดังนั้นฉันจึงเห็นประโยชน์ของการอ่าน แต่ฉันก็ตระหนักถึงปัญหาที่อาจเกิดขึ้นเมื่อคุณละทิ้งการจัดฟันออก

ฉันจะไม่พยายามค้นหาการศึกษาหรือความเห็นของใครบางคนที่ตีพิมพ์ ทุกคนมีหนึ่ง (ความเห็นนั่นคือ) และเพราะมันเป็นปัญหาโวหารความเห็นหนึ่งเป็นเรื่องที่ดีเหมือนกัน คิดเกี่ยวกับปัญหาด้วยตัวคุณเองประเมินข้อดีข้อเสียและทำใจของคุณเอง หากร้านค้าที่คุณทำงานมีมาตรฐานการเข้ารหัสที่ครอบคลุมปัญหานี้เพียงทำตามนั้น


7
ฉันรู้สึกแย่เมื่อเร็ว ๆ นี้เมื่อการเยื้องออกและทำให้เข้าใจผิด
Andy

12
เพราะมันเป็น C โดยไม่ต้องGCC -Wmisleading-indentation6
wchargin

2
@CandiedOrange: มันคือลุงบ๊อบที่ท้าทายความเชื่อ
Robert Harvey

1
@RobertHarvey ฉันไม่ได้ทำให้ชัดเจนว่า? ใช่เขาท้าทายความเชื่อ เขาท้าทายความเชื่อของฉัน ฉันแค่พยายามเป็นนักเรียนที่ดีและอย่างน้อยก็ลองพิจารณาดู แต่ลุงบ๊อบมีเสน่ห์ดึงดูดมากมันทำให้ฉันสงสัยว่าฉันสูญเสียความเที่ยงธรรมหรือเปล่า ดังนั้นฉันขอร้องให้ช่วยหายาแก้พิษก่อนที่ฉันจะดื่ม koolaid
candied_orange

1
@CandiedOrange: มันเป็นบริบทอย่างแน่นอน คนที่เพิ่งยอมรับความเชื่อไม่ได้พิจารณาบริบท; เป็นกฎที่ยังคงใช้กฎ "คืนเดียวเท่านั้น" ในภาษาที่ได้รับการจัดการนานหลังจากที่กฎนั้นมีอายุการใช้งานที่ยาวนานกว่าประโยชน์และได้กลายเป็นอุปสรรค
Robert Harvey

133

คุณสามารถค้นหาโปรโมชั่นที่เผยแพร่หรือการปฏิเสธสไตล์ที่ไม่มีการรั้งได้ที่นี่หรือที่นี่หรือที่ใดก็ตามที่เพิงจักรยานถูกทาสี

ก้าวออกจากจักรยานหายจำความผิดพลาด OS X / iOS SSL ที่ยอดเยี่ยมของปี 2014 ได้หรือไม่

if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0)
    goto fail;
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
    goto fail;
    goto fail;
if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
    goto fail;

ใช่ "เกิด" โดยไม่มีการปิดกั้นบล็อกhttps://www.imperialviolet.org/2014/02/22/applebug.html

การตั้งค่าอาจขึ้นอยู่กับสไตล์รั้ง ถ้าฉันต้องเขียน

if (suiteSetup)
{
    includePage(mode, suiteSetup);
}

ฉันอาจจะกินพื้นที่มากเกินไป แต่

if (suiteSetup) {
    includePage(mode, suiteSetup);
}

ใช้เพียงหนึ่งบรรทัด "พิเศษ"


ฉันรู้ว่าคุณไม่ได้ถาม แต่ถ้าฉันทำงานคนเดียวฉันเป็นคนนอกรีต หากฉันลบเครื่องมือจัดฟันฉันต้องการ

if (suiteSetup != null) includePage(mode, suiteSetup);

มันไม่มีปัญหาด้านภาพเช่นเดียวกับบั๊กสไตล์ SSL ของ iOS แต่จะบันทึกบรรทัดที่ "ไม่จำเป็น" ได้มากกว่าที่ลุงบ็อบทำ;) อ่านได้ดีถ้าคุณคุ้นเคยกับมันและมีการใช้งานหลักใน Ruby ( includePage(mode, suiteSetup) unless suiteSetup.nil?) อืมเพิ่งรู้ว่ามีความคิดเห็นมากมาย


13
นอกจากนี้หากคุณใช้} else[if(...)] {นั่นไม่ได้เพิ่มบรรทัดพิเศษใด ๆ ดังนั้นจึงเพิ่มบรรทัดพิเศษได้เพียงหนึ่งบรรทัดในทุกสิ่ง
Random832

12
ฉันดีใจที่คุณแสดงข้อผิดพลาด SSL ของ iOS ตั้งแต่นั้นมาฉันพบว่าตัวเองใช้เหล็กดัดฟันในสถานการณ์เช่นนี้มากขึ้นเรื่อย ๆ
Zach Lipton

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

16
"การข้ามไปล้มเหลว" ไม่ได้เกิดจากการบล็อกบรรทัดเดียวมันเกิดจากการเขียนโปรแกรมเลอะเทอะแม้แต่การตรวจสอบโค้ดที่ผิดเพี้ยนไปและไม่ใช่แม้แต่การก้าวผ่านโค้ดด้วยตนเอง
gnasher729

35
Meh การขาดการจัดฟันไม่ได้ทำให้เกิดปัญหานั้น โปรแกรมเมอร์ที่น่ากลัว (และขาดการตรวจสอบรหัสการทดสอบ) แก้ไขปัญหาโดยการยิงผู้ที่รับผิดชอบไม่ใช่โดยการผูกมือพวกเราที่เหลือ!
Lightness Races ในวงโคจร

62

ลุงบ๊อบมีการป้องกันหลายชั้นต่อความผิดพลาดที่ไม่ธรรมดาเมื่อ "การจัดฟันอยู่เสมอ" เป็นภูมิปัญญาที่แพร่หลาย:

  1. การตั้งค่าส่วนบุคคลที่แข็งแกร่งสำหรับเงื่อนไขแบบบรรทัดเดียวดังนั้นแบบหลายบรรทัดจึงโดดเด่นและได้รับการตรวจสอบอย่างละเอียด
  2. ตัวแก้ไขที่จะทำให้เกินโดยอัตโนมัติเมื่อคุณแทรกบรรทัดที่สอง
  3. ชุดทดสอบหน่วยที่สมบูรณ์ที่เขาทำงานอย่างต่อเนื่อง
  4. ชุดการทดสอบการรวมที่สมบูรณ์
  5. การตรวจสอบโดยเพื่อนทำก่อนที่จะรวมรหัสของเขา
  6. รันการทดสอบทั้งหมดอีกครั้งโดยเซิร์ฟเวอร์การรวมอย่างต่อเนื่อง
  7. ทดสอบโดยแผนกคุณภาพผลิตภัณฑ์

ฉันคิดว่าถ้ามีคนตีพิมพ์ความท้าทายให้กับลุงบ๊อบเขาคงจะมีข้อโต้แย้งที่ดีในประเด็นข้างต้น นี่เป็นหนึ่งในข้อผิดพลาดที่ง่ายที่สุดในการจับ แต่เนิ่น ๆ


16
ฉันไม่เคยกลัวที่จะล้มเหลวในแบบที่ฉันกลัวสิ่งที่ล้มเหลวอย่างเงียบ ๆ อย่างน้อยคุณก็รู้ว่ามีอะไรผิดพลาดเกิดขึ้น ด้านหลังของสมองของฉันรู้สึกเสียวซ่าเมื่อฉันเห็นสิ่งนี้ มัน tingles while(true);{break;}ทางเดียวกันมันไม่เมื่อฉันเห็น หากมีบริบทที่ถูกต้องสำหรับเรื่องนี้มันจะต้องใช้เวลาสักพักกว่าจะผ่านมันไป
candied_orange

9
เรามีวิธีตรวจสอบอัตโนมัติที่includePage()ไม่ใช่มาโครที่เขียนไม่ดีซึ่งมีคำสั่งมากกว่าหนึ่งคำหรือไม่?
Martin York

51
@LokiAstari ใช่มันเรียกว่า "Java ไม่มีมาโคร"
svick

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

16
@Jules โอ้ใช่! ผลิตภัณฑ์ทั้งหมดที่ฉันได้รับหรือเผยแพร่ในที่ทำงานมีการทดสอบครอบคลุม 100% (อย่างน้อยที่สุด) ได้รับการตรวจสอบโดยเพื่อน (หลายครั้ง) และธุรกิจทั้งหมดที่มีแผนก QA ของซอฟต์แวร์ ใช่. ฉันคิดว่าคุณพบว่าอาชีพการงานของคุณเหมือนกันเพราะทุกธุรกิจมีทีมโปรแกรมเมอร์แทนที่จะเป็นโปรแกรมเมอร์คนเดียวและพวกเขาให้เวลามากพอที่จะทำแบบทดสอบที่พวกเขาต้องการ ใช่ที่อธิบายถึงสถานที่ทำงานอย่างสมบูรณ์แบบ ทำไมต้องกังวลเกี่ยวกับการเพิ่มข้อผิดพลาดบางอย่างเมื่อเราแน่ใจว่าซอฟต์แวร์ของเราส่งข้อผิดพลาดได้ฟรี 100% อยู่เสมอ
SJuan76

31

ส่วนใหญ่เป็นความชอบส่วนตัวอย่างไรก็ตามมีบางสิ่งที่ต้องพิจารณา

ข้อบกพร่องที่เป็นไปได้

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

รหัสที่ถูกต้อง (ที่อ่านเช่นนี้อาจเป็นข้อบกพร่อง)

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

เราเริ่มต้นด้วย:

if (foo)
    bar();

นักพัฒนาเพิ่มความคิดเห็นที่เป็นประโยชน์

if (foo)
    // At this point we know foo is valid.
    bar();

ต่อมาเมื่อนักพัฒนาขยายตัว

if (foo)
    // At this point we know foo is valid.
    // This never fails but is too slow even for debug, so keep disabled.
    // assert(is_valid(foo));
    bar();

หรือเพิ่มบล็อกซ้อนกัน:

if (foo)
    while (i--) {
        bar(i);
        baz(i);
    }

หรือใช้มาโคร:

if (foo)
    SOME_MACRO();

"... เนื่องจากมาโครอาจกำหนดโค้ดได้หลายบรรทัดมาโครใช้do {...} while (0)กับหลายบรรทัดหรือไม่มันควรเป็นเพราะมันอยู่ในไกด์นำเที่ยวของเรา แต่ฉันควรตรวจสอบในกรณีที่ดีกว่า!"


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

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

เสียงรบกวนต่าง

เหตุผลหนึ่งที่ทำให้การปฏิบัติในการใช้เครื่องหมายวงเล็บสำหรับสายเดียวคือการลดเสียงรบกวนต่าง

นั่นคือการเปลี่ยนแปลง:

if (foo)
    bar();

ไปที่:

if (foo) {
    bar();
    baz();
}

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

  • บรรทัดแสดงว่ามีการเปลี่ยนแปลงในการตรวจสอบโค้ดหากเครื่องมือการกระจายของคุณเป็นแบบใช้คำคุณสามารถเห็นได้อย่างง่ายดายว่ามีเพียงการเปลี่ยนรั้ง แต่ต้องใช้เวลามากขึ้นในการตรวจสอบว่าบรรทัดไม่เปลี่ยนแปลงเลยหรือไม่
    ต้องบอกว่าไม่ใช่เครื่องมือทั้งหมดที่รองรับการกระจายคำโดยใช้ diff (svn, git, hg ... ฯลฯ ) จะแสดงราวกับว่าทั้งบรรทัดเปลี่ยนไปแม้ว่าจะเป็นเครื่องมือแฟนซีบางครั้งคุณอาจต้องมองข้ามเส้นธรรมดาอย่างรวดเร็ว -based diff เพื่อดูว่ามีอะไรเปลี่ยนแปลง
  • เครื่องมือการเพิ่มความคิดเห็น (เช่นgit blame) จะแสดงบรรทัดที่มีการเปลี่ยนแปลงทำให้การติดตามที่มาของขั้นตอนเพิ่มเติมเพื่อค้นหาการเปลี่ยนแปลงที่แท้จริง

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

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


มีข้อยกเว้นนี้สำหรับรหัสฐานที่มี{ในบรรทัดของตัวเอง - มันไม่ใช่ปัญหา

diff เสียงโต้แย้งไม่ถือถ้าคุณเขียนในรูปแบบนี้

if (foo)
{
    bar();
    baz();
}

อย่างไรก็ตามเรื่องนี้ไม่ได้เป็นเช่นการประชุมร่วมกันเพื่อเพิ่มส่วนใหญ่จะตอบสำหรับสมบูรณ์(ไม่แนะนำโครงการควรใช้รูปแบบนี้)


8
ฉันชอบเสียงรบกวนที่ลดความเห็นที่เป็นบวก
Martin York

2
หากทุกคนเท่านั้นที่คลั่งไคล้ JSON มีการพิจารณาเรื่องเสียงรบกวนต่าง ๆ ! ฉันกำลังดูคุณอยู่
Roman Starkov

1
อืมฉันไม่ได้พิจารณาถึงประโยชน์ของสัญญาณรบกวนของสไตล์ใน{แบบของมันเอง ฉันเกลียดสไตล์นั้นและไม่ชอบทำงานในโครงการที่ต้องการสไตล์นั้น อาจเป็นเพราะในใจฉันจะพบว่ามันน่าหงุดหงิดน้อยกว่าที่จะต้องเขียนโค้ดด้วยวิธีนี้ ความหนาแน่นของรหัสเป็นสิ่งสำคัญ หากคุณสามารถเห็นฟังก์ชั่นทั้งหมดบนมอนิเตอร์ของคุณได้ในครั้งเดียวคุณสามารถคลี่คลายสิ่งต่างๆได้ง่ายขึ้น ฉันชอบที่จะเว้นบรรทัดว่างไว้ระหว่างบล็อกของโค้ดที่แยกต่างหากภายในฟังก์ชั่นเพื่อให้อ่านได้ (เพื่อจัดกลุ่มคำสั่งที่เกี่ยวข้อง) และการถูกบังคับให้เสียพื้นที่ในที่อื่นทำให้การแบ่งนั้นอ่อนแอกว่า
Peter Cordes

1
@ peter-cordes ไม่ใช่แฟนของสไตล์{-on-own-line แต่รวมไว้เพื่อความสมบูรณ์เท่านั้น สำหรับการไว้วางใจให้ใช้มาโครdo{}while(0)ฉันพบว่าปัญหานี้คือคุณสามารถไว้วางใจได้เกือบตลอดเวลา ปัญหาคืออุบัติเหตุเกิดขึ้นข้อผิดพลาดสามารถตรวจสอบได้โดยการตรวจสอบรหัส ... และข้อผิดพลาดสามารถแนะนำได้ว่าจะไม่เป็นอย่างอื่น
ideasman42

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

15

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

if (debug)
   foo (4);

และปรากฎว่าคนที่เขียนมันได้นิยามfooว่าเป็นมาโคร แมโครที่มีโค้ดสองบรรทัด ifและแน่นอนเพียงครั้งแรกของทั้งสองสายเป็นเรื่องที่ (ดังนั้นบรรทัดที่สองจะถูกดำเนินการโดยไม่มีเงื่อนไข)

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

ตอนนี้ฉันเยื้องและใช้เครื่องมือจัดฟันแตกต่างจากคนอื่นอย่างเห็นได้ชัด สำหรับบรรทัดเดียวifฉันจะทำ:

if (debug) { foo (4); }

ดังนั้นจึงไม่ต้องใช้บรรทัดเพิ่มเติมใด ๆ เพื่อรวมเครื่องมือจัดฟัน


6
ในกรณีนั้นใครก็ตามที่เขียนมาโครนั้นเป็นคนที่ผิด
gnasher729

6
การเขียนมาโครตัวประมวลผลล่วงหน้า C อย่างถูกต้องอาจไม่ง่าย แต่ก็สามารถทำได้ และควรจะทำตามที่ gnasher729 ชี้ให้เห็น และตัวอย่างของคุณคือเหตุผลว่าทำไมแมโครใด ๆ ที่มีคำสั่งมากกว่าหนึ่งคำสั่งต้องรวมเนื้อความของมันไว้ในdo { ... } while(0)ลูป สิ่งนี้จะไม่เพียง แต่ทำให้แน่ใจว่าจะได้รับการปฏิบัติอย่างถูกต้องเสมอโดยการปิดif()คำแถลง แต่ยังเครื่องหมายอัฒภาคที่ท้ายคำสั่งนั้นถูกกลืนอย่างถูกต้อง ใครก็ตามที่ไม่ทราบเกี่ยวกับกฎง่ายๆเช่นนั้นก็ไม่ควรเขียนมาโครตัวประมวลผลล่วงหน้า การป้องกันที่ไซต์โทรนั้นเป็นสถานที่ที่ไม่ถูกต้องในการป้องกัน
cmaster

18
@cmaster: จริง แต่วิธีแมโคร (หรือคุณสมบัติภาษาอื่น ๆ ) เขียนโดยคนอื่นอยู่นอกเหนือการควบคุมของฉัน ฉันจะใช้เครื่องมือจัดฟันได้อย่างไรภายใต้การควบคุมของฉัน ฉันไม่ได้พูดอย่างแน่นอนว่านี่เป็นเหตุผลที่หุ้มด้วยเหล็กในการใส่เหล็กดัดฟัน แต่มันเป็นสิ่งที่ฉันสามารถทำได้เพื่อป้องกันตัวเองจากความผิดพลาดของผู้อื่นดังนั้นฉันจึงทำมัน
Wayne

@ gnasher729 ใครจะสนใจความผิดของคนอื่น หากคุณกำลังทำบทวิจารณ์โค้ดและปฏิบัติตามมาตรฐานรหัสบางอย่างที่เหมาะสมอาจเป็นความผิดของทีมของคุณ และถ้ามันเข้าถึงผู้ใช้พวกเขาจะตำหนิองค์กรที่ปล่อยซอฟต์แวร์ buggy
ideasman42

1
ใครก็ตามที่เกิดขึ้นกับมาโครเป็นคนที่ผิด
Neme

14

"ลุงบ๊อบ" ได้รับอนุญาตให้มีความคิดเห็นของเขาคุณได้รับอนุญาตให้มีความคิดเห็นของคุณ ไม่จำเป็นต้องท้าทายเขา

หากคุณต้องการอุทธรณ์ต่อผู้มีอำนาจโปรดนำ Chris Lattner ไปด้วย ใน Swift หากข้อความทำเครื่องหมายวงเล็บหาย แต่จะต้องใส่เครื่องหมายวงเล็บเสมอ ไม่มีการสนทนามันเป็นส่วนหนึ่งของภาษา ดังนั้นหาก "Uncle Bob" เริ่มลบเครื่องหมายวงเล็บรหัสจะหยุดรวบรวม

การใช้รหัสของคนอื่นและ "การกำจัดวงเล็บที่ไร้ประโยชน์" นั้นเป็นนิสัยที่ไม่ดี ทำให้เกิดการทำงานเพิ่มเติมเฉพาะเมื่อรหัสต้องได้รับการตรวจสอบและเมื่อมีการสร้างความขัดแย้งโดยไม่จำเป็น บางที "ลุงบ๊อบ" เป็นโปรแกรมเมอร์ที่ดีอย่างเหลือเชื่อซึ่งเขาไม่ต้องการการตรวจสอบโค้ด? ฉันเสียชีวิตไปหนึ่งสัปดาห์เพราะโปรแกรมเมอร์ยอดเยี่ยมคนหนึ่งเปลี่ยน "if (p! = NULL)" เป็น "if (! p)" โดยไม่ต้องตรวจสอบโค้ดซ่อนอยู่ในที่ที่เลวร้ายที่สุด

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


1
ฉันเดาว่ามันเกี่ยวกับ "ท้าทาย" เพราะ UB (sic!) นำเสนอความคิดเห็นของเขาว่าเป็นข้อเท็จจริง - อย่างน้อยมันก็ทำให้ฉันประทับใจเมื่อฉันฟังเขา
vaxquis

3
การพูดว่า "ทำในสิ่งที่คุณต้องการ" จริง ๆ แล้วคือการเห็นด้วยกับลุงบ๊อบในเรื่องนี้เพราะนั่นคือสิ่งที่เขาระบุว่า "มันไม่สำคัญ" ในหลายภาษานี่ไม่ใช่ปัญหา ก่อนหน้านี้ฉันเคยคิดในเรื่องที่คุณควรใช้เครื่องมือจัดฟันและไม่เคยเห็นใครท้าทายเลย ตอนนี้ที่นี่ลุงบ็อบท้าทายและฉันก็สงสัยว่าเขาจะหนีไปเพราะเขาทำงานในวิธีการเล็ก ๆ ที่ได้รับการปรับปรุงใหม่หรือเพราะเขาเต็มไปด้วยมัน ฉันไม่ได้คิดว่ามันจะไม่เป็นอันตรายอย่างแน่นอนเพราะข้อผิดพลาดประเภทต่างๆ @PaulDraper กล่าวถึงในคำตอบของเขา
candied_orange

Re เสมอ : เสียงทางวากยสัมพันธ์กำลังเบี่ยงเบนความสนใจและบรรทัด "ว่าง" พิเศษสำหรับวงเล็บปีกกาปิดเพิ่มตัวคั่นที่มองเห็นได้ในย่อหน้าที่บรรทัดไม่ควรแยกออกจากกันขัดขวางการอ่านเพิ่มเติม นี่เป็นสิ่งสำคัญอย่างยิ่งในบล็อกเล็ก ๆ ที่คุณพูดถึง
JDługosz

9

เหตุผลของฉันที่ไม่ลบวงเล็บปีกกาคือ:

  1. ลดความเหนื่อยล้าในการตัดสินใจ หากคุณใช้เครื่องมือจัดฟันคุณไม่จำเป็นต้องตัดสินใจว่าคุณต้องการเครื่องมือจัดฟันหรือไม่

  2. ลดความล่าช้าในการพัฒนา: แม้ว่าคุณจะพยายามแยกตรรกะหลาย ๆ เส้นทั้งหมดเป็นวิธีการในที่สุดก็ต้องแปลง braceless ถ้าเป็นแบบ braced หากเป็นการเพิ่มแบบตรรกะถ้าเป็นการเพิ่มตรรกะเป็นบิตที่น่ารำคาญของการพัฒนา ดังนั้นจึงมีความพยายามในการลบวงเล็บปีกกาและความพยายามในการเพิ่มพวกเขาอีกครั้งเมื่อคุณต้องการรหัสเพิ่มเติม เล็ก แต่น่ารำคาญ


0

เพื่อนร่วมงานรุ่นเยาว์ได้กล่าวว่าเครื่องมือจัดฟันที่เราเห็นว่าเกินความจำเป็นและฟุ่มเฟือยนั้นมีประโยชน์ต่อเขาในความเป็นจริง ฉันจำไม่ได้ว่าทำไม แต่ถ้ามันอนุญาตให้เขาเขียนโค้ดที่ดีกว่าได้เร็วกว่านั้นเพียงอย่างเดียวก็เป็นเหตุผลที่ทำให้พวกเขา

Fwiw เราเห็นด้วยกับการประนีประนอมที่ทำให้พวกเขาอยู่ในบรรทัดเดียวไม่ได้ทำให้เงื่อนไขเบื้องต้นสั้น ๆ เช่นนี้ไม่สามารถอ่าน / ทำให้เสียสมาธิได้ เช่น

if (!param) { throw invalid_argument (blahblah); }
if (n < 2) { return 0; }
// real code for function starts here...

ฉันยังชี้ให้เห็นว่าสิ่งที่จำเป็นเบื้องต้นเหล่านี้มักจะเป็นคำสั่งควบคุมการไหลของร่างกาย (เช่นกreturn) ดังนั้นความกลัวที่จะเพิ่มคำสั่งที่สองที่ตั้งใจจะอยู่ภายใต้เงื่อนไขเดียวกันและการลืมวงเล็บปีกกาเขียนก็คือ moot คำสั่งที่สองภายใต้เงื่อนไขจะเป็นรหัสตายแล้วและไม่เข้าท่า

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


1
ลุงบ๊อบอาจคิดว่าเขาเขียนโค้ดได้เร็วขึ้นถ้าไม่มีพวกเขา
djechlin

2
เช่นเดียวกับฉันและอื่น ๆ ได้อย่างคล่องแคล่วใน C ++
JDługosz

1
"ถ้ามันอนุญาตให้เขาเขียนโค้ดได้เร็วขึ้นดีกว่านั่นคือเหตุผลเดียวที่จะรักษาพวกเขาไว้" ++ ฉันมีจูเนียร์ที่พูดแบบเดียวกันดังนั้นเราจึงเก็บมันไว้
RubberDuck

... และนั่นเป็นเหตุผลเดียวที่ทำในสิ่งที่ลุงบ๊อบต้องการ
djechlin

-1

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

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


สิ่งนี้ดูเหมือนจะไม่นำเสนออะไรมากมายเกินกว่าที่ทำคะแนนและอธิบายไว้ในคำตอบก่อนหน้า 10 ข้อ
gnat

-3

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

หากรหัสของคุณผ่านการทดสอบเป็นอย่างดี "บั๊ก" ชนิดนี้จะระเบิดออกมาในหน้า

การทำความสะอาดรหัสโดยการหลีกเลี่ยงวงเล็บเหลี่ยมที่ไร้ประโยชน์และน่าเกลียดนั้นเป็นวิธีปฏิบัติที่ฉันปฏิบัติตาม


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

3
เพื่อเพิ่มความคิดเห็นของ ruakh: ไม่สามารถทำการทดสอบรหัสได้ 100%
BЈовић

โปรดมาดูโค้ดของฉัน;) ขณะฝึก TDD เป็นไปได้เสมอที่จะแสดงข้อผิดพลาดประเภทนี้อย่างรวดเร็ว
Mik378

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