문제

I have a model Administrator that has its properties, but it also consists of numerous static methods that do not really tied any way to the current object itself like for example GetByCredentials(string username, string password);. Is it somehow possible to divide static methods someplace else and lave object as pure as possible?

Example

public class Administrator : Entity
{
    // OBJECT START
    public int Id { get; set; }
    public DateTime CreatedDateTime { get; set; }
    public DateTime UpdatedDateTime { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string PasswordSalt { get; set; }

    public void SetNewPassword(string password)
    {
        var cryptoService = new PBKDF2();
        this.Password = cryptoService.Compute(password);
        this.PasswordSalt = cryptoService.Salt;
    }

    public override void OnBeforeInsert()
    {
        this.CreatedDateTime = DateTime.Now;
        this.UpdatedDateTime = DateTime.Now;

        this.SetNewPassword(this.Password);
    }

    public override void OnBeforeUpdate()
    {
        this.UpdatedDateTime = DateTime.Now;
    }
    // OBJECT END

    // Now I have multiple static methods that do not really
    // have anything to do with current object
    public static Administrator GetByCredentials(string username, string password)
    {
        var db = new MainDataContext();
        var admin = db.Administrators.SingleOrDefault(x => x.Username == username);
        if (admin == null) return null;

        ICryptoService cryptoService = new PBKDF2();
        var hash = cryptoService.Compute(password, admin.PasswordSalt);

        if (hash == admin.Password) return admin;
        return null;
    }

    public static bool IsCurrentIpBanned
    {
        get
        {
            const int minutesBlocked = 5;
            const int maxLoginCount = 5;

            var db = new MainDataContext();
            var loginCount = db.AdministratorAuthorizationLogs.AsEnumerable().Count(x => x.Ip == HttpContext.Current.Request.UserHostAddress && x.CreatedDateTime.AddMinutes(minutesBlocked) > DateTime.Now && x.IsSuccess == false);

            return loginCount > maxLoginCount;
        }
    }

    public static void LogSuccess(Administrator admin)
    {
        Administrator.Log(admin, true);
    }

    public static void LogFailure(Administrator admin)
    {
        Administrator.Log(admin, false);
    }

    private static void Log(Administrator admin, bool success)
    {
        var db = new MainDataContext();
        db.AdministratorAuthorizationLogs.Add(new AdministratorAuthorizationLog
        {
            Username = admin.Username,
            Password = admin.Password,
            Ip = HttpContext.Current.Request.UserHostAddress,
            IsSuccess = success
        });

        db.SaveChanges();
    } 
}
도움이 되었습니까?

해결책

There are several options here, but the main thing is that C# classes are the tool for separating concerns.

The most obvious is to capture those things in their own abstraction(s). For example, the GetByCredentials might be better as a (non-static) member of a different class Authority or similar. That class only needs to be able to create an Administrator type.

You can also use extension methods. A possible candidate for that is Log, which takes an Administrator as an argument and uses only public facilities on it. Extension methods are defined in a separate class, but allow you to use them "as if" they were members of the extended class, e.g.:

public static class AdministratorExtensions
{
    public static void log( this Administrator admin, bool success ) { ... }
}

var admin = new Administrator();
admin.Log( true );

The key thing is to identify real abstractions and build your system up from them by combining them in sensible ways. Separating out concerns is part of that process.

다른 팁

This is a hint that your class "knows too much". The Administrator class should only know what concerns an administrator. He shouldn't be able to query the database and retrieve entities.

You should look into the repository pattern. Try to decompose your application into multiple layers. For example, you could have a DataRepository class whose main concern is to query and update the database entities.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top