순수 기능은 하나 즉 :
- 같은 주장을한다면 항상 같은 결과를 낼 것입니다
- 관찰 가능한 부작용이 없음 (예 : 상태 변경)
제공된 사용자 이름과 비밀번호가 올바른지 확인하고 실패한 시도가 너무 많은 경우 사용자가 로그인하지 못하게하는 사용자 로그인을 처리하기위한 코드를 작성한다고 가정하십시오. 명령형 스타일에서 코드는 다음과 같습니다.
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
.
이 코드를보다 기능적인 스타일로 리팩토링하면 다음과 같은 결과가 나타날 수 있습니다.
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
함수는 이제 순수 함수이므로 결과적으로 외부 사용자를 조롱 할 필요없이 핵심 사용자 인증 로직을 단위 테스트 할 수 있습니다. 이는 데이터베이스와의 상호 작용이 호출 스택에서 더 높게 처리되기 때문입니다.