Com a ajuda do AOP, posso remover o código de log da minha lógica de negócios. Mas acho que só pode ser usado para registrar coisas simples (por exemplo, entrada / saída do método de registro e valores de parâmetros).
No entanto, e se eu precisar registrar algo na minha lógica de negócios? por exemplo
public void SomeDomainMethod(string id)
{
//Get user by Id
User user = Users.Get(id);
if (user == null)
{
Log.Warn("user is not existed"); //<----------------- Log A
throw new InvalidOperationException("user is not existed");
}
//Step 1
while(true)
{
//do something
}
Log.Info("Step 1 is completed"); //<----------------- Log B
//Step 2
while(true)
{
//do something
}
Log.Info("Step 2 is completed"); //<----------------- Log C
}
O método de amostra acima pode não ser suficientemente claro, o que quero mostrar aqui é que o método deve ser tratado como a menor unidade do ponto de vista do domínio. Não deve ser dividido em pedaços menores.
É possível mover acima do código de log 3 acima do método? Qual é a melhor prática para essa situação?
c#
logging
separation-of-concerns
Charlie
fonte
fonte
Respostas:
Certo!
Mas, na minha experiência, existem dois tipos gerais de log útil :
Tudo registra: logs criados por meio de APIs de criação de perfil. Bom para identificar problemas de desempenho e relatar exceções. Muito barulhento.
Logs de eventos de negócios : logs chamados na lógica de negócios. Qualquer coisa com que a empresa possa se importar. Ruído mínimo. Apenas eventos "comerciais" notáveis, lógicos. Bom para auditoria e KPI's ...
Então, eu sugeriria duas coisas. Primeiro, faça o que outras ferramentas de monitoramento fazem, como New Relic, e use a API de criação de perfil .NET 1 . Em segundo lugar, registre eventos de negócios lógicos em sua lógica de negócios . Manter um registro de determinados eventos é lógica de negócios.
E, normalmente, eu não sugeriria AOP para nenhum tipo de registro 2 . Na minha experiência, você quer tudo , o que significa que está usando um criador de perfil, ou deseja eventos lógicos / de negócios. E, no último caso, acho mais simples invocar o criador de logs na lógica de negócios.
1. Mas, sério, economize milhares de horas de esforço e use apenas uma ferramenta de criação de perfil existente ...
2. Obviamente, isso pressupõe que você compartilhe minha opinião de que um aspecto não é um ótimo lugar para ocultar regras de negócios!
fonte
Claro, você pode facilmente usar o AOP para isso. Simplesmente refatorar as peças
em métodos separados (como você deveria ter feito para tornar seu código mais limpo). Agora você pode configurar facilmente sua estrutura de AOP para registrar as chamadas de método de sua escolha ( como mostrado aqui ). A exceção pode ser registrada diretamente pelo chamador, sem a necessidade de usar o AOP para tirar isso da lógica de negócios.
Para sua edição:
Por que não deveria? Se, em um "contexto de lógica de negócios", você desejar registrar "algo" que vale a pena registrar, e se esse "algo" puder receber um nome sensato, na maioria dos casos, fará sentido refatorar o código em um método própria. Se você deseja usar o AOP, será necessário estruturar seu código de uma maneira que você provavelmente deveria ter estruturado, independentemente do requisito de log. Você pode interpretar isso como uma desvantagem do AOP, ou pode ser interpretado como um benefício, uma vez que fornece um feedback onde sua estrutura de código pode ser aprimorada.
fonte
A menos que o material de log faça parte dos requisitos de negócios, é melhor, como você diz, mantê-lo completamente fora do seu código.
Isso significa que você realmente não deseja registrar coisas como "etapa 1 concluída". Embora possa ser útil inicialmente para depuração, na produção, apenas gera gigabytes de lixo que você nunca verá.
Se o Step1Complete for algum tipo de evento comercial que requer ação adicional, ele poderá ser exposto através de um bom evento antiquado sem forçar você a injetar um ILogger ou similar em sua classe
fonte
Com a ajuda de algum padrão comum, você pode extrair o código de log da sua lógica de negócios. No entanto, você pode achar que não vale a pena fazê-lo
Por exemplo, pelo uso do listener (artesanato um ou usando o barramento de eventos etc.), seu código será semelhante a
Ao implementar o log no ouvinte, a lógica de log não está mais na sua lógica de negócios.
No entanto, você pode achar que isso nem sempre é realista, pois nem sempre você pode definir eventos significativos de sua lógica.
Outra abordagem é através de mecanismos como o Dtrace no Solaris, que permitem que você injete em processos em execução (acredito que há uma maneira de fazer algo semelhante em C #?), Para que o registro e as reuniões estatísticas possam ser definidos em tempo de execução. Ainda existem outras desvantagens.
fonte
Outra abordagem é separar o registro comercial e o registro técnico. Em seguida, podemos chamar o log de negócios de "Auditoria" e aplicar um conjunto específico de regras de negócios, como termo de armazenamento e regras de processamento, como Monitoramento de Atividade de Negócios.
Por outro lado, o log técnico, ou simplesmente "log", é um meio de último recurso para deixar um rastro de problema técnico. Deve ser assíncrono, rápido, tolerante à falha na persistência da mensagem de log. Além disso, as mensagens de log devem passar pelo menor número possível de proxies para estar perto da origem do problema.
A lógica do The Logging é bastante variável e está fortemente associada à implementação, então você realmente precisa separá-lo do código?
A lógica da auditoria deve ser considerada uma lógica de domínio e tratada adequadamente.
Por exemplo, na arquitetura hexagonal, pode haver uma porta de auditoria juntamente com as portas Clients, Storage e MQ (e, possivelmente, Metrics and Control). Seria uma porta secundária, ou seja, a atividade nessa porta é acionada pelo núcleo de negócios, e não por sistemas externos.
fonte
Maneiras de evitar o log diretamente em uma classe ou método:
Lance uma exceção e faça seu logon em um bloco de captura mais adiante na árvore de chamadas. Se você precisar capturar um nível de log, poderá lançar uma exceção personalizada.
Faça chamadas para métodos que já estão instrumentados para log.
fonte
É realmente necessário separar seu registro da lógica de negócios? O registro realizado está em correspondência com a lógica de negócios escrita e, portanto, faz sentido estar na mesma classe / função. Mais importante, ajuda a facilitar a legibilidade do código.
No entanto, caso você realmente queira segregar o log da sua lógica de negócios, considere lançar exceções personalizadas e entregá-las para log.
fonte
Não, não em c #
OP, a resposta para sua pergunta específica é não, não em c #. Pode haver outras linguagens de AOP mais nativas por aí, mas todas as abordagens de AOP em c # que eu já vi só podem aplicar comportamentos de aspecto no contexto de um ponto de junção , o que significa que deve haver fluxo de controle entre um bloco de código e outro. Comportamentos esperados não serão executados no meio de um método, exceto, é claro, chamando outro método.
Você pode "selecionar" certos bits de log
Dito isto, você pode extrair certas preocupações envolvidas no log, apenas não na gravação do log. Por exemplo, um ponto de corte que é executado na entrada de um método pode configurar um contexto de log e gerar todos os parâmetros de entrada, e na saída pode capturar exceções ou comprometer um log para armazenamento permanente, esse tipo de coisa.
A gravação de logs não é um aspecto, de qualquer maneira
Eu acrescentaria que a gravação de logs não é realmente uma preocupação transversal, de qualquer maneira. Pelo menos, não o log de depuração. Minha evidência disso é que você não pode escrever um requisito transversal que explique completamente o que esse aspecto faria - ele é específico para todos os casos, porque o objetivo de escrever o log é refletir o que está acontecendo com o lógica, e a lógica em cada método deve ser razoavelmente única (consulte DRY ).
Em outras palavras, há uma dependência lógica inextricável entre a gravação de log e as coisas sobre as quais estamos escrevendo. Você não pode generalizar.
Mas a auditoria é
Se você tiver algum tipo de requisito de log funcional (por exemplo, log de auditoria em suporte a um requisito de não-repúdio ), alguns argumentariam (e eu concordo) que se você precisar executar essas gravações de log no meio de um método, você não estruturou seu código de maneira consistente com o pensamento orientado a aspectos. Se isso ocorrer, você deve extrair o código em métodos separados até obter o nível de granularidade necessário.
fonte