Dependências demais podem indicar que a própria classe está fazendo muito. Para determinar se não está fazendo muito:
Observando as dependências reais, não vejo nada que indique coisas ruins acontecendo:
IDbContextFactory - criando o contexto para o banco de dados.
OK, provavelmente estamos dentro de uma camada de negócios em que as classes interagem com a camada de acesso a dados. Parece bem.
IMapper - Mapeamento de entidades para modelos de domínio.
É difícil dizer algo sem a imagem geral. Pode ser que a arquitetura esteja incorreta e o mapeamento seja feito diretamente pela camada de acesso a dados, ou pode ser que a arquitetura esteja perfeitamente correta. Em todos os casos, faz sentido ter essa dependência aqui.
Outra opção seria dividir a classe em duas: uma que lida com o mapeamento e a outra com a lógica de negócios real. Isso criaria uma camada de fato que separará ainda mais o BL do DAL. Se os mapeamentos são complexos, pode ser uma boa ideia. Na maioria dos casos, porém, isso apenas adicionaria complexidade inútil.
IClock - Abstracts DateTime.Now para ajudar com testes de unidade.
Provavelmente não é muito útil ter uma interface (e classe) separada apenas para obter a hora atual. Eu simplesmente passaria DateTime.Now
para os métodos que exigem a hora atual.
Uma classe separada pode fazer sentido se houver outras informações, como fusos horários ou períodos, etc.
IPerformanceFactory - mede o tempo de execução de métodos específicos.
Veja o próximo ponto.
ILog - Log4net para registro.
Essa funcionalidade transcendente deve pertencer à estrutura e as bibliotecas reais devem ser intercambiáveis e configuráveis em tempo de execução (por exemplo, através do app.config no .NET).
Infelizmente, esse não é (ainda) o caso, que permite escolher uma biblioteca e ficar com ela, ou criar uma camada de abstração para poder trocar as bibliotecas mais tarde, se necessário. Se sua intenção é especificamente ser independente da escolha da biblioteca, vá em frente. Se você tiver certeza de que continuará usando a biblioteca por anos, não adicione uma abstração.
Se a biblioteca é muito complexa para usar, um padrão de fachada faz sentido.
ICollectionWrapperFactory - Cria coleções (que estendem IEnumerable).
Eu diria que isso cria estruturas de dados muito específicas que são usadas pela lógica do domínio. Parece uma classe de utilidade. Em vez disso, use uma classe por estrutura de dados com construtores relevantes. Se a lógica de inicialização for um pouco complicada para caber em um construtor, use métodos estáticos de fábrica. Se a lógica for ainda mais complexa, use padrão de fábrica ou de construtor.
IQueryFilterFactory - gera consultas com base na entrada que consultará o banco de dados.
Por que isso não está na camada de acesso a dados? Por que existe um Filter
no nome?
IIdentityHelper - Recupera o usuário conectado.
Não sei por que existe um Helper
sufixo. Em todos os casos, outros sufixos também não serão particularmente explícitos ( IIdentityManager
?)
Enfim, faz todo o sentido ter essa dependência aqui.
IFaultFactory - Crie diferentes FaultExceptions (eu uso o WCF).
É a lógica tão complexa que requer o uso de um padrão de fábrica? Por que a injeção de dependência é usada para isso? Você trocaria a criação de exceções entre código de produção e testes? Por quê?
Eu tentaria refatorar isso para simples throw new FaultException(...)
. Se alguma informação global deve ser adicionada a todas as exceções antes de propagá-las para o cliente, o WCF provavelmente possui um mecanismo no qual você captura uma exceção não tratada e pode alterá-la e repassá-la para o cliente.
Medir a qualidade por números geralmente é tão ruim quanto ser pago por linhas de código que você escreve por mês. Você pode ter um alto número de dependências em uma classe bem projetada, pois pode ter uma classe de baixa qualidade usando poucas dependências.
Muitas dependências tornam a lógica mais difícil de seguir. Se a lógica for difícil de seguir, a classe provavelmente está fazendo muito e deve ser dividida.