ระบุชื่อพารามิเตอร์ทางเลือกแม้ว่าจะไม่จำเป็นก็ตาม?


25

พิจารณาวิธีการต่อไปนี้:

public List<Guid> ReturnEmployeeIds(bool includeManagement = false)
{

}

และสายต่อไปนี้:

var ids = ReturnEmployeeIds(true);

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

var ids = ReturnEmployeeIds(includeManagement: true);

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

บทความต่อไปนี้กล่าวถึงข้อตกลงการเข้ารหัสบางอย่าง: https://msdn.microsoft.com/en-gb/library/ff926074.aspx

สิ่งที่คล้ายกับบทความข้างต้นจะดีมาก


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

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

1
อาจรวมลิงก์นั้นเป็นแหล่งตัวอย่างในคำถามของคุณ
MetaFight

4
ถ้ามันเพิ่มอะไรฉันก็วิ่งผ่าน StyleCop & ReSharper - ไม่มีมุมมองที่ชัดเจนเลย ReSharper เพียงแค่บอกว่าพารามิเตอร์ที่มีชื่อสามารถลบออกได้และจากนั้นก็จะบอกว่าพารามิเตอร์ที่มีชื่อสามารถเพิ่ม คำแนะนำฟรีสำหรับเหตุผลที่ฉันเดา ... : - /
Robbie Dee

คำตอบ:


28

ฉันจะบอกว่าในโลก C #, Enum จะเป็นหนึ่งในตัวเลือกที่ดีที่สุดที่นี่

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

public enum WhatToInclude
{
    IncludeAll,
    ExcludeManagement
}

var ids = ReturnEmployeeIds(WhatToInclude.ExcludeManagement);

ดังนั้นในความคิดของฉันที่นี่:

enum> ตัวเลือก enum> ตัวเลือกบูล

แก้ไข: เนื่องจากการสนทนากับ LeopardSkinPillBoxHat ด้านล่างเกี่ยวกับ[Flags]enum ซึ่งในกรณีนี้อาจเหมาะสม (เนื่องจากเรากำลังพูดถึงการรวม / ไม่รวมสิ่งต่าง ๆ ) โดยเฉพาะฉันจึงขอเสนอให้ใช้ISet<WhatToInclude>เป็นพารามิเตอร์

มันเป็นแนวคิดที่ "ทันสมัย" มากขึ้นด้วยข้อดีหลายประการส่วนใหญ่มาจากความจริงที่ว่ามันเหมาะกับคอลเลกชันตระกูล LINQ แต่ก็[Flags]มีกลุ่มได้มากถึง 32 กลุ่ม ข้อเสียเปรียบหลักของการใช้ISet<WhatToInclude>คือการสนับสนุนชุดที่ไม่ดีในไวยากรณ์ C #:

var ids = ReturnEmployeeIds(
    new HashSet<WhatToInclude>(new []{ 
        WhatToInclude.Cleaners, 
        WhatToInclude.Managers});

บางส่วนอาจถูกลดทอนโดยฟังก์ชั่นตัวช่วยทั้งในการสร้างชุดและสำหรับการสร้าง "ชุดทางลัด" เช่น

var ids = ReturnEmployeeIds(WhatToIncludeHelper.IncludeAll)

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

3
ฉันชอบenumวิธีการ แต่ฉันไม่ได้เป็นแฟนตัวยงของการผสมIncludeและExcludeในเช่นเดียวenumกับมันยากที่จะเข้าใจสิ่งที่เกิดขึ้น หากคุณต้องการนี้จะขยายอย่างแท้จริงที่คุณสามารถทำมัน[Flags] enumให้พวกเขาทั้งหมดIncludeXxxและให้ซึ่งเป็นชุดที่IncludeAll Int32.MaxValueจากนั้นคุณสามารถระบุReturnEmployeeIdsโอเวอร์โหลดได้2 อัน- อันที่ส่งคืนพนักงานทั้งหมดและอีกอันที่รับWhatToIncludeพารามิเตอร์ตัวกรองซึ่งสามารถเป็นการรวมกันของแฟล็ก enum
LeopardSkinPillBox มี

@LeopardSkinPillBox มีอะไรฉันตกลงในการยกเว้น / รวม ดังนั้นนี่เป็นตัวอย่างของการวางแผน แต่ฉันอาจเรียกมันว่า IncludeAllButManagement ในอีกประเด็นของคุณฉันไม่เห็นด้วย - ฉันคิดว่า[Flags]เป็นของที่ระลึกและควรใช้เพื่อเหตุผลดั้งเดิมหรือเหตุผลด้านประสิทธิภาพเท่านั้น ฉันคิดว่าISet<WhatToInclude>เป็นแนวคิดที่ดีกว่าอย่างมาก (น่าเสียดายที่ C # ขาดน้ำตาลประโยคเพื่อให้ใช้งานได้ดี)
NiklasJ

@NiklasJ - ฉันชอบFlagsวิธีการเพราะช่วยให้ผู้โทรผ่านWhatToInclude.Managers | WhatToInclude.Cleanersและ bitwise หรือเป็นการแสดงออกอย่างชัดเจนว่าผู้โทรจะประมวลผลมันอย่างไร (เช่นผู้จัดการหรือน้ำยาทำความสะอาด) น้ำตาล syntactic ที่ใช้งานง่าย :-)
LeopardSkinPillBox มี

@LeopardSkinPillBoxHat แน่นอน แต่นั่นเป็นวิธีเดียวที่คว่ำ ข้อเสียรวมถึงตัวเลือกจำนวน จำกัด และไม่เข้ากันได้กับแนวคิดที่คล้ายกับ linq อื่น ๆ
NiklasJ

20

มันสมเหตุสมผลหรือไม่ที่จะเขียน:

 var ids=ReturnEmployeeIds(includeManagement: true);

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

 bool includeManagement=true;
 var ids=ReturnEmployeeIds(includeManagement);

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

ดังนั้นคำแนะนำของฉัน: ถ้าคุณคิดว่าการใช้ enum หรือสองฟังก์ชั่นที่มีชื่อแตกต่างกันคือ "overkill" หรือคุณไม่ต้องการหรือไม่สามารถเปลี่ยนลายเซ็นด้วยเหตุผลอื่นให้ไปข้างหน้าและใช้พารามิเตอร์ที่มีชื่อ


อาจต้องการทราบว่าคุณกำลังใช้หน่วยความจำเพิ่มเติมในตัวอย่างที่สอง
Alvaro

10
@Alvaro นั้นไม่น่าจะเป็นจริงได้ในกรณีเล็ก ๆ น้อย ๆ (ที่ตัวแปรมีค่าคงที่) ถึงแม้ว่ามันจะเป็นเรื่องยากที่จะกล่าวถึง วันนี้พวกเราส่วนใหญ่ไม่ได้ทำงานด้วย RAM 4KB
Chris Hayes

3
เนื่องจากนี่คือ C # คุณสามารถทำเครื่องหมายincludeManagementเป็นโลคอลconstและหลีกเลี่ยงการใช้หน่วยความจำเพิ่มเติมได้เลย
Jacob Krall

8
พวกฉันจะไม่เพิ่มสิ่งใด ๆ ลงในคำตอบของฉันซึ่งอาจเบี่ยงเบนความสนใจจากสิ่งที่ฉันคิดว่าเป็นสิ่งสำคัญที่นี่
Doc Brown

17

หากคุณพบรหัสเช่น:

public List<Guid> ReturnEmployeeIds(bool includeManagement = false)
{

}

คุณสามารถรับประกันได้ว่าสิ่งที่อยู่ภายใน{}จะเป็นอย่างไร:

public List<Guid> ReturnEmployeeIds(bool includeManagement = false)
{
    if (includeManagement)
        return something
    else
        return something else
}

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

public List<Guid> GetNonManagementEmployeeIds()
{

}

public List<Guid> GetAllEmployeeIds()
{

}

ทั้งสองนี้จะช่วยปรับปรุงความสามารถในการอ่านของรหัสและช่วยให้คุณปฏิบัติตามหลักการของ SOLID ได้ดียิ่งขึ้น

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

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

  • อาร์กิวเมนต์สำหรับระบุชื่อคือผู้พัฒนารายอื่น (รวมถึงตัวคุณเองในเวลาหกเดือน) ควรเป็นผู้ชมหลักของรหัสของคุณ คอมไพเลอร์เป็นผู้ชมสำรองแน่นอน ดังนั้นควรเขียนรหัสเพื่อให้ผู้อื่นอ่านง่ายขึ้น มากกว่าแค่การจัดหาสิ่งที่คอมไพเลอร์ต้องการ ตัวอย่างของวิธีที่เราใช้กฎนี้ทุกวันคือเราไม่ใส่โค้ดของเราด้วยตัวแปร _1, _2 ฯลฯ เราใช้ชื่อที่มีความหมาย (ซึ่งไม่มีความหมายต่อคอมไพเลอร์)
  • อาร์กิวเมนต์ตัวนับเป็นวิธีส่วนตัวที่มีรายละเอียดการใช้งาน ใคร ๆ ก็สามารถคาดหวังได้ว่าใครก็ตามที่กำลังมองหาวิธีเช่นด้านล่างนี้จะติดตามรหัสเพื่อทำความเข้าใจวัตถุประสงค์ของพารามิเตอร์บูลีนเนื่องจากพวกเขาอยู่ภายใน internals ของรหัส:
public List<Guid> GetNonManagementEmployeeIds()
{
    return ReturnEmployeeIds(true);
}

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


12
ฉันได้ยินสิ่งที่คุณพูด แต่คุณพลาดจุดที่ฉันขอไป สมมติว่าสถานการณ์โดยมันเป็นที่เหมาะสมที่สุดในการใช้พารามิเตอร์ที่ไม่จำเป็น (สถานการณ์เหล่านี้ทำอยู่) ก็ตกลงที่จะตั้งชื่อพารามิเตอร์แม้ว่ามันจะไม่จำเป็น?
JᴀʏMᴇᴇ

4
จริงทั้งหมด แต่คำถามเกี่ยวกับการเรียกวิธีการดังกล่าว นอกจากนี้พารามิเตอร์การตั้งค่าสถานะไม่รับประกันสาขาภายในวิธีเลย มันอาจถูกส่งต่อไปยังเลเยอร์อื่น
Robbie Dee

สิ่งนี้ไม่ผิด แต่เป็นการทำให้ใหญ่เกินไป ในรหัสจริงคุณจะพบpublic List<Guid> ReturnEmployeeIds(bool includeManagement) { calculateSomethingHereForBothBranches; if (includeManagement) return something else return something else }ดังนั้นการแยกออกเป็นสองวิธีอาจจะหมายความว่าทั้งสองวิธีจะต้องใช้ผลลัพธ์ของการคำนวณครั้งแรกเป็นพารามิเตอร์
Doc Brown เมื่อ

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

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

1

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

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

ตัวอย่างเช่นมันอาจช่วยชี้แจงหนึ่งสาย แต่ไม่จำเป็นอีก

อาร์กิวเมนต์ที่ระบุชื่ออาจมีประโยชน์ที่นี่:

var ids = ReturnEmployeeIds(includeManagement: true);

ไม่เพิ่มความชัดเจนเพิ่มเติม (ฉันจะเดาว่านี่คือการแยกวิเคราะห์ enum):

Enum.Parse(typeof(StringComparison), "Ordinal", ignoreCase: true);

อาจลดความชัดเจน (ถ้าคนไม่เข้าใจความสามารถในรายการ):

var employeeIds = new List<int>(capacity: 24);

หรือที่ไม่สำคัญเพราะคุณใช้ชื่อตัวแปรที่ดี:

bool includeManagement = true;
var ids = ReturnEmployeeIds(includeManagement);

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

ไม่ใช่ AFAIK ให้ลองพิจารณาทั้งสองส่วน: ครั้งเดียวที่คุณต้องใช้พารามิเตอร์ที่กำหนดไว้อย่างชัดเจนคือเพราะคอมไพเลอร์ต้องการให้คุณทำ (โดยทั่วไปจะเป็นการลบความคลุมเครือของคำสั่ง) นอกจากนั้นคุณสามารถใช้มันได้ทุกเมื่อที่คุณต้องการ บทความนี้จาก MS มีคำแนะนำบางประการเกี่ยวกับเวลาที่คุณอาจต้องการใช้ แต่ไม่ได้มีความชัดเจนมากนักhttps://msdn.microsoft.com/en-us/library/dd264739.aspx

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

TL; DR

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


0

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

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

ตอนนี้ให้พิจารณากรณีที่สามนี้:

void PrintEmployeeNames(bool includeManagement) {
    foreach (id; ReturnEmployeeIds(includeManagement)) {
        Console.WriteLine(ReturnEmployeeName(id));
    }
}

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

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


7
ฉันไม่เห็นด้วยที่ReturnEmployeeName(57)ทำให้ชัดเจนทันทีว่า57เป็น ID GetEmployeeById(57)ในทางกลับกัน ...
Hugo Zink

@HugoZink ตอนแรกฉันต้องการใช้บางอย่างเช่นนั้น แต่ฉันตั้งใจเปลี่ยนReturnEmployeeNameให้แสดงกรณีที่แม้ไม่ได้กล่าวถึงพารามิเตอร์ในชื่อของเมธอดอย่างชัดเจนก็สมเหตุสมผลพอที่จะคาดหวังให้คนคิดว่ามันคืออะไร ไม่ว่าในกรณีใดก็ตามReturnEmployeeNameคุณไม่สามารถเปลี่ยนชื่อReturnEmployeeIdsเป็นสิ่งที่บ่งบอกถึงความหมายของพารามิเตอร์ได้
Idan Arye

1
ไม่ว่าในกรณีใดมันก็ไม่น่าเป็นไปได้ที่เราจะเขียน ReturnEmployeeName (57) ในโปรแกรมจริง มีโอกาสมากที่เราจะเขียน ReturnEmployeeName (employeeId) ทำไมเราต้อง hardcode รหัสพนักงาน? นอกจากจะเป็น ID ของโปรแกรมเมอร์และมีการฉ้อโกงบางประเภทเกิดขึ้นเช่นเพิ่มนิดหน่อยในบัญชีเงินเดือนของพนักงานคนนี้ :-)
Jay

0

ใช่ฉันคิดว่ามันเป็นสไตล์ที่ดี

วิธีนี้เหมาะสมที่สุดสำหรับค่าคงที่บูลีนและจำนวนเต็ม

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

หากคุณส่งผ่านสตริงความหมายมักชัดเจน เช่นถ้าฉันเห็นการเรียกไปยัง GetFooData ("Oregon") ฉันคิดว่าผู้อ่านสามารถเดาได้ว่าพารามิเตอร์นั้นเป็นชื่อรัฐ

แน่นอนว่าสายทั้งหมดนั้นไม่ชัดเจน ถ้าฉันเห็น GetFooData ("M") ถ้าฉันไม่ทราบฟังก์ชันฉันไม่รู้ว่า "M" หมายถึงอะไร หากเป็นรหัสบางประเภทเช่น M = "พนักงานระดับการจัดการ" ดังนั้นเราน่าจะควรมี enum มากกว่าตัวอักษรและชื่อ enum ควรชัดเจน

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

แต่ GetFooData (จริง) หรือ GetFooData (42) ... นั่นอาจหมายถึงอะไรก็ได้ พารามิเตอร์ที่กำหนดชื่อเป็นวิธีที่ยอดเยี่ยมในการจัดทำเอกสารด้วยตนเอง ฉันใช้มันเพื่อจุดประสงค์นั้นหลายครั้ง


0

ไม่มีเหตุผลใดที่ชัดเจนเป็นพิเศษว่าทำไมต้องใช้ไวยากรณ์ประเภทนี้ตั้งแต่แรก

โดยทั่วไปแล้วพยายามหลีกเลี่ยงการมีข้อโต้แย้งแบบบูลว่าระยะทางอาจดูไม่เจาะจง includeManagementจะ (ส่วนใหญ่) จะส่งผลกระทบต่อผลอย่างมาก แต่ข้อโต้แย้งดูเหมือนว่าจะมี "น้ำหนักน้อย"

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

พิจารณาสิ่งนี้: หากคุณปรับขนาดWhatToInclude-enum แต่ไม่ใช่ReturnEmployeeIds-method จากนั้นอาจโยนArgumentOutOfRangeException(กรณีที่ดีที่สุด) หรือส่งคืนสิ่งที่ไม่ต้องการอย่างสมบูรณ์ ( nullหรือว่างเปล่าList<Guid>) ซึ่งในบางกรณีอาจสร้างความสับสนให้โปรแกรมเมอร์โดยเฉพาะอย่างยิ่งหากคุณReturnEmployeeIdsอยู่ในไลบรารีคลาสซึ่งซอร์สโค้ดไม่พร้อมใช้งาน

หนึ่งจะคิดว่าWhatToInclude.Traineesจะทำงานถ้าWhatToInclude.Allไม่เห็นผู้ฝึกอบรมที่เป็น "ส่วนย่อย" ของทั้งหมด

สิ่งนี้ (แน่นอน) ขึ้นอยู่กับวิธี ReturnEmployeeIdsการนำไปใช้


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

เนื่องจากมีเพียงสองผลลัพธ์สำหรับบางสิ่งที่มีอาร์กิวเมนต์บูลีน การใช้สองวิธีใช้ความพยายามน้อยมาก

รหัสน้อยกว่าไม่ค่อยดีกว่า


ด้วยวิธีนี้กล่าวว่ามีมีบางกรณีที่ประกาศอย่างชัดเจนว่าการโต้แย้งช่วยเพิ่มความสามารถในการอ่าน พิจารณาตัวอย่าง GetLatestNews(max: 10). GetLatestNews(10)คือยังคงสวยอธิบายตนเองประกาศชัดเจนmaxจะช่วยให้ชัดเจนขึ้นใด ๆเกิดความสับสน

และถ้าคุณอย่างจะต้องมีการโต้แย้งแบบบูลซึ่งการใช้งานไม่สามารถสรุปได้โดยเพียงแค่การอ่านหรือtrue falseจากนั้นฉันก็จะบอกว่า:

var ids = ReturnEmployeeIds(includeManagement: true);

.. ดีกว่าจริง ๆ และอ่านง่ายกว่า:

var ids = ReturnEmployeeIds(true);

เนื่องจากในตัวอย่างที่สองที่trueอาจหมายถึงอย่างแน่นอนอะไร แต่ฉันจะพยายามหลีกเลี่ยงข้อโต้แย้งนี้

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