การใช้คำสั่ง if-statement โดยไม่ต้องใช้เครื่องหมายปีกกาเป็นวิธีที่ไม่ดีหรือไม่? [ปิด]


130

ฉันเคยเห็นรหัสเช่นนี้:

if(statement)
    do this;
else
    do this;

อย่างไรก็ตามฉันคิดว่านี่สามารถอ่านได้มากขึ้น:

if(statement){
    do this;
}else{
    do this;
}

เนื่องจากวิธีการทั้งสองวิธีนี้เป็นเพียงเรื่องของการตั้งค่าที่จะใช้หรือจะมีวิธีหนึ่งที่จะแนะนำมากกว่าอื่น ๆ ?



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

คำตอบ:


212

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

การบำรุงรักษาที่ชาญฉลาดก็มักจะได้อย่างชาญฉลาดที่จะใช้รูปแบบที่สอง

แก้ไข: เน็ดชี้ประเด็นนี้ในความคิดเห็น แต่มันก็คุ้มค่าที่จะมาที่นี่เช่นกันฉันคิดว่า นี่ไม่ได้เป็นเพียงแค่การพล่ามตามหอคอยงาช้าง: https://www.imperialviolet.org/2014/02/22/applebug.html


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

12
หรือคุณอาจจะใช้ภาษาที่ไม่ใช้วงเล็บสำหรับบล็อกรหัส ...
Tor Valamo

10
@ lins314159 - ไม่ฉันหมายถึงเหมือนงูหลาม เพราะฉันเป็นคนที่คลั่งไคล้ในเรื่องนี้
Tor Valamo

17
ความผิดพลาดหลักฐานเพิ่มเติมสามารถ (และ) เกิดขึ้น: imperialviolet.org/2014/02/22/applebug.html
เน็ด

8
อ้างว่าข้อผิดพลาด SSL เป็นอาร์กิวเมนต์ในความโปรดปรานของการจัดฟันนั้นไม่ตรง ไม่ใช่ว่านักพัฒนาตั้งใจจะเขียนif (…) { goto L; goto L; }แต่ลืมวงเล็บปีกกา เป็นเรื่องบังเอิญโดยสิ้นเชิงที่ `` if (…) {goto L; ข้ามไป L; } `เกิดขึ้นไม่ได้เป็นข้อบกพร่องด้านความปลอดภัยเพราะมันยังคงเป็นข้อผิดพลาด (ไม่ใช่แค่หนึ่งเดียวที่มีผลต่อความปลอดภัย) ในอีกตัวอย่างหนึ่งสิ่งต่าง ๆ อาจไปในทิศทางตรงกันข้ามและรหัส braceless อาจปลอดภัยโดยไม่ได้ตั้งใจ ในตัวอย่างที่สามโค้ด braceless จะไม่มีข้อบกพร่องในตอนแรกและผู้พัฒนาจะแนะนำการพิมพ์ผิดในขณะที่เพิ่มการจัดฟัน
Pascal Cuoq

112

ปัญหาหนึ่งที่เกิดจากการเลิกบล็อกข้อความสั่งคือความคลุมเครืออื่น นั่นคือภาษาที่ได้รับแรงบันดาลใจจาก C ไม่สนใจการเยื้องและไม่มีทางแยกสิ่งนี้:

if(one)
    if(two)
        foo();
    else
        bar();

จากนี้:

if(one)
    if(two)
        foo();
else
    bar();

8
นี่เป็นปัญหาที่ร้ายแรงยิ่งกว่าที่กล่าวไว้ในคำตอบยอดนิยม (เพิ่มข้อความที่สอง)

3
จริงคำตอบนี้เอาฉันจากการอ่านคำตอบเหล่านี้อย่างเหยียดหยามเป็นกังวลเล็กน้อยฉันอาจทำผิดพลาดจริง
ทุก

2
หากมีคนอื่นสงสัยว่าฉันเป็นคนแบบไหนที่ C ตีความหมายได้จริงการทดสอบที่ฉันทำกับ GCC ตีความรหัสนี้ในวิธีแรก tpcg.io/NIYeqx
horta

2
"ความกำกวม" เป็นคำที่ผิด : มีสิ่งที่ไม่มีความคลุมเครือในวิธีการแยกวิเคราะห์จะเห็นนี้คือelseผูกละโมบที่ใกล้ที่สุด, ifสุด ปัญหาเกิดขึ้นที่ C หรือภาษาที่คล้ายกันกำลังถูกเข้ารหัสโดยผู้ที่ไม่ทราบสิ่งนี้ไม่ต้องคิดมากหรือไม่มีกาแฟเพียงพอ - ดังนั้นพวกเขาจึงเขียนโค้ดที่พวกเขาคิดว่าจะทำสิ่งหนึ่ง แต่ ภาษา spec บอกว่า parser ต้องทำอย่างอื่นซึ่งอาจแตกต่างกันมาก และใช่แล้วนั่นเป็นอีกเหตุผลหนึ่งที่ทำให้หินแข็งขึ้นอยู่กับการใส่วงเล็บปีกกาแม้ว่าไวยากรณ์จะตั้งค่าสถานะพวกมันว่า 'ไม่จำเป็น' ก็ตาม
underscore_d

35

รูปแบบทั่วไปของฉันคือถ้ามันเหมาะกับหนึ่งบรรทัดฉันจะทำ:

if(true) do_something();

หากมีส่วนคำสั่งอื่นหรือหากรหัสที่ฉันต้องการใช้งานtrueนั้นมีความยาวที่สำคัญให้จัดฟันตลอด:

if(true) {
    do_something_and_pass_arguments_to_it(argument1, argument2, argument3);
}

if(false) {
    do_something();
} else {
    do_something_else();
}

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


4
แม้ว่าจะง่ายเหมือนที่เขียนif(true){ do_something(); }ไว้ทำไมถึงมีโอกาสที่จะมีโปรแกรมเมอร์อีกคนแนะนำบั๊กที่ร้ายแรงบนท้องถนน (การค้นหา "goto fail" ของแอปพลิเคชันรหัสรวม ssl ทั้งหมด)
เครก

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

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

10

ฉันใช้ฟอร์แมตโค้ดของ IDE ที่ฉันใช้อยู่ อาจแตกต่างกัน แต่สามารถตั้งค่าได้ในการตั้งค่า / ตัวเลือก

ฉันชอบอันนี้:

if (statement)
{
    // comment to denote in words the case
    do this;
    // keep this block simple, if more than 10-15 lines needed, I add a function for it
}
else
{
    do this;
}

5
นี่เป็นปัญหาสไตล์ที่เป็นอัตวิสัยทั้งหมดฉันเองไม่ชอบความซ้ำซ้อนของเส้นรั้งเท่านั้น แต่เฮ้
Matchu

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

6
ฉันชอบสไตล์นี้มาตลอด ง่ายกว่ามากในการค้นหาวงเล็บปิดที่สอดคล้องกัน ดังนั้นต้องใช้พื้นที่มากไหม? ใช้แบบอักษรขนาดเล็ก
จันทร์ที่

4
ฉันมักจะง่ายกว่าในการ "สแกน" ผ่านรหัสเมื่อวงเล็บปีกกาอยู่ในบรรทัดที่แยกกัน สำหรับทุกสิ่ง คลาส, เมธอด, if- และ while-statement, และอื่น ๆ ไม่เคยชอบที่มีรั้งแรกในบรรทัดเดียวกัน ...
Svish

2
ช่องว่างราคาถูกโดยเฉพาะอย่างยิ่งเมื่อคุณมี IDE ที่สามารถพับโค้ดได้
หมู่

10

"กฎ" ที่ฉันติดตามคือ:

หากคำสั่ง "ถ้า" กำลังทดสอบเพื่อที่จะทำบางสิ่ง (ฟังก์ชั่นการโทร IE กำหนดค่าตัวแปร ฯลฯ ) ให้ใช้วงเล็บปีกกา

if($test)
{
    doSomething();
}

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

หากคำสั่ง "if" กำลังทำการทดสอบเพื่อหยุดทำบางสิ่ง (IE flow control ภายในลูปหรือฟังก์ชั่น) ให้ใช้เพียงบรรทัดเดียว

if($test) continue;
if($test) break;
if($test) return;

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


8

การจัดฟันที่ถูกต้องตั้งแต่วินาทีแรกจะช่วยป้องกันไม่ให้คุณต้องแก้ไขข้อบกพร่องนี้:

if (statement)
     do this;
else
     do this;
     do that;

1
ดูเหมือนว่าจะเป็นเหตุผลที่ยอมรับได้ แต่ (เพื่อแสดงให้เห็นถึงการสนับสนุนของปีศาจที่นี่) จะไม่มีกฎการเน้นไวยากรณ์เพิ่มเติมเพียงอย่างเดียวที่จะแก้ปัญหานี้ในขณะที่บันทึกหนึ่งบรรทัด?
เคน

2
ดังนั้นจะมี IDE ที่แก้ไขเยื้องเมื่อคุณกด;:)
แซม Harwell

6

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

if (someFlag) {
 someVar= 'someVal1';
} else {
 someVar= 'someVal2';
}

ดูเหมือนดีกว่านี้มาก:

someVar= someFlag ? 'someVal1' : 'someVal2';

แต่ใช้ผู้ประกอบการที่ประกอบไปด้วยถ้าคุณมั่นใจอย่างแน่นอนว่าไม่มีสิ่งใดที่จะต้องไปในบล็อก if / else!


4

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

นี่คือลิงค์สำหรับการใช้เครื่องมือจัดฟัน:


2

จากประสบการณ์ของฉันข้อได้เปรียบเพียงเล็กน้อย (มาก) ของแบบฟอร์มแรกคือการอ่านโค้ดได้แบบฟอร์มที่สองจะเพิ่ม "สัญญาณรบกวน"

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

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

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

สิ่งนี้จะเหมือนกันกับการตั้งชื่ออย่างชัดเจน & ชัดเจนตัวแปรวิธีการไฟล์หรือด้วยการเยื้องอย่างถูกต้อง ...

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


2

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

if(statement)
{
    do this;
}
else
{
    do this;
}

อย่างไรก็ตามฉันคิดว่าทางออกที่ดีที่สุดสำหรับปัญหานี้คือใน Python ด้วยโครงสร้างบล็อกที่อิงช่องว่างคุณไม่มีวิธีการสร้างคำสั่ง if สองวิธีที่ต่างกัน: คุณมีเพียงวิธีเดียว:

if statement:
    do this
else:
    do this

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


ฉันเองคิดว่าวิธีที่ Python จัดการกับคำสั่ง if-else เป็นเรื่องที่น่าเกลียดมาก แต่จากนั้นอีกครั้งฉันไม่มีโปรแกรมเมอร์ Python (ยัง)
helpermethod

1

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

จะไม่ทำงาน:

ถ้า (คำสั่ง) ทำสิ่งนี้; และนี่; อื่นทำเช่นนี้;


1

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

ตัวอย่าง:

if (argument == null)
    throw new ArgumentNullException("argument");

if (argument < 0)
    return false;

มิฉะนั้นฉันจะใช้รูปแบบที่สอง


1

ความชอบส่วนตัวของฉันใช้ส่วนผสมของช่องว่างและวงเล็บเหลี่ยมดังนี้:

if( statement ) {

    // let's do this

} else {

    // well that sucks

}

ฉันคิดว่ามันดูสะอาดและทำให้โค้ดของฉันง่ายต่อการอ่านและที่สำคัญที่สุดคือ - debug


0

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


0

ฉันชอบที่จะใส่รั้งผมหยิก แต่บางครั้งผู้ประกอบการที่สามช่วย

แทน :

int x = 0;
if (condition) {
    x = 30;
} else {
    x = 10;
}

สิ่งหนึ่งที่ควรทำ: int x = condition ? 30 : 20;

ลองจินตนาการถึงกรณี:

if (condition)
    x = 30;
else if (condition1)
    x = 10;
else if (condition2)
    x = 20;

มันจะดีกว่านี้มากถ้าคุณใส่วงเล็บปีกกาไว้

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