ผู้ประกอบการพิจารณาว่าเป็นอันตรายหรือไม่? [ปิด]


79

ตัวอย่างเช่นคุณต้องการซับไลเนอร์นี้หรือไม่

int median(int a, int b, int c) {
    return (a<b) ? (b<c) ? b : (a<c) ? c : a : (a<c) ? a : (b<c) ? c : b;
}

หรือโซลูชัน if / else ที่เกี่ยวข้องกับคำสั่ง return หลายรายการ?

เมื่อใด?:ที่เหมาะสมและเมื่อใด ควรสอนหรือซ่อนเร้นจากผู้เริ่มต้นหรือไม่


221
นี้โดยเฉพาะอย่างยิ่งการใช้งานของมันก็คือ :)
karmajunkie

6
ใครเขียนรหัสนั้นและค่ามัธยฐานของตัวเลขสี่ตัวเป็นอย่างไร หรือห้า
Mason Wheeler

3
ชื่อที่ถูกต้องมากขึ้นคือ 'โอเปอเรเตอร์ที่มีเงื่อนไข' มันเกิดขึ้นเพื่อเป็นผู้ประกอบการที่ใช้กันทั่วไปมากที่สุดในการใช้งาน
Alan Pearce

1
เรื่องนี้ถูกถามเมื่อสองปีก่อนใน stackoverflow ตอนนี้เราจะถามทุกอย่างที่นี่อีกไหม stackoverflow.com/questions/160218/to-ternary-or-not-to-ternary
webbiedave

3
ฉันประหลาดใจว่าทำไมคำถามเช่นนี้ยังคงเกิดขึ้น คำตอบคือ "สิ่งที่ใช้ได้และอ่านได้เสมอ" - คนสุดท้ายที่มีความสำคัญเท่าเทียมกัน
Apoorv Khurasia

คำตอบ:


234

ผู้ประกอบการประกอบไปด้วยความชั่วร้ายหรือไม่?

ไม่เป็นพร

เมื่อใด: เหมาะสม

เมื่อมันเป็นอะไรที่ง่ายมากคุณไม่ต้องการที่จะเสียสายไปมากมาย

และเมื่อไหร่

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


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


23
+1 สำหรับเมื่อการอ่านและความชัดเจนของรหัสได้รับความเดือดร้อน ด้วยตัวดำเนินการที่ถูกล่ามโซ่มากมายเช่นเดียวกับในตัวอย่างของคุณ ตัวอย่างใช้เวลาในการทำความเข้าใจนานกว่าการเทียบเท่าหาก / else
ประหลาดใจที่

23
+1 ไชโยสำหรับคำอธิบายที่ยอดเยี่ยม! นักพัฒนามักจะไม่ทราบว่าบางสิ่งเป็นการตัดสินใจที่เรียกว่าต้องการให้ทุกอย่างเป็นขาวดำ มันทำให้ฉันบ้า ฉันได้พบกับหลายคนที่เห็นว่า "X is evil ไม่อนุญาตให้ใช้" ฉันชอบ "X ดีมากถ้าคุณใช้เพื่อสิ่งที่ดี"
Reinstate Monica

54
นอกจากนี้ยังเป็นสิ่งที่เลวร้ายถ้ามันถูกใช้: myVar = (someExpression)? ถูกผิด; Aaaaarrgh!
adamk

20
@adamk: ลองสิ่งนี้เพื่อความชั่ว:myVar = someExpression ? false : true;
Dean Harding

8
วิธีการเกี่ยวกับ(someExpression ? var1 : var2)++:-)
fredoverflow

50

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


3
สิ่งนี้อาจถูกพิจารณาว่าเป็นการใช้งานเกินขนาด แต่เป็นแนวทางที่ง่ายมากในการติดตามและใช้งานได้ในกรณีส่วนใหญ่
Alan Pearce

2
จริง ๆ แล้วมันเป็นกฎของหัวแม่มือของคุณ: คุณไม่ควรทำรังพวกเขามิฉะนั้นแทนที่พวกเขาด้วยถ้า / อื่น ๆ มันจะมีความชัดเจนในแบบนั้น
Piovezan

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

24

เมื่อใด: เหมาะสม

  • เมื่อมันทำให้โค้ดของคุณกระชับและอ่านง่ายขึ้น

และเมื่อไหร่

  • เมื่อมันทำให้โค้ดของคุณอ่านไม่ได้
  • หากคุณกำลังทำเพียงเพื่อโปรดเครื่องมือ refactoring เช่น ReSharper และไม่ใช่คนที่ต้องรักษารหัส

หากคุณมีการโทรแบบลอจิกหรือฟังก์ชั่นใด ๆ ภายในนิพจน์ประกอบไปด้วยคุณจะทำให้ดูน่ากลัว


อันนี้สมควรได้รับการโหวตมากมาย!
Piovezan

22

ข้อแตกต่างอย่างหนึ่งที่ (ฉันคิดว่า) ไม่มีใครชี้ให้เห็นว่าถ้า - อย่างอื่นไม่สามารถคืนค่าได้

มาจาก F # บางครั้งฉันต้องการใช้โอเปอร์เรเตอร์ที่ประกอบขึ้นเป็นการเลียนแบบแพทเทิร์น

match val with
| A -> 1
| B -> 3
| _ -> 0

VS

return val == A ? 1 : 
       val == B ? 3 : 
       0;

มันเท่ห์มาก ไม่เคยคิดอย่างนั้น
Rei Miyasaka

+1 @Benjol: ฉันจะชี้ให้เห็นสิ่งเดียวกัน (ใน F # ทุกอย่างเป็นการแสดงออกรวมถึงถ้า / elif / อื่น) ฉันใช้ตัวอย่างแบบไตรภาคในตัวอย่างของคุณด้วยและยังไม่ได้ค้นพบ :) อีกสิ่งที่ฉันได้ทำใน Javascript อาจเหนือกว่าคือvar res = function() {switch(input) {case 1: return "1"; case 2: return "2"; ...}}()การเลียนแบบสวิตช์เป็นนิพจน์
Stephen Swensen

@Stephen ผมก็จะใช้คำว่าexpressionและstatementแต่ฉันกังวลอยู่เสมอฉันจะได้รับพวกเขารอบทางที่ผิดและทำให้คนโง่ของตัวเอง :)
Benjol

@Benjol: ฉันรู้ว่าคุณหมายถึงอะไร!
Stephen Swensen

6
ยังมีประโยชน์ใน C และ C ++ สำหรับการเริ่มต้นconstตัวแปรที่ไม่สามารถเปลี่ยนแปลงได้ในภายหลัง
David Thornley

13

ตัวอย่างของการใช้ที่ถูกต้อง (IMHO):

printf("Success in %d %s\n", nr_of_tries, (nr_of_tries == 1 ? "try" : "tries"));

สิ่งนี้ส่งผลให้โค้ดอ่านง่ายกว่าการพิมพ์ 2 statement ตัวอย่างแบบซ้อนขึ้นอยู่กับ: (เข้าใจได้หรือไม่ใช่: ไม่ใช่)


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

1
นั่นเป็นกฎง่ายๆของฉัน: การทำรัง 1 ระดับ (ในบางสถานการณ์)
Oliver Weiler

7

ไม่ใช่ความชั่วร้ายอย่างแน่นอน ในความเป็นจริงมันบริสุทธิ์และถ้าเป็นอย่างอื่นไม่ได้

ในภาษาที่ใช้งานได้เช่น Haskell, F #, ML เป็นต้นมันเป็นคำสั่ง if-then-else ที่ถือว่าเป็นความชั่วร้าย

เหตุผลสำหรับสิ่งนี้คือ "การกระทำ" ใด ๆ เช่นคำสั่ง if-then-else ที่จำเป็นต้องให้คุณแยกการประกาศตัวแปรจากคำจำกัดความและแนะนำสถานะให้กับฟังก์ชั่นของคุณ

ตัวอย่างเช่นในรหัสต่อไปนี้:

const var x = n % 3 == 1
    ? Parity.Even
    : Parity.Odd;

เมื่อเทียบกับ

Parity x;
if (n % 3 == 1)
    x = Parity.Even;
else
    x = Parity.Odd;

ข้อแรกมีสองข้อได้เปรียบนอกเหนือจากความสั้น:

  1. x เป็นค่าคงที่และมีโอกาสน้อยมากในการแนะนำบั๊กและสามารถปรับให้เหมาะสมในวิธีที่สองไม่สามารถทำได้
  2. ชนิดที่จะทำให้เห็นได้ชัดจากการแสดงออกเพื่อให้คอมไพเลอร์ง่ายสามารถอนุมานได้ว่าจะต้องมีประเภทxParity

ในภาษาที่ใช้งานสับสนผู้ประกอบการที่สามมักจะถูกเรียกว่า if-then-else ใน Haskell x = if n mod 3 == 1 then Odd else Evenคุณอาจจะบอกว่า


ใช่นี่คือจุดที่ @Benjol ทำเช่นกัน ดูความคิดเห็นของฉันที่มีต่อคำตอบของเขาเพื่อหาวิธีที่สนุกในการเลียนแบบคำสั่งสวิตช์เป็นนิพจน์ใน Javascript
Stephen Swensen

7

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

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

return
      ( 'a' == $s ) ? 1
    : ( 'b' == $s ) ? 2
    : ( 'c' == $s ) ? 3
    :                 4;

ฉันชอบที่ดีกว่าถ้า if แล้ว / เชนอื่น ๆ :

if ( 'a' == $s ) {
    $retval = 1;
}
elsif ( 'b' == $s ) {
    $retval = 2;
}
elsif ( 'c' == $s ) {
    $retval = 3;
}
else {
    $retval = 4;
}

return $retval;

ฉันจะจัดรูปแบบใหม่ให้เป็น:

if    ( 'a' == $s ) { $retval = 1; }
elsif ( 'b' == $s ) { $retval = 2; }
elsif ( 'c' == $s ) { $retval = 3; }
else                { $retval = 4; }

return $retval;

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


เหตุใดฉันจึงไม่สามารถกำหนด linebreaks ในความคิดเห็นได้ Arrgghh!
Christopher Mahan

3

ReSharperใน VS.NET บางครั้งแนะนำให้แทนที่if...elseด้วยตัว?:ดำเนินการ

มันดูเหมือนว่า ReSharper แสดงให้เห็นเฉพาะในกรณีที่เงื่อนไข / if...elseบล็อกอยู่ต่ำกว่าระดับที่ซับซ้อนบางอย่างอื่นที่มันเกาะติดกับ


4
อีกคุณสมบัติที่ยอดเยี่ยมฉันชอบเกี่ยวกับ ReSharper
ไม่ระบุตัวตนพิมพ์

2

คุณสามารถฟอร์แมตใหม่เพื่อให้ดูดีเหมือนชุดค่าผสม if / else:

int median(int a, int b, int c)
{
    return
        (a<b)
        ?
            (b<c)
            ? b
            :
                (a<c)
                ? c
                : a
        :
            (a<c)
            ? a
            :
                (b<c)
                ? c
                : b;
}

แต่ปัญหาคือว่าฉันไม่แน่ใจจริงๆถ้าฉันได้รับการเยื้องขวาเพื่อแสดงสิ่งที่จะเกิดขึ้นจริง :-)


3
+1 ฉันคิดว่านี่ดีกว่าif-elseโครงสร้างที่เทียบเท่า กุญแจสำคัญคือการจัดรูปแบบ
Orbling

13
ถ้าฉันเห็นสิ่งนี้ในฐานรหัสฉันจะพิจารณาหางานใหม่อย่างจริงจัง
Nick Larsen

+1 ไม่ได้สำหรับการเยื้องจริงนี้ แต่เป็นทางออกที่ดีที่สุดสำหรับการนี้ตัวอย่างเช่น
Mark Hurd

2
เฉพาะการจัดรูปแบบอัตโนมัติอื่นโดยไม่ตั้งใจเท่านั้นที่จะลบล้างการเยื้องและเวลาสำหรับการปรับโครงสร้างรอบใหม่ - การผลิตอย่างมหาศาล :)
nawfal

2

ห่างไกลจากความชั่วร้ายผู้ประกอบการที่สามคือสวรรค์

  • มันมีประโยชน์มากที่สุดเมื่อคุณต้องการตัดสินใจในนิพจน์ที่ซ้อนกัน ตัวอย่างคลาสสิกคือการเรียกใช้ฟังก์ชัน:

    printf("I see %d evil construct%s in this program\n", n, n == 1 ? "" : "s");
    
  • ในตัวอย่างของคุณโดยเฉพาะ ternary returnเกือบเปล่าเพราะมันคือการแสดงออกที่ระดับบนภายใต้ คุณสามารถยกระดับเงื่อนไขออกเป็นระดับคำสั่งโดยไม่ทำซ้ำสิ่งอื่นใดนอกจากreturnคำหลัก

NB ไม่มีสิ่งใดที่จะทำให้อัลกอริทึมเฉพาะนั้นสำหรับค่ามัธยฐานอ่านง่าย


มันยากที่จะอ่านได้จนคุณไม่สามารถทำให้ดีขึ้นได้ printf("I see %d evil construct%s in this program\n", n, "s" unless (n == 1) "s");
Pacerier

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

  2. ผู้ประกอบการที่สามดึงดูดตัวเลขเวทย์มนตร์เช่น s ** t ดึงดูดแมลงวัน

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


2

นี่คือตัวอย่างของเมื่อมันเป็นความชั่วร้าย

oldValue = newValue >= 0 ? newValue : oldValue;

มันสับสนและสิ้นเปลือง คอมไพเลอร์สามารถปรับให้เหมาะสมกับนิพจน์ที่สอง (oldValue = oldValue) แต่ทำไม coder ถึงทำสิ่งนี้ตั้งแต่แรก?

doozy อื่น:

thingie = otherThingie != null ? otherThingie : null;

บางคนไม่ได้เป็นนักเขียนโคด ...

Greg กล่าวว่าสิ่งที่เทียบเท่าถ้าคำสั่ง 'มีเสียงดัง' มันเป็นถ้าคุณเขียนมันดัง แต่ก็เหมือนกันถ้าสามารถเขียนเป็น:

if ('a' == $s) return 1;
if ('b' == $s) return 2;
if ('c' == $s) return 3;
return 4;

ซึ่งไม่มีเสียงดังกว่าไตรภาค ฉันสงสัยว่าทางลัดไปสามภาคหรือไม่; นิพจน์ทั้งหมดได้รับการประเมินหรือไม่


ตัวอย่างที่สองของคุณทำให้ฉันนึกถึงif (x != 0) x = 0;...
fredoverflow

2

ชั่ว? ดูสิพวกมันต่างกัน

ifเป็นคำสั่ง (test ? a : b)คือการแสดงออก พวกเขาไม่เหมือนกัน

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

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

หากคุณกังวลเกี่ยวกับความสามารถในการอ่านคุณสามารถจัดรูปแบบได้อย่างง่ายดาย

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


1
ฉันขอคำใบ้กับผู้ต้องสงสัยว่าเป็นใครได้บ้าง เพียงเพื่อปรับปรุงความรู้ของฉันของสนามเล็กน้อย
mlvljr

1
@mlvljr: ฉันอาจจะผิดดังนั้นดีกว่าที่จะไม่
Mike Dunlavey

1

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

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


1

ฉันไม่คิดว่าผู้ประกอบการที่สามเป็นความชั่วร้าย

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


1

อะไรก็ตามที่ทำให้โค้ดของคุณน่าเกลียดคือชั่วร้าย

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

"Hello ".($Male?"Mr":"Ms")." $Name

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


1

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

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

ได้โปรดเมตตาชื่อเสียงของฉันน่าสงสารแล้ว


1

ผู้ชนะที่ยิ่งใหญ่ที่สุด: แสดงให้เห็นว่ามีเป้าหมายเดียวของการกระทำ

if ( $is_whatever )
    $foo = 'A';
else
    $foo = 'B';

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

if ( $is_whatever )
    $foo = 'A';
else
    $bar = 'B';

ด้วยโอเปอเรเตอร์ผู้ประกอบการเห็นได้ชัดว่ามีการตั้งค่าตัวแปรเดียวเท่านั้น

$foo = $is_whatever ? 'A' : 'B';

ในระดับที่ต่ำที่สุดมันเป็นหลักการ DRY (อย่าทำซ้ำตัวเอง) ที่พื้นฐานที่สุด หากคุณสามารถระบุได้$fooเพียงครั้งเดียวให้ทำ


0

ถ้า ... ถ้าอย่างนั้น ... มีแนวโน้มที่จะเน้นย้ำเงื่อนไขและดังนั้นจึงยกเลิกการเน้นย้ำการปฏิบัติการที่มีเงื่อนไข

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

มี niggle ด้านเทคนิคเล็กน้อยในบางภาษาว่าพวกเขาไม่สามารถแลกเปลี่ยนกันได้เนื่องจากมีคำสั่งและนิพจน์เช่น const ที่เริ่มต้นแบบมีเงื่อนไขใน C ++


0

เมื่อใดที่เหมาะสมและเมื่อใด

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

ควรสอนหรือซ่อนเร้นจากผู้เริ่มต้นหรือไม่

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


0

IMO ตัวดำเนินการเองนั้นไม่ได้ชั่วร้าย แต่ไวยากรณ์ที่ใช้สำหรับมันใน C (และ C ++) นั้นสั้นเกินไป IMO, Algol 60 ทำได้ดีกว่าดังนั้นบางสิ่งเช่นนี้:

A = x == y ? B : C;

จะมีลักษณะเช่นนี้มากขึ้น (แต่ยึดติดกับไวยากรณ์ทั่วไปเช่น C):

A = if (x==y) B else C;

แม้จะมีการทำรังที่ลึกมากเกินไปอาจนำไปสู่ปัญหาเกี่ยวกับการอ่านได้ แต่อย่างน้อย A) ใครก็ตามที่เขียนโปรแกรมเสร็จแล้วสามารถคิดได้ว่าเป็นเรื่องง่ายและ B) ผู้ที่เข้าใจว่าสามารถจัดการการทำรังลึกได้ง่ายมาก OTOH ฉันจะทราบด้วยเช่นกันว่าใน LISP (ตัวอย่าง) a condนั้นคล้ายกับคำที่ประกอบไปด้วยไตรภาค - ไม่ใช่ชุดของคำสั่ง แต่การแสดงออกเพียงครั้งเดียวผลลัพธ์จะให้ค่า (จากนั้น LISP ส่วนใหญ่จะเป็นแบบนั้น .. .)


ทำไมไม่ทำเช่นนี้เพื่ออ่านง่าย? A = (x==y) ? B : C
Jeremy Heiler

@ Jeremy: ในขณะที่บางคนพบ parens ประโยชน์แม้ที่ดีที่สุดที่พวกเขาไม่ได้ช่วยมาก ทำรังมากกว่าสองสามลึกและคุณยังต้องมีการเยื้องอย่างระมัดระวัง (เป็นขั้นต่ำเปล่า) เพื่อแยกสิ่งต่าง ๆ ออก ไม่ต้องสงสัยเลยว่าจะเกิดขึ้นในท้ายที่สุดใน Algol แต่ฉันไม่เคยพูดว่ามีปัญหาเกิดขึ้นเหมือนที่ฉันมักจะทำใน C ...
Jerry Coffin

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

0

ร้านค้าที่เขียนวิธี 600-600 บรรทัดเป็นประจำไม่ควรบอกฉันว่าประกอบไปด้วย "ยากที่จะเข้าใจ" ร้านค้าใด ๆ ที่เป็นประจำจะช่วยให้ห้าเงื่อนไขในการประเมินสาขารหัสไม่ควรบอกว่าเงื่อนไขสรุปเป็นรูปธรรมใน ternary เป็น "ยากที่จะอ่าน"


0

เมื่อใด: เหมาะสมและเมื่อใด

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

ควรสอนหรือซ่อนเร้นจากผู้เริ่มต้นหรือไม่

ไม่สำคัญหรอก แต่ไม่ควรปิดบังความตั้งใจเพราะมันไม่ซับซ้อนเกินไปสำหรับ "ผู้เริ่มต้น" ในการเรียนรู้


-2

ในตัวอย่างของคุณ:

def median(a, b, c):
    if a < b < c: return b
    if a < c < b: return c
    if b < a < c: return a
    if b < c < a: return c
    if c < a < b: return a
    if c < b < a: return b

อ่านง่ายมากและชัดเจน ตัวแปรระหว่าง <<คือค่าที่ส่งคืน

ปรับปรุง

เหมือนกัน แต่มีโค้ดน้อยกว่า ฉันคิดว่าเรียบง่าย

def median(a, b, c):
    if b<a<c or c<a<b: return a
    if a<b<c or c<b<a: return b
    if a<c<b or b<c<a: return c

สิ่งนี้ต้องมีการเปรียบเทียบ 12 ครั้งในกรณีที่เลวร้ายที่สุด ...
fredoverflow

1
บางที แต่มันชัดเจน
Christopher Mahan

-2

นอกจากนี้ยังจำเป็นสำหรับ const

const int nLegs  = isChicken ? 2: 4 ;

แปลก. ฉันคิดว่ามัน C ++ หรืออะไรบางอย่าง ฉันคิดว่า const เคยคงที่รวบรวมเวลา (เช่นใน C #)
Nawfal

@nawfal - หากคุณไม่ทราบว่า isChicken จนกระทั่ง runtime
Martin Beckett

ใช่นั่นคืออะไร ฉันคิดว่าconstเป็นเช่นนั้นในบางภาษา ใน C # constควรจะรวบรวมค่าเวลาที่รู้จักกันเสมอ ซึ่งหมายความว่าconst int nLegs = isChicken ? 2: 4 ;จะไม่ทำงาน แต่const int nLegs = true ? 2: 4 ;จะ
nawfal
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.