ฟังก์ชั่นที่บริสุทธิ์เป็นสิ่งหนึ่งที่:
- จะเสมอให้ผลเหมือนกันให้ขัดแย้งกัน
- ไม่มีผลข้างเคียงที่สังเกตได้ (เช่นการเปลี่ยนแปลงสถานะ)
สมมติว่าเรากำลังเขียนรหัสบางอย่างเพื่อจัดการการเข้าสู่ระบบของผู้ใช้ที่เราต้องการตรวจสอบว่าชื่อผู้ใช้และรหัสผ่านที่ให้มานั้นถูกต้องและป้องกันการเข้าสู่ระบบของผู้ใช้หากมีความพยายามล้มเหลวมากเกินไป ในรูปแบบที่จำเป็นรหัสของเราอาจมีลักษณะเช่นนี้:
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;
}
มันค่อนข้างชัดเจนว่านี่ไม่ใช่ฟังก์ชั่นบริสุทธิ์:
- ฟังก์ชั่นนี้จะไม่เคยให้ผลเหมือนกันสำหรับการกำหนด
username
และpassword
การรวมกันเป็นผลยังขึ้นอยู่กับผู้ใช้บันทึกที่เก็บไว้ในฐานข้อมูล
- ฟังก์ชั่นสามารถเปลี่ยนสถานะของฐานข้อมูลเช่นมีผลข้างเคียง
นอกจากนี้ยังทราบว่าในการทดสอบหน่วยฟังก์ชันนี้เราต้องเยาะเย้ยจากสองสายฐานข้อมูลและFindUser
RecordFailedLoginAttempt
หากเราต้อง 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
ตอนนี้ฟังก์ชั่นเป็นฟังก์ชั่นที่บริสุทธิ์และเป็นผลให้ตรรกะการตรวจสอบผู้ใช้หลักสามารถทดสอบหน่วยโดยไม่จำเป็นต้องจำลองการพึ่งพาภายนอกใด ๆ นี่เป็นเพราะการโต้ตอบกับฐานข้อมูลได้รับการจัดการที่สูงขึ้นถึงสแต็คการโทร