สไตล์การทำงานมีประโยชน์อย่างไรกับการล้อเลียนอ้างอิง


10

จากการสัมภาษณ์กับ Kent Beck ในนิตยสาร Java Magazine ฉบับล่าสุด:

Binstock: มาพูดคุยเรื่องไมโครไซต์ สำหรับฉันดูเหมือนว่าการทดสอบครั้งแรกเกี่ยวกับบริการไมโครซอฟท์จะซับซ้อนในแง่ที่ว่าบริการบางอย่างเพื่อให้สามารถทำงานได้จะต้องมีบริการอื่น ๆ ทั้งหมด คุณเห็นด้วยหรือไม่?

เบ็ค: ดูเหมือนว่าชุดการค้าขายเดียวกันกับการมีชั้นเรียนใหญ่ ๆ

Binstock: ใช่ฉันเดาว่าที่นี่คุณต้องใช้ mocks จำนวนมากเพื่อให้สามารถตั้งค่าระบบที่คุณสามารถทดสอบบริการที่กำหนดได้

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

เขาหมายถึงอะไร สไตล์การทำงานจะช่วยปลดปล่อยคุณจากการล้อเลียนการพึ่งพาจากภายนอกได้อย่างไร?



1
หากพวกเขากำลังพูดถึง Java โดยเฉพาะฉันสงสัยว่าการอภิปรายส่วนใหญ่นั้นเป็นสิ่งที่สงสัย Java ไม่ได้รับการสนับสนุนชนิดใดที่จำเป็นต้องใช้ในการเขียนโปรแกรมเพื่อการทำงานตามที่อธิบายไว้ โอ้แน่นอนคุณสามารถใช้คลาสยูทิลิตี้หรือ Java 8 Lambdas เพื่อจำลองมัน แต่ ... blecch
Robert Harvey

1
ที่เกี่ยวข้อง: softwareengineering.stackexchange.com/q/5757
Robert Harvey

คำตอบ:


8

ฟังก์ชั่นที่บริสุทธิ์เป็นสิ่งหนึ่งที่:

  1. จะเสมอให้ผลเหมือนกันให้ขัดแย้งกัน
  2. ไม่มีผลข้างเคียงที่สังเกตได้ (เช่นการเปลี่ยนแปลงสถานะ)

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

bool UserLogin(string username, string password)
{
    var user = _database.FindUser(username);
    if (user == null)
    {
        return false;
    }
    if (user.FailedAttempts > 3)
    {
        return false;
    }
    // Password hashing omitted for brevity
    if (user.Password != password)
    {
        _database.RecordFailedLoginAttempt(username);
    }
    return true;
}

มันค่อนข้างชัดเจนว่านี่ไม่ใช่ฟังก์ชั่นบริสุทธิ์:

  1. ฟังก์ชั่นนี้จะไม่เคยให้ผลเหมือนกันสำหรับการกำหนดusernameและpasswordการรวมกันเป็นผลยังขึ้นอยู่กับผู้ใช้บันทึกที่เก็บไว้ในฐานข้อมูล
  2. ฟังก์ชั่นสามารถเปลี่ยนสถานะของฐานข้อมูลเช่นมีผลข้างเคียง

นอกจากนี้ยังทราบว่าในการทดสอบหน่วยฟังก์ชันนี้เราต้องเยาะเย้ยจากสองสายฐานข้อมูลและFindUserRecordFailedLoginAttempt

หากเราต้อง refactor รหัสนี้ในรูปแบบการทำงานมากขึ้นเราอาจท้ายด้วยบางสิ่งเช่นนี้

bool UserLogin(string username, string password)
{
    var user = _database.FindUser(username);
    var result = UserLoginPure(user, password);
    if (result == Result.FailedAttempt)
    {
        _database.RecordFailedLoginAttempt(username);
    }
    return result == Result.Success;
}

Result UserLoginPure(User user, string pasword)
{
    if (user == null)
    {
        return Result.UserNotFound;
    }
    if (user.FailedAttempts > 3)
    {
        return Result.LoginAttemptsExceeded;
    }
    if (user.Password != password)
    {
        return Result.FailedAttempt;        
    }
    return Result.Success;
}

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


การตีความของคุณคือ: imperative-style = microservices statefullและ functional-style = microservies ไร้รัฐหรือไม่?
k3b

@ k3b เรียงลำดับยกเว้นบิตเกี่ยวกับบริการไมโคร สไตล์ Imperative อย่างง่ายเกี่ยวข้องกับการจัดการของรัฐในขณะที่รูปแบบการทำงานใช้ฟังก์ชั่นที่บริสุทธิ์โดยไม่ต้องจัดการของรัฐ
Justin

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

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

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