Bir saf fonksiyonu bir olmasıdır:
- Will hep aynı argümanlar verilen aynı sonucu verir
- Gözlenebilir herhangi bir yan etkisi yoktur (örn. Durum değişiklikleri)
Kullanıcı girişini işlemek için bazı kodlar yazdığımızı varsayalım, burada verilen kullanıcı adı ve parolanın doğru olup olmadığını kontrol etmek ve çok fazla başarısız deneme varsa kullanıcının oturum açmasını engellemek istiyoruz. Zorunlu bir tarzda kodumuz şöyle görünebilir:
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;
}
Bunun saf bir işlev olmadığı oldukça açıktır:
- Bu işlev belirli bir
username
ve password
kombinasyon için her zaman aynı sonucu vermeyecektir, çünkü sonuç aynı zamanda veritabanında saklanan kullanıcı kaydına da bağlıdır.
- Fonksiyon veritabanının durumunu değiştirebilir, yani yan etkileri vardır.
Ayrıca birim testi için bu fonksiyon iki veritabanı aramaları dışarı alay etmek gerek, unutmayın FindUser
ve RecordFailedLoginAttempt
.
Bu kodu daha işlevsel bir stile dönüştürürsek, bunun gibi bir şeyle sonuçlanabiliriz:
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
İşlev hala saf olmasa da, işlevin UserLoginPure
artık saf bir işlev olduğunu ve bunun sonucunda çekirdek kullanıcı kimlik doğrulama mantığının harici bağımlılıklarla alay etmeden birim test edilebileceğini unutmayın. Bunun nedeni, veritabanı ile etkileşimin çağrı yığını üzerinde daha üst düzeyde ele alınmasıdır.