ฉันจะโทรด้วยบูลีนที่ชัดเจนขึ้นได้อย่างไร? กับดักบูลีน


76

ตามที่ระบุไว้โดยในความคิดเห็นโดย @ benjamin-gruenbaum สิ่งนี้เรียกว่ากับดักบูลีน:

สมมติว่าฉันมีฟังก์ชั่นเช่นนี้

UpdateRow(var item, bool externalCall);

และในคอนโทรลเลอร์ของฉันค่าexternalCallนั้นจะเป็นจริงเสมอ วิธีที่ดีที่สุดในการเรียกใช้ฟังก์ชันนี้คืออะไร ฉันมักจะเขียน

UpdateRow(item, true);

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

bool externalCall = true;
UpdateRow(item, externalCall);

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

PD2: ฉันไม่ได้ติดแท็กภาษาใด ๆ 'เพราะฉันคิดว่ามันเป็นปัญหาทั่วไปมาก อย่างไรก็ตามฉันทำงานกับ c # และคำตอบที่ยอมรับนั้นใช้ได้กับ c #


10
รูปแบบนี้เรียกอีกอย่างว่ากับดักบูลีน
Benjamin Gruenbaum

11
หากคุณกำลังใช้ภาษาที่สนับสนุนประเภทข้อมูลเกี่ยวกับพีชคณิตฉันขอแนะนำ adt ใหม่แทนบูลีน data CallType = ExternalCall | InternalCallใน Haskell เช่น
Filip Haglund

6
ฉันเดาว่า Enums จะเติมเต็มวัตถุประสงค์เดียวกัน รับชื่อสำหรับ booleans และความปลอดภัยเล็กน้อย
Filip Haglund

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

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

คำตอบ:


154

ไม่มีวิธีแก้ปัญหาที่สมบูรณ์แบบเสมอไป แต่คุณมีทางเลือกมากมายให้เลือก:

  • ใช้อาร์กิวเมนต์ที่มีชื่อหากมีในภาษาของคุณ มันใช้งานได้ดีมากและไม่มีข้อเสีย ในบางภาษาอาร์กิวเมนต์ใด ๆ ที่สามารถส่งผ่านเป็นอาร์กิวเมนต์ที่กำหนดชื่อเช่นupdateRow(item, externalCall: true)( C # ) หรือupdate_row(item, external_call=True)(Python)

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

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

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

  • ใช้enum ปัญหาเกี่ยวกับบูลีนคือพวกเขาถูกเรียกว่า "จริง" และ "เท็จ" ดังนั้นแทนที่จะแนะนำประเภทที่มีชื่อที่ดีกว่า (เช่นenum CallType { INTERNAL, EXTERNAL }) ในฐานะที่เป็นประโยชน์เพิ่มเติมนี้จะเพิ่มความปลอดภัยประเภทของโปรแกรมของคุณ (หากภาษาของคุณใช้ enums เป็นประเภทที่แตกต่างกัน) ข้อเสียเปรียบของ enums ก็คือพวกเขาจะเพิ่มประเภทให้กับ API ที่เปิดเผยต่อสาธารณะของคุณ สำหรับฟังก์ชั่นภายในอย่างแท้จริงนี้ไม่สำคัญและ enums ไม่มีข้อเสียอย่างมีนัยสำคัญ

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

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


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

6
สิ่งหนึ่งที่สามารถช่วยบรรเทาปัญหาเกี่ยวกับสตริงสั้น ๆ คือการใช้ค่าคงที่กับค่าสตริง @MarioGarcia ไม่มีอะไรให้ทำอย่างละเอียด นอกเหนือจากสิ่งที่กล่าวถึงที่นี่รายละเอียดส่วนใหญ่จะขึ้นอยู่กับภาษาเฉพาะ มีบางสิ่งที่คุณต้องการเห็นพูดถึงที่นี่ไหม?
jpmc26

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

4
ข้อบกพร่องอื่นของการใช้สตริงในบทบาทนี้คือคุณไม่สามารถตรวจสอบความถูกต้องได้ในเวลารวบรวมซึ่งแตกต่างจาก enums
Ruslan

32
enumเป็นผู้ชนะ เพียงเพราะพารามิเตอร์สามารถมีสถานะที่เป็นไปได้หนึ่งในสองสถานะเท่านั้นนั่นไม่ได้หมายความว่าควรเป็นบูลีนโดยอัตโนมัติ
Pete

39

วิธีแก้ไขที่ถูกต้องคือทำสิ่งที่คุณแนะนำ แต่บรรจุลงในซุ้มขนาดเล็ก:

void updateRowExternally() {
  bool externalCall = true;
  UpdateRow(item, externalCall);
}

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


8
การห่อหุ้มนี้คุ้มหรือไม่เมื่อฉันเรียก funcion นั้นเพียงครั้งเดียวในคอนโทรลเลอร์ของฉัน?
Mario Garcia

14
ใช่. ใช่แล้ว. เหตุผลที่ฉันเขียนข้างต้นคือค่าใช้จ่าย (การเรียกใช้ฟังก์ชัน) น้อยกว่าประโยชน์ (คุณประหยัดเวลานักพัฒนาน้อยเพราะไม่มีใครเคยค้นหาสิ่งที่trueทำ) มันจะคุ้มค่าแม้ว่ามันจะคุ้มค่า ประหยัดเวลาของ CPU มากเท่าที่จะช่วยประหยัดเวลานักพัฒนาเนื่องจากเวลาของ CPU นั้นถูกกว่า
Kilian Foth

8
นอกจากนี้เครื่องมือเพิ่มประสิทธิภาพที่มีอำนาจใด ๆ ควรจะสามารถแทรกสิ่งนั้นให้คุณดังนั้นคุณไม่ควรทำสิ่งใดเสียในที่สุด
firedraco

33
@KilianFoth ยกเว้นว่าเป็นข้อสมมติฐานที่ผิดพลาด ผู้ดูแลไม่จำเป็นต้องรู้ว่าพารามิเตอร์ที่สองไม่และทำไมมันเป็นความจริงและเกือบตลอดเวลานี้เกี่ยวข้องกับรายละเอียดของสิ่งที่คุณกำลังพยายามที่จะทำ การซ่อนฟังก์ชั่นในฟังก์ชั่นจิ๋วที่เสียชีวิตต่อครั้งจะลดการบำรุงรักษา แต่ไม่เพิ่มขึ้น ฉันเคยเห็นมันเกิดขึ้นด้วยตัวเองเศร้าที่จะพูด การแบ่งพาร์ติชันที่มากเกินไปเข้าไปในฟังก์ชั่นอาจเลวร้ายยิ่งกว่าฟังก์ชั่นใหญ่ของพระเจ้า
เกรแฮม

6
ฉันคิดว่าUpdateRow(item, true /*external call*/);น่าจะสะอาดกว่าในภาษาที่อนุญาตให้ใช้ไวยากรณ์ความคิดเห็นนั้น การเขียนโค้ดของคุณด้วยฟังก์ชั่นพิเศษเพื่อหลีกเลี่ยงการเขียนความคิดเห็นนั้นไม่คุ้มค่าสำหรับกรณีง่ายๆ อาจเป็นเพราะมีฟังก์ชั่นอื่น ๆ อีกมากมายและ / หรือมีรหัสที่ล้อมรอบและมีเละเทะ + บางอย่างมันจะเริ่มดึงดูดมากขึ้น แต่ฉันคิดว่าถ้าคุณกำลังดีบั๊กคุณจะต้องตรวจสอบฟังก์ชั่น wrapper เพื่อดูว่ามันทำอะไรและต้องจำไว้ว่าฟังก์ชั่นใดบ้างที่ล้อมรอบไลบรารี API และซึ่งมีตรรกะบางอย่าง
Peter Cordes

25

บอกว่าฉันมีฟังก์ชั่นเช่น UpdateRow (รายการ var, บูล externalCall);

ทำไมคุณมีฟังก์ชั่นเช่นนี้

ภายใต้สถานการณ์ใดที่คุณจะเรียกมันด้วยอาร์กิวเมนต์ externalCall ที่ตั้งค่าเป็นค่าที่ต่างกัน

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

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


6
ฉันเห็นด้วย. และเพื่อตอกประเด็นให้กับผู้อ่านคนอื่น ๆ การวิเคราะห์สามารถทำได้กับผู้โทรทุกคนที่จะผ่านทั้งความจริงเท็จหรือตัวแปร หากไม่พบอันหลังฉันจะโต้แย้งสองวิธีแยกกัน (โดยไม่มีบูลีน) เหนือหนึ่งด้วยบูลีน - เป็นอาร์กิวเมนต์ YAGNI ที่บูลีนนำเสนอความซับซ้อนที่ไม่ได้ใช้ / ไม่จำเป็น แม้ว่าจะมีผู้เรียกบางคนกำลังส่งผ่านตัวแปรฉันยังคงจัดให้มีรุ่นที่ปราศจากพารามิเตอร์ (บูลีน) เพื่อใช้สำหรับผู้โทรที่ผ่านค่าคงที่ - มันง่ายกว่าซึ่งดี
Erik Eidt

18

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

UpdateRow(item, true /* row is an external call */);

หรือ:

UpdateRow(item, true); // true means call is external

หรือ (ถูกต้องตามที่แนะนำโดย Frax):

UpdateRow(item, /* externalCall */true);

1
ไม่มีเหตุผลให้ลงคะแนน นี่เป็นข้อเสนอแนะที่ถูกต้องสมบูรณ์
Suncat2000

ขอบคุณ <3 @ Suncat2000!
บิชอป

11
A (มีแนวโน้มที่ดีกว่า) UpdateRow(item, /* externalCall */ true )ที่แตกต่างเป็นเพียงแค่ใส่ชื่ออาร์กิวเมนต์ธรรมดามีเช่น ความคิดเห็นเต็มประโยคนั้นยากที่จะแยกวิเคราะห์มันเป็นเสียงส่วนใหญ่ (โดยเฉพาะอย่างยิ่งตัวแปรที่สอง
Frax

1
นี่คือคำตอบที่เหมาะสมที่สุด นี่คือสิ่งที่ความคิดเห็นมีไว้สำหรับ
Sentinel

9
ไม่ใช่แฟนตัวยงของความเห็นเช่นนี้ ความคิดเห็นมีแนวโน้มที่จะกลายเป็นเก่าถ้าไม่ถูกแตะต้องเมื่อทำการปรับโครงสร้างใหม่หรือทำการเปลี่ยนแปลงอื่น ๆ ไม่ต้องพูดถึงเมื่อคุณมีมากกว่าหนึ่ง bool param สิ่งนี้ทำให้เกิดความสับสนอย่างรวดเร็ว
John V.

11
  1. คุณสามารถ 'ตั้งชื่อ' คนขายเครื่องของคุณ ด้านล่างเป็นตัวอย่างสำหรับภาษา OO (ซึ่งสามารถแสดงในชั้นเรียนได้UpdateRow()) อย่างไรก็ตามแนวคิดนี้สามารถนำไปใช้ในภาษาใดก็ได้:

    class Table
    {
    public:
        static const bool WithExternalCall = true;
        static const bool WithoutExternalCall = false;
    

    และในเว็บไซต์โทร:

    UpdateRow(item, Table::WithExternalCall);
    
  2. ฉันเชื่อว่ารายการ # 1 ดีกว่า แต่ก็ไม่ได้บังคับให้ผู้ใช้ใช้ตัวแปรใหม่เมื่อใช้ฟังก์ชัน หากความปลอดภัยของประเภทมีความสำคัญสำหรับคุณคุณสามารถสร้างenumประเภทและUpdateRow()ยอมรับสิ่งนี้แทนbool:

    UpdateRow(var item, ExternalCallAvailability ec);

  3. คุณสามารถปรับเปลี่ยนชื่อของฟังก์ชั่นอย่างใดที่มันสะท้อนให้เห็นถึงความหมายของboolพารามิเตอร์ที่ดีกว่า ไม่แน่ใจ แต่อาจจะ:

    UpdateRowWithExternalCall(var item, bool externalCall)


8
ไม่ชอบ # 3 ในขณะนี้ถ้าคุณเรียกใช้ฟังก์ชันด้วยexternalCall=falseชื่อของมันไม่สมเหตุสมผล คำตอบที่เหลือของคุณนั้นดี
การแข่งขัน Lightness ใน Orbit

ตกลง ฉันไม่ค่อยแน่ใจนัก แต่อาจเป็นตัวเลือกที่เหมาะสมสำหรับฟังก์ชั่นอื่น I
simurg

@LightnessRacesinOrbit แน่นอน UpdateRowWithUsuallyExternalButPossiblyInternalCallมันปลอดภัยที่จะไป
Eric Duminil

@EricDuminil: จุดบน😂
การแข่งขัน Lightness ใน Orbit

10

ตัวเลือกอื่นที่ฉันยังไม่ได้อ่านที่นี่คือ: ใช้ IDE ที่ทันสมัย

ตัวอย่างเช่นความคิด IntelliJ พิมพ์ชื่อตัวแปรของตัวแปรในวิธีการที่คุณโทรถ้าคุณผ่านตัวอักษรเช่นtrueหรือหรือnull username + “@company.comสิ่งนี้ทำในแบบอักษรขนาดเล็กดังนั้นจึงไม่ใช้พื้นที่มากเกินไปบนหน้าจอของคุณและดูแตกต่างจากรหัสจริงมาก

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

ตัวอย่างดัดแปลงจากส่วนหนึ่งของการตั้งค่าการทดสอบของฉัน: ป้อนคำอธิบายรูปภาพที่นี่


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

@DanielPryden แน่นอนดังนั้นความคิดเห็นของฉันและเพื่อนร่วมงานของคุณ เป็นเรื่องปกติที่จะมี IDE มาตรฐานใน บริษัท ต่างๆ สำหรับเครื่องมืออื่น ๆ ฉันขอยืนยันว่าเป็นไปได้ว่าเครื่องมือประเภทเหล่านี้อาจสนับสนุนสิ่งนี้หรือจะเป็นในอนาคตหรือว่าข้อโต้แย้งเหล่านั้นไม่ได้ใช้ (เช่นสำหรับทีมเขียนโปรแกรมคู่คน 2 คน)
Sebastiaan van den Broek

2
@Sebastiaan: ฉันไม่คิดว่าฉันเห็นด้วย แม้ในฐานะนักพัฒนาเดี่ยวฉันก็อ่านรหัสของตัวเองใน Git อย่างสม่ำเสมอ Git จะไม่สามารถทำวิชวลไลเซชันบริบทแบบเดียวกับที่ IDE สามารถทำได้และไม่ควรทำ ฉันทุกคนใช้ IDE ที่ดีเพื่อช่วยคุณเขียนโค้ด แต่คุณไม่ควรใช้ IDE เป็นข้ออ้างในการเขียนโค้ดที่คุณจะไม่ได้เขียนถ้าไม่มีมัน
Daniel Pryden

1
@DanielPryden ฉันไม่สนับสนุนการเขียนรหัสเลอะเทอะมาก มันไม่ใช่สถานการณ์ขาวดำ อาจมีบางกรณีที่ในอดีตสำหรับสถานการณ์เฉพาะคุณจะ 40% ชอบเขียนฟังก์ชันด้วยบูลีนและไม่ 60% และคุณไม่ได้ทำมัน อาจมีการสนับสนุน IDE ที่ดีในขณะนี้ยอดคงเหลือคือ 55% เขียนแบบนั้นและ 45% ไม่ และใช่คุณยังอาจจำเป็นต้องอ่านนอก IDE บางครั้งดังนั้นจึงไม่สมบูรณ์ แต่ก็ยังคงมีการแลกเปลี่ยนที่ถูกต้องกับทางเลือกเช่นการเพิ่มวิธีการอื่นหรือการแจงนับเพื่อชี้แจงรหัสมิฉะนั้น
Sebastiaan van den Broek

6

2 วันและไม่มีใครพูดถึงความแตกต่าง?

target.UpdateRow(item);

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

ทำอย่างนั้นและมันจะกลายเป็นส่วนหนึ่งของปัญหาการก่อสร้าง ที่สามารถแก้ไขได้หลายวิธี นี่คือหนึ่ง:

Target xyzTargetFactory(TargetBuilder targetBuilder) {
    return targetBuilder
        .connectionString("some connection string")
        .table("table_name")
        .external()
        .build()
    ; 
}

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

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


2

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

function updateRow(var item, bool externalCall) {
  Database.update(item);

  if (externalCall) {
    Service.call();
  }
}

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

function updateRowAndService(var item) {
  updateRow(item);
  Service.call();
}

function updateRow(var item) {
  Database.update(item);
}

ตอนนี้ทุกที่ที่คุณเรียกใช้ฟังก์ชั่นเหล่านี้คุณสามารถบอกได้ทันทีว่ามีการให้บริการภายนอกหรือไม่

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


0

หาก UpdateRow อยู่ใน codebase ที่ควบคุมฉันจะพิจารณารูปแบบกลยุทธ์:

public delegate void Request(string query);    
public void UpdateRow(Item item, Request request);

โดยที่ Request หมายถึง DAO บางประเภท (การโทรกลับในกรณีเล็กน้อย)

กรณีจริง:

UpdateRow(item, query =>  queryDatabase(query) ); // perform remote call

กรณีเท็จ:

UpdateRow(item, query => readLocalCache(query) ); // skip remote call

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

UpdateRow(item, query => {
  var data = readLocalCache(query);
  if (data == null) {
    data = queryDatabase(query);
  }
  return data;
} );

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

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