กำลังตรวจสอบว่าเมธอดส่งคืน false หรือไม่: กำหนดผลลัพธ์ให้กับตัวแปรชั่วคราวหรือทำให้การเรียกใช้เมธอดตรงตามเงื่อนไขหรือไม่


9

เป็นวิธีปฏิบัติที่ดีในการเรียกใช้เมธอดที่ส่งคืนค่าจริงหรือเท็จในคำสั่ง if หรือไม่?

บางสิ่งเช่นนี้

private void VerifyAccount()
{
    if (!ValidateCredentials(txtUser.Text, txtPassword.Text))
    {
        MessageBox.Show("Invalid user name or password");
    }
}

private bool ValidateCredentials(string userName, string password)
{
    string existingPassword = GetUserPassword(userName);
    if (existingPassword == null)
        return false;

    var hasher = new Hasher { SaltSize = 16 };
    bool passwordsMatch = hasher.CompareStringToHash(password, existingPassword);

    return passwordsMatch;
}

หรือจะเป็นการดีกว่าถ้าเก็บไว้ในตัวแปรแล้วเปรียบเทียบกับมันถ้าใช้ค่าอื่นเช่นนี้

bool validate = ValidateCredentials(txtUser.Text, txtPassword.Text);
if(validate == false){
    //Do something
}

ฉันไม่เพียง แต่หมายถึง. NET ฉันหมายถึงคำถามในทุกภาษาการเขียนโปรแกรมมันเกิดขึ้นดังนั้นฉันจึงใช้. NET เป็นตัวอย่าง


3
หากคุณใช้ตัวแปรชั่วคราวเขียนมากกว่าif (!validate) if (validate == false)
ฟิลิป

12
ฉันจะตั้งชื่อฟังก์ชั่นบางอย่างเช่น "CredentialsAreValid ()" เพื่อให้คุณรู้ว่ามันควรจะส่งคืนบูล แต่อย่างอื่นก็ใช่แนวปฏิบัติที่ดี
Zachary K

3
IsValidCredentialsแม้ว่าไวยากรณ์ผิดปกติเป็นรูปแบบทั่วไปสำหรับการระบุค่าส่งคืนบูลีน
zzzzBov

@Philip ความแตกต่างระหว่าง if (! ตรวจสอบ) และสิ่งนี้ถ้า (ตรวจสอบ)
KyelJmD

!เป็นโอเปอเรเตอร์ "NOT" มันจะลบล้างนิพจน์บูลีนใด ๆ ดังนั้นเป็นสิ่งที่ตรงกันข้ามของif (!validate) if (validate)คำสั่ง if จะถูกป้อนหากvalidateไม่เป็นจริง
ฟิลิป

คำตอบ:


26

เช่นเดียวกับสิ่งเหล่านี้มันขึ้นอยู่กับ

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

รหัสจะไม่สามารถวัดได้อย่างมีประสิทธิภาพน้อยลง


1
ประเภทนั้นสามารถอ่านได้? เช่นเดียวกับที่ฉันทำข้างต้น
KyelJmD

@KelelJmD: ขึ้นอยู่กับวัฒนธรรมที่คุณกำลังเขียนโปรแกรมในสถานที่ที่ฉันตั้งโปรแกรมไว้!ValidateCredentialsมันอ่านได้ง่ายขึ้นเพราะมันบอกอย่างชัดเจนว่ามันกำลังทำอะไรอยู่ในรหัส มันชัดเจนมาก หากฟังก์ชั่นที่คุณโทรไม่มีชื่อ "เอกสารด้วยตนเอง" ก็อาจจะดีกว่าถ้าใช้ตัวแปร ฉันขอแนะนำให้ละเว้นตัวแปรและอยู่กับรหัสการจัดทำเอกสารด้วยตนเองที่คุณมี
Joel Etherton

ValidateCredentials ไม่สามารถอ่านได้ตั้งแต่แรก - ชื่อนี้บอกคุณได้อย่างไรว่าผลลัพธ์มีความหมายอย่างไร ดีกว่ามากทั้ง CredentialsAreValid หรือ CredentialsAreInvalid
gnasher729

9

เหตุใดจึงต้องใช้ตัวแปรเพิ่มเติม ฉันชอบใช้วิธีแรกมันอ่านง่ายกว่าและง่ายกว่า


4

เป็นวิธีปฏิบัติที่ดีในการเรียกใช้เมธอดที่ส่งคืนค่าจริงหรือเท็จในคำสั่ง if หรือไม่?

ใช่ถ้าเงื่อนไขไม่ง่ายพอที่จะอินไลน์และสามารถอ่านได้

หรือจะเป็นการดีกว่าถ้าเก็บไว้ในตัวแปรแล้วเปรียบเทียบกับมันถ้าใช้ค่าอื่นเช่นนี้

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


2

มาดูกัน...

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

แต่เนื่องจากคุณแห้งถ้าคุณโทรมาValidateCredentialsและพบว่าตัวเองพิมพ์ValidateCredentials(txtUser.Text, txtPassword.Text)คุณรู้ว่าคุณควรสร้างตัวแปรเพิ่มเติม


2

ใช่มันเป็นเรื่องปกติที่จะใช้วิธีการเช่นถ้าเงื่อนไข มันจะมีประโยชน์แม้ว่าถ้าชื่อเมธอดบ่งชี้ว่าเมธอดส่งคืนบูล; เช่น CanValidateCredentials ในภาษา C-style วิธีนี้มักใช้รูปแบบของ Is และ Can นำหน้าและใน Ruby ด้วย '?' วิภัตติ


1
จุดดีเกี่ยวกับชื่อเมธอด แต่ฉันจะไม่เริ่มชื่อเมธอดด้วย "if" จากนั้นรหัสจะอ่านว่า "ถ้าหาก" "สามารถ" เป็น if (cat.canOpenCanOfCatFood())ok:
วินไคลน์

ขอบคุณ @Kevin ฉันหมายถึง 'ไม่ใช่' ถ้า ' ฉันแก้ไขคำตอบ
Christian Horsdal

1

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

ตัวอย่างที่ 1:

if(foo() && bar() && baz())
{
    quz();
}

ตัวอย่างที่ 2:

bool isFoo = foo();
bool isBar = bar();
bool isBaz = baz();
if(isFoo && isBar && isBaz)
{
    quz();
}

รหัสสองส่วนนี้ดูเหมือนจะทำสิ่งเดียวกัน แต่หากภาษาของคุณรองรับการประเมินการลัดวงจรชิ้นส่วนทั้งสองนั้นแตกต่างกัน การประเมินการลัดวงจรหมายความว่ารหัสจะประเมินค่าต่ำสุดที่จำเป็นต้องผ่านหรือล้มเหลวในเงื่อนไข หากตัวอย่าง # 1 ถ้า foo () ส่งคืนค่าเท็จ bar () และ baz () จะไม่ได้รับการประเมิน สิ่งนี้มีประโยชน์หาก baz () เป็นการเรียกใช้ฟังก์ชันที่ใช้เวลานานเนื่องจากคุณสามารถข้ามได้หาก foo () ส่งคืน false หรือ foo () ส่งคืน true และ bar () ส่งคืน false

นี่ไม่ใช่กรณีในตัวอย่าง # 2 foo (), bar () และ baz () จะได้รับการประเมินเสมอ หากคุณคาดหวังว่าแถบ () และ baz () จะแสดงผลข้างเคียงคุณจะมีปัญหากับตัวอย่าง # 1 ตัวอย่าง # 1 ด้านบนเทียบเท่ากับสิ่งนี้:

ตัวอย่างที่ 3:

if(foo())
{
    if(bar())
    {
        if(baz())
        {
            quz();
        }
    }
}

ระวังความแตกต่างเหล่านี้ในรหัสของคุณเมื่อเลือกระหว่างตัวอย่าง # 1 และ # 2


1

การขยายเล็กน้อยในปัญหาการอ่าน ...

ฉันสามารถคิดถึงเหตุผลที่ดีสองข้อในการเก็บผลลัพธ์ไว้ในตัวแปร:

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

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

ตัวอย่างเช่นสิ่งนี้:

bool foo_is_ok = is_ok(foo);
if (foo_is_ok) ...

ไม่ได้ช่วยให้อ่านง่าย แต่สิ่งนี้:

bool done_processing = feof(file1) && feof(file2);
if (done_processing) ...

อาจเป็นเพราะไม่ชัดเจนทันทีซึ่งfeof(file1) && feof(file2)หมายความว่าเรากำลังดำเนินการอยู่

passwordsMatchตัวแปรในคำถามที่อาจจะเป็นตัวอย่างที่ดีกว่าฉัน

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


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

@cmaster: ปัญหาหนึ่งของความคิดเห็นคือพวกเขาสามารถซิงค์กับโค้ดได้ง่ายมาก ตัวแปรที่มีชื่อdone_processingเป็นวิธีที่คงทนกว่าในการแสดงเจตนา
Keith Thompson

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