Правило о том, что нельзя брать зависимость просто для ее передачи, является правильным, но с точки зрения вашего публичного API это тоже не то, что вы делаете.Поскольку AccessGateKeeper
является внутренним, он не является частью общедоступного API - это подробности реализации .С тем же успехом это могла быть частная вспомогательная функция класса UserAccessManagement
.
Таким образом, с общедоступной точки зрения класс UserAccessManagement
не принимает зависимость только дляпередать это ».Вместо этого вы могли бы сказать, что класс UserAccessManagement
требует выполнения зависимостей IUserRepository
, IHashProvider
и ITokenEncryptor
для его работы.
Однако с точки зрения удобства обслуживания текущая реализация тесно связана UserAccessManagement
и AccessGateKeeper
, что может быть или не быть проблемой.Однако, если это является проблемой, вы можете рассмотреть возможность включения желаемого поведения в интерфейс.Механическое извлечение может выглядеть следующим образом:
public interface IAccess
{
void Grant(object ticket, string resource)
}
С помощью этого интерфейса вы можете изменить реализацию UserAccessManagement
на:
public class UserAccessManagement
{
private readonly IUserRepository _repo;
private readonly IAccess _access;
public UserAccessManagement(IUserRepository repo, IAccess access)
{
_repo = repo;
_access = access;
}
public void GrantAccess(string username, string resource)
{
User user = repo.FindUser(username);
_access.Grant(user.SpnTicket, resource);
}
}
Реализация IAccess
может выглядеть следующим образом:
public class Access : IAccess
{
private readonly IHashProvider _hash;
private readonly ITokenEncryptor _tokenEnc;
public Access(IHashProvider _hash, ITokenEncryptor _tokenEnc)
{
_hash = hash;
_tokenEnc = tokenEnc;
}
public void Grant(object ticket, string resource)
{
new AccessGateKeeper(ticket, _hash, _tokenEnc)
.GrantAccess(resource);
}
}