การบำรุงรักษาอย่างชาญฉลาดมีอีกอย่างหนึ่งที่ไม่ต้องใช้เครื่องมือจัดฟันที่ปลอดภัยหรือไม่?


26

คือelse whileโดยไม่แทรกแซงการพิจารณาการจัดฟัน "ปลอดภัย" การบำรุงรักษาที่ชาญฉลาด?

กำลังเขียนif-elseโค้ดโดยไม่มีเครื่องหมายวงเล็บด้านล่าง ...

if (blah)
    foo();
else
    bar();

... มีความเสี่ยงเนื่องจากการขาดเครื่องหมายปีกกาทำให้ง่ายต่อการเปลี่ยนความหมายของรหัสโดยไม่ตั้งใจ

อย่างไรก็ตามด้านล่างมีความเสี่ยงหรือไม่

if (blah)
{
    ...
}
else while (!bloop())
{
    bar();
}

หรือelse whileโดยไม่ต้องจัดฟันจัดฟันถือว่า "ปลอดภัย"?


20
ให้ฉันelse whileดูน่ากลัว else { while (condition) { ... } }ฉันต้องการใช้
Joachim Sauer

7
ฉันคิดว่ามันเป็นอัตนัยเกินไปสำหรับคำตอบที่เหมาะสม ... ฉันเองจะไม่ทำอย่างนั้นเพราะฉันไม่คาดว่าจะมีการวนซ้ำที่นั่นและคิดว่าฉันไม่คาดหวังว่าการอ่านจะยาก
โยฮันเนส

7
ฉันจะแยกวิธีการในขณะที่สิ่ง
ริ้น

12
สุจริตมันให้ครีพแก่ฉัน ifมีการประเมินเพียงครั้งเดียว แต่whileหมายถึงการวนซ้ำดังนั้นการเชื่อมต่อทั้งสองทำให้ฉันรู้สึกพร้อมเพรียงว่าifเป็นส่วนหนึ่งของวง ... อย่างใด ...
user281377

4
และถ้าเกิดในelseประโยคที่คุณต้องการทำwhile และทำอะไรมากกว่านี้? เพียงแค่ใช้เครื่องมือจัดฟันโปรด
Carlos Campderrós

คำตอบ:


57

ที่ทำให้ฉันรหัสนี้:

if ( ... ) try {
..
} catch (Exception e) {
..
} else {
...
}

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


18
ตัวอย่างที่ดี ช่างเป็นวิธีที่น่ากลัวในการเขียน
Leo

4
ว้าวคำตอบนี้น่าเชื่ออย่างน่าขัน!
Mehrdad

คุณสามารถตั้งค่า IDE ที่ทันสมัยเพื่อจัดรูปแบบรหัสในการบันทึกโดยอัตโนมัติ - รวมถึงการใส่เครื่องมือจัดฟันและแก้ไขการเยื้อง ดังนั้นนี่เป็นข้อโต้แย้งเพียงครึ่งเดียว การเยื้องอย่างถูกต้องจะทำให้เกิดปัญหาในการอ่านไม่ว่าจะมีเครื่องหมายวงเล็บหรือไม่ก็ตาม
Hans-Peter Störr

55

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

สิ่งอื่นใด (ไม่มีการเล่นสำนวนเจตนา) ทำให้เกิดความเข้าใจผิดและ / หรือปัญหาการบำรุงรักษา นั่นคือสิ่งสำคัญของแนวคิด OPs ที่เป็น "ไม่ปลอดภัย"

ฉันยังต้องระมัดระวังมากเกี่ยวกับการรวมwhile()บรรทัดเดียวกันกับelse- ไม่ว่าจะค้ำยันหรือไม่ มันไม่ถูกต้องสำหรับฉัน ... การขาดมาสก์ย่อหน้าพิเศษที่เป็นส่วนelseคำสั่ง และการขาดความชัดเจนทำให้เกิดความเข้าใจผิด (ดูด้านบน)

ดังนั้นในตัวอย่างฉันขอแนะนำ / แนะนำ (และยืนยันในทีมของฉัน) ใน:

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

แน่นอนฉันก็คาดหวังที่จะเห็นความคิดเห็นที่เหมาะสมเช่นกัน

- แก้ไข -

เมื่อเร็ว ๆ นี้ Apple ได้รับผลกระทบจากช่องโหว่ SSL ที่เกิดจากการแก้ไขปัญหาการบำรุงรักษาที่ไม่ดีซึ่งเพิ่มบรรทัดที่สองในบรรทัดเดียวที่ไม่ได้ถูกโยง งั้นลองคิดกันว่าบรรทัดเดียวที่ไม่มีรอยหยักนั้นโอเคไหม?


2
ฉันเห็นด้วยหากเป็นคำที่ถูกต้องเพียงคำเดียวที่จะติดตามคนอื่น หากมีelse whileฉันอาจจะไม่ได้สังเกตเห็นว่ามีการวนรอบในการอ่านอย่างรวดเร็วของรหัสโดยเฉพาะถ้าเงื่อนไขที่ฉันกำลังมองหาก็พอใจถ้า
Drake Clarris

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

2
@JeffDavis เป็นสิ่งที่ดี "ง่ายต่อการอ่าน" เป็นคำเชื้อเชิญทั่วไปสำหรับสงครามศักดิ์สิทธิ์ที่ไร้ประโยชน์ ฉันหนึ่งต้องการวงเล็บปีกกา แต่ไม่ใช่เพราะขยะ "ง่ายกว่าการทดสอบ" (สำหรับฉันเช่นมันตรงกันข้าม) แต่เพราะยากที่จะทำลายในการบำรุงรักษารหัสเพิ่มเติม โดย OP วิธีการสะกดมันได้ดีขึ้นในคำถามของพวกเขาเป็นelse whileโดยไม่แทรกแซงการจัดฟันถือว่าเป็น "ปลอดภัย" ?
ริ้น

@JeffDavis - ฉันรู้ว่าเธรดนี้มีอายุสองปี แต่ Apple เพิ่งค้นพบสาเหตุที่ไม่ใช้วงเล็บปีกกาไม่ใช่ความคิดที่ดีandrewbanks.com/…
Andrew

@Andrew อย่างไรก็ตามภาษา Swift ของ Apple ได้ห้ามการควบคุมการไหลแบบหนึ่งบรรทัดอย่างชัดเจน จุดบกพร่องนั้นอาจเป็นหนึ่งในเหตุผลที่จะทำเช่นนั้น
Sulthan

6

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

    if(blah)
    {
     ....
    }
    else
    {
       while(!bloop()
       {
        bar;
       }
    }

6

ฉันจะแยกวิธีการและทำให้มัน

if ( blah )
{
    ...
}
else
{
   newMethod();
}

ดูวิธีการ "แยกวิธี" ที่อธิบายไว้ในไซต์Refactoring Catalog

คุณมีส่วนของรหัสที่สามารถจัดกลุ่มเข้าด้วยกัน

เปลี่ยนแฟรกเมนต์เป็นวิธีที่ชื่ออธิบายถึงวัตถุประสงค์ของเมธอด

void printOwing() {
    printBanner();

    //print details
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + getOutstanding());
}

                                                                                                         http://www.refactoring.com/catalog/arrow.gif

void printOwing() {
    printBanner();
    printDetails(getOutstanding());
}

void printDetails (double outstanding) {
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + outstanding);
}

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

1
คอมไพเลอร์สมาร์ท C ++ +1 สามารถอินไลน์ฟังก์ชันได้ ใน. Net ฟังก์ชั่นขนาดเล็กจะดีกว่าเนื่องจาก JIT
งาน

4

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

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

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

เป็นวิธีปฏิบัติที่ดีในการใส่รหัสในบล็อก ทำให้ง่ายต่อการเข้าใจและแก้ปัญหาเช่นกัน


4

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

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

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

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


3

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

if (...)
   foo();
else while(...)
   bar();

... ฉันพบว่า "" นี้else while(...)อ่านง่ายมาก! มันอ่านเหมือนภาษาอังกฤษธรรมดา ๆ ! แต่ฉันคิดว่าทุกคนจะพบว่ามันแปลกเพราะมันผิดปกติที่จะพูดน้อย

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


3
ที่จะสามารถอ่านได้โดยเฉพาะอย่างยิ่งหลังจากผู้ดูแลผู้บริสุทธิ์บางคนเปลี่ยนelse while(...) bar();เป็นอย่างelse while(...) foobar(); bar();:)
gnat

3
ฉันจะบอกว่านั่นเป็นผู้ดูแลผู้บริสุทธิ์ที่โง่และอันตราย ฉันรู้หลักการของการทำให้แย่ลงเพื่อหลีกเลี่ยงข้อผิดพลาดที่โง่เง่า ... แต่ฉันรู้ว่าฉันจะได้รับความคิดเห็นและ downvotes ไม่มีปัญหา.
dagnelies

2
"รหัสเสมอว่าคนที่จะรักษารหัสของคุณเป็นโรคจิตรุนแรงที่รู้ว่าคุณอยู่ที่ไหน" ( Alan Braggins )
gnat

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

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

2

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

if(blah) {
    foo();
}
else {
    bar();
}

การจัดตำแหน่งของเครื่องมือจัดฟันอาจก่อให้เกิดการโต้แย้งมากกว่าสิ่งอื่นใดนอกเหนือไปจากศาสนา
แอนดรู

ตกลง จะแก้ไขคำตอบของฉันเพื่อเน้นที่การมีอยู่ไม่ใช่ตำแหน่ง
Tsvetomir Dimitrov

2

มีอะไรผิดปกติกับเครื่องมือจัดฟันที่ผู้คนจำนวนมากพยายามหลีกเลี่ยงการเขียนมัน?

ปัญหาอะไรกันแน่ที่else whileแก้ได้?

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

การอ้างอิงปรัชญา Unix:

กฎของความชัดเจน: ความชัดเจนดีกว่าความฉลาด

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


1

ไม่มีอะไรผิดปกติกับ

if (blah)
    foo();
else
    bar();

เหมือนไม่มีอะไรผิดปกติ

if (blah) foo(); else bar();

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

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


นอกจากนี้ฉันเคยเห็นรหัสนี้มาก่อน:

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

และมันถูกเขียนโดยมาตรฐานการเข้ารหัสนาซีเอง (ซึ่งยืนยันในวงเล็บสำหรับทุกสิ่ง)


1

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

if (blah) {
  blub();
} else
  while (!bloop()) {
    bar();
  }

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

โดยส่วนตัวแล้วฉันพบโค้ดที่ไม่ใช้วงเล็บปีกกาและ linebreaks ที่อ่านได้มากขึ้นเพราะหลีกเลี่ยงความยุ่งเหยิง:

if (blah) blub();
else while (!bloop()) bar();

แต่แน่นอนว่านักพัฒนาจำนวนมากยินดีที่จะโต้แย้งเกี่ยวกับสิ่งต่าง ๆ เช่นนี้ตลอดไปและต่อวัน

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