นิพจน์บูลีนขนาดใหญ่สามารถอ่านได้มากกว่านิพจน์เดียวกันที่แบ่งออกเป็นวิธีเพรดิเคตหรือไม่ [ปิด]


63

จะเข้าใจอะไรได้ง่ายกว่าคำสั่งบูลีนขนาดใหญ่ (ค่อนข้างซับซ้อน) หรือคำเดียวกันนี้แบ่งออกเป็นเมธอดเพรดิเคต (มีโค้ดพิเศษมากมายให้อ่าน)

ตัวเลือก 1 นิพจน์บูลีนขนาดใหญ่:

    private static bool ContextMatchesProp(CurrentSearchContext context, TValToMatch propVal)
    {

        return propVal.PropertyId == context.Definition.Id
            && !repo.ParentId.HasValue || repo.ParentId == propVal.ParentId
            && ((propVal.SecondaryFilter.HasValue && context.SecondaryFilter.HasValue && propVal.SecondaryFilter.Value == context.SecondaryFilter) || (!context.SecondaryFilter.HasValue && !propVal.SecondaryFilter.HasValue));
    }

ตัวเลือก 2 เงื่อนไขแบ่งออกเป็นวิธีเพรดิเคต:

    private static bool ContextMatchesProp(CurrentSearchContext context, TValToMatch propVal)
    {
        return MatchesDefinitionId(context, propVal)
            && MatchesParentId(propVal)
            && (MatchedSecondaryFilter(context, propVal) || HasNoSecondaryFilter(context, propVal));
    }

    private static bool HasNoSecondaryFilter(CurrentSearchContext context, TValToMatch propVal)
    {
        return (!context.No.HasValue && !propVal.SecondaryFilter.HasValue);
    }

    private static bool MatchedSecondaryFilter(CurrentSearchContext context, TValToMatch propVal)
    {
        return (propVal.SecondaryFilter.HasValue && context.No.HasValue && propVal.SecondaryFilter.Value == context.No);
    }

    private bool MatchesParentId(TValToMatch propVal)
    {
        return (!repo.ParentId.HasValue || repo.ParentId == propVal.ParentId);
    }

    private static bool MatchesDefinitionId(CurrentSearchContext context, TValToMatch propVal)
    {
        return propVal.PropertyId == context.Definition.Id;
    }

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


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

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

3
สิ่งที่ผู้พูด @ @ ความจริงที่ว่าการทำมันด้วยวิธีแรกทำให้คุณทำผิดพลาดเป็นเงื่อนงำที่ค่อนข้างดีว่าวิธีแรกนั้นไม่สามารถเข้าใจได้ง่ายในส่วนที่สำคัญมากของกลุ่มเป้าหมายของคุณ ตัวเอง!
Steve Jessop

3
ตัวเลือก 3: ฉันไม่ชอบอย่างใดอย่างหนึ่ง อย่างที่สองคือ verbose ที่น่าขันที่หนึ่งไม่เท่ากับที่สอง วงเล็บช่วย
David Hammen

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

คำตอบ:


88

สิ่งที่เข้าใจง่ายกว่าคือ

แนวทางหลัง มันไม่เพียง แต่ง่ายต่อการเข้าใจ แต่ยังง่ายกว่าในการเขียนทดสอบ refactor และขยายอีกด้วย แต่ละเงื่อนไขที่ต้องการสามารถแยกได้อย่างปลอดภัยและจัดการในแบบของตัวเอง

มันเป็นปัญหาเพราะคุณต้องอ่านวิธีการทั้งหมดเพื่อทำความเข้าใจโค้ด

มันไม่มีปัญหาหากวิธีการตั้งชื่ออย่างถูกต้อง ในความเป็นจริงมันจะง่ายต่อการเข้าใจเป็นชื่อวิธีจะอธิบายถึงเจตนาของเงื่อนไข
สำหรับผู้สังเกตการณ์if MatchesDefinitionId()นั้นมีคำอธิบายมากกว่าif (propVal.PropertyId == context.Definition.Id)

[โดยส่วนตัววิธีแรกที่ทำให้ตาของฉันเจ็บ]


12
หากชื่อเมธอดนั้นดีก็จะเข้าใจได้ง่ายขึ้น
BЈовић

และโปรดทำให้พวกเขา (ชื่อวิธีการ) อย่างมีนัยสำคัญและสั้น 20+ วิธีการตัวอักษรชื่อเจ็บตาของฉัน MatchesDefinitionId()เป็นเส้นเขตแดน
Mindwin

2
@Mindwin หากมันเป็นทางเลือกระหว่างการรักษาชื่อเมธอด "short" และทำให้มันมีความหมายฉันจะใช้หลังทุกครั้ง สั้นเป็นสิ่งที่ดี แต่ไม่เสียค่าใช้จ่ายในการอ่าน
Ajedi32

@ Ajedi32 ไม่จำเป็นต้องเขียนเรียงความเกี่ยวกับสิ่งที่วิธีการทำกับชื่อวิธีการหรือมีชื่อวิธีเสียงที่น่าทึ่ง หากใครรักษามาตรฐานตัวย่อให้ชัดเจน (ทั่วทั้งกลุ่มงานหรือองค์กร) จะไม่มีปัญหากับชื่อและการอ่านที่สั้น
Mindwin

ใช้กฎของ Zipf: ทำให้ทุกอย่างละเอียดยิ่งขึ้นเพื่อกีดกันการใช้งาน
hoosierEE

44

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

private static bool ContextMatchesProp(CurrentSearchContext context, TValToMatch propVal)
{
    bool matchesDefinitionId = (propVal.PropertyId == context.Definition.Id);
    bool matchesParentId = (!repo.ParentId.HasValue || repo.ParentId == propVal.ParentId);
    bool matchesSecondaryFilter = (propVal.SecondaryFilter.HasValue && context.No.HasValue && propVal.SecondaryFilter.Value == context.No);
    bool hasNoSecondaryFilter = (!context.No.HasValue && !propVal.SecondaryFilter.HasValue);

    return matchesDefinitionId
        && matchesParentId
        && matchesSecondaryFilter || hasNoSecondaryFilter;
}

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

bool hasSecondaryFilter = propVal.SecondaryFilter.HasValue;

propVal.SecondaryFilter.HasValueแล้วเปลี่ยนทุกกรณี สิ่งหนึ่งที่ยื่นออกมาทันทีก็คือhasNoSecondaryFilterใช้ตรรกะ AND กับHasValueคุณสมบัติที่ถูกทำให้ยุ่งเหยิงในขณะที่matchesSecondaryFilterใช้ตรรกะ AND บนที่ไม่ถูกปฏิเสธHasValue- ดังนั้นจึงไม่ใช่สิ่งที่ตรงกันข้าม


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

5
การทดสอบ @BuvinJ เช่นเดียวกับที่แสดงในที่นี้ควรมีราคาถูกพอสมควรดังนั้นหากฉันไม่ทราบว่ามีเงื่อนไขบางอย่างที่มีราคาแพงหรือหากนี่คือรหัสที่มีประสิทธิภาพสูง
svick

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

การเพิ่มความคิดเห็นสามารถช่วยให้สามารถอ่านได้ด้วย ...
BuvinJ

@BuvinJ สิ่งที่ฉันชอบเกี่ยวกับวิธีนี้คือการเพิกเฉยทุกอย่างยกเว้นบรรทัดสุดท้ายฉันสามารถเข้าใจได้อย่างรวดเร็วว่ากำลังทำอะไรอยู่ ฉันคิดว่ามันอ่านง่ายขึ้น
svick

42

โดยทั่วไปแล้วจะนิยมใช้หลัง

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

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


1
ใช่แม้ว่าคำตอบของคุณควรแก้ไขการใช้repoซึ่งจะปรากฏเป็นเขตข้อมูล / คุณสมบัติคงที่เช่นตัวแปรทั่วโลก วิธีการทางสถิติควรจะกำหนดและไม่ใช้ตัวแปรทั่วโลก
David Arno

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

1
ใช่ไม่เป็นไร repo ผมต้องทำให้งงงวยรหัสเล็ก ๆ น้อย ๆ ไม่ต้องการที่จะแบ่งปันรหัสลูกค้าตามที่เป็นใน interwebs :) ความ
วิลเล็ม

23

หากอยู่ระหว่างตัวเลือกทั้งสองตัวเลือกหลังจะดีกว่า อย่างไรก็ตามสิ่งเหล่านี้ไม่ใช่ตัวเลือกเท่านั้น! วิธีการเกี่ยวกับการแบ่งฟังก์ชั่นเดียวออกเป็นหลาย ๆ ifs? ทดสอบหาวิธีออกจากฟังก์ชั่นเพื่อหลีกเลี่ยงการทดสอบเพิ่มเติมโดยจำลอง "ลัดวงจร" ในการทดสอบบรรทัดเดียว

สิ่งนี้ง่ายต่อการอ่าน (คุณอาจต้องตรวจสอบตรรกะอีกครั้งสำหรับตัวอย่างของคุณ แต่แนวคิดนั้นมีจริง):

private static bool ContextMatchesProp(CurrentSearchContext context, TValToMatch propVal)
{
    if( propVal.PropertyId != context.Definition.Id ) return false;

    if( repo.ParentId.HasValue || repo.ParentId != propVal.ParentId ) return false;

    if( propVal.SecondaryFilter.HasValue && 
        context.SecondaryFilter.HasValue && 
        propVal.SecondaryFilter.Value == context.SecondaryFilter ) return true;

    if( !context.SecondaryFilter.HasValue && 
        !propVal.SecondaryFilter.HasValue) return true;

    return false;   
}

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

2
@BuvinJ: ไม่มีอะไรผิดปกติกับมัน เหมือนกับรหัสต้นฉบับยกเว้นคุณไม่ต้องต่อสู้กับวงเล็บหนึ่งโหลและบรรทัดเดียวที่ทอดยาวผ่านจุดสิ้นสุดของหน้าจอ ฉันสามารถอ่านรหัสนั้นจากบนลงล่างและเข้าใจได้ทันที WTF count = 0.
gnasher729

1
การส่งคืนค่าอื่นนอกเหนือจากที่ส่วนท้ายของฟังก์ชันทำให้โค้ดอ่านน้อยลงไม่สามารถอ่านได้มากขึ้น IMO ฉันชอบจุดทางออกเดียว ข้อโต้แย้งที่ดีทั้งสองวิธีที่ลิงค์นี้ stackoverflow.com/questions/36707/…
แบรดโธมัส

5
@Brad thomas ฉันไม่สามารถเห็นด้วยกับจุดทางออกเดียว มันมักจะนำไปสู่วงเล็บซ้อนกันลึก การกลับมาจะจบเส้นทางดังนั้นสำหรับฉันอ่านง่ายกว่ามาก
Borjab

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

10

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

private static bool ContextMatchesProp(CurrentSearchContext context, TValToMatch propVal)
{
    return MatchesDefinitionId(context, propVal)
        && MatchesParentId(propVal)
        && MatchesSecondaryFilterIfPresent(context, propVal);
}

private static bool MatchesSecondaryFilterIfPresent(CurrentSearchContext context, 
                                                    TValToMatch propVal)
{
    return MatchedSecondaryFilter(context, propVal) 
               || HasNoSecondaryFilter(context, propVal);
}

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

ฉันไม่แน่ใจว่าMatchesSecondaryFilterIfPresent()เป็นชื่อที่ดีที่สุดสำหรับชุดค่าผสมหรือไม่ แต่ไม่มีอะไรดีกว่าที่จะนึกขึ้นมาทันที


เยี่ยมมากพยายามอธิบายสิ่งที่ทำในวิธีการนั้นดีกว่าการปรับโครงสร้างการโทร
klaar

2

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

คุณควรแปลงรหัสนี้เป็นรูปแบบเชิงวัตถุมากขึ้น เมื่อคุณทำเช่นนี้คุณจะพบว่ามีสถานที่ที่เหมาะสมในการใส่รหัสที่ทำการเปรียบเทียบวัตถุของเขตข้อมูล ฯลฯ เป็นไปได้ว่าคุณสามารถขอให้วัตถุเปรียบเทียบตัวเองซึ่งจะลดขนาดใหญ่ลงถ้าคำสั่งเป็น คำของ่าย ๆ ในการเปรียบเทียบ (เช่นif ( a.compareTo (b) ) { }ซึ่งอาจรวมถึงการเปรียบเทียบข้อมูลทั้งหมด)

C # มีชุดอินเตอร์เฟสและยูทิลิตีของระบบจำนวนมากสำหรับทำการเปรียบเทียบกับวัตถุและฟิลด์ นอกเหนือจากที่เห็นได้ชัด.Equalsวิธีการสำหรับการเริ่มดูเป็นIEqualityComparer, และสาธารณูปโภคเช่นIEquatableSystem.Collections.Generic.EqualityComparer.Default


0

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


0

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

โปรดจำไว้ว่า: คำวิจารณ์ที่ดีจะบอกผู้อ่านว่าคุณคิดอย่างไรเมื่อคุณเขียนโค้ด

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


สมควรได้รับ +1 อาหารดีสำหรับความคิดแม้ว่าจะไม่ใช่ความคิดเห็นที่ได้รับความนิยมก็ตาม ขอบคุณ :)
วิลเล็ม

1
@ วิลเล็มไม่มันไม่สมควร +1 สองแนวทางไม่เหมือนกัน ความคิดเห็นเพิ่มเติมนั้นโง่และไม่จำเป็น
BЈовић

2
รหัสที่ดีไม่เคยขึ้นอยู่กับความคิดเห็นที่เข้าใจได้ ในความเป็นจริงความคิดเห็นเป็นความยุ่งเหยิงที่เลวร้ายที่สุดที่รหัสอาจมี รหัสควรพูดเพื่อตัวเอง นอกจากนี้ทั้งสองวิธีที่ OP ต้องการประเมินก็ไม่สามารถ "ใกล้เคียงกันได้" ไม่ว่าจะเพิ่มจำนวนช่องว่างเท่าใด
wonderbell

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

0

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

ตอนนี้ลองมาดูตัวเลือกแรกของคุณและยอมรับว่าไม่มีการเยื้องและการแบ่งบรรทัดของคุณทั้งหมดที่มีประโยชน์และไม่มีโครงสร้างแบบมีเงื่อนไขที่ดีทั้งหมด:

private static bool ContextMatchesProp(CurrentSearchContext context, TValToMatch propVal) {
    return propVal.PropertyId == context.Definition.Id && !repo.ParentId.HasValue
        || repo.ParentId == propVal.ParentId
        && propVal.SecondaryFilter.HasValue == context.SecondaryFilter.HasValue
        && (!propVal.SecondaryFilter.HasValue || propVal.SecondaryFilter.Value == context.SecondaryFilter.Value);
}

0

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

    return (   (   propVal.PropertyId == context.Definition.Id
                && !repo.ParentId.HasValue)
            || (   repo.ParentId == propVal.ParentId
                && (   (   propVal.SecondaryFilter.HasValue
                        && context.SecondaryFilter.HasValue 
                        && propVal.SecondaryFilter.Value == context.SecondaryFilter)
                    || (   !context.SecondaryFilter.HasValue
                        && !propVal.SecondaryFilter.HasValue))));

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

โปรดทราบว่า (cond1 && cond2) || (! cond1 && cond3) สามารถเขียนเป็น

cond1 ? cond2 : cond3

ซึ่งจะลดความยุ่งเหยิง ฉันจะเขียน

if (propVal.PropertyId == context.Definition.Id && !repo.ParentId.HasValue) {
    return true;
} else if (repo.ParentId != propVal.ParentId) {
    return false;
} else if (propVal.SecondaryFilter.HasValue) {
    return (   context.SecondaryFilter.HasValue
            && propVal.SecondaryFilter.Value == context.SecondaryFilter); 
} else {
    return !context.SecondaryFilter.HasValue;
}

-4

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

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

ฉันไม่แน่ใจเกี่ยวกับ c # แต่ในจาวาสคริปต์บางอย่างเช่นนี้จะดีขึ้นมากและอย่างน้อยก็สามารถแทนที่ MatchesDefinitionId และ MatchesParentId ได้

function compareContextProp(obj, property, value){
  if(obj[property])
    return obj[property] == value
  return false
}

1
ไม่ควรมีปัญหาในการใช้สิ่งนี้ใน C #
Snoop

ฉันไม่เห็นว่าการรวมกันของบูล ~ 5 โทรไปcompareContextProp(propVal, "PropertyId", context.Definition.Id)จะง่ายต่อการอ่านกว่าการรวมกันแบบบูล OP ของ ~ 5 propVal.PropertyId == context.Definition.Idเปรียบเทียบของแบบฟอร์ม มันใช้เวลานานและเพิ่มเลเยอร์พิเศษโดยไม่ต้องซ่อนความซับซ้อนใด ๆ จากไซต์การโทร (ถ้ามันเป็นเรื่องสำคัญฉันไม่ได้ลงคะแนน)
Ixrec
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.