Con la ayuda de AOP, puedo eliminar el código de registro de mi lógica empresarial. Pero creo que solo se puede usar para registrar cosas simples (es decir, entrada / salida del método de registro y valores de parámetros).
Sin embargo, ¿qué sucede si necesito registrar algo en mi lógica comercial? p.ej
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
}
El método de muestra anterior puede no ser lo suficientemente claro, lo que quiero mostrar aquí es que el método debe tratarse como la unidad más pequeña desde el punto de vista del dominio. No debe dividirse en piezas más pequeñas.
¿Es posible mover por encima del código de registro 3 fuera del método? ¿Cuál es la mejor práctica para tal situación?
c#
logging
separation-of-concerns
Charlie
fuente
fuente
Respuestas:
¡Seguro!
Pero en mi experiencia, hay dos tipos generales de registro útil :
Todo registra: registros creados a través de API de creación de perfiles. Bueno para identificar problemas de rendimiento y reportar excepciones. Muy ruidoso.
Registros de eventos empresariales : registros invocados en la lógica empresarial. Cualquier cosa que le interese al negocio. Ruido mínimo. Solo eventos notables, lógicos, "comerciales". Bueno para auditoría y KPI's ...
Por lo tanto, sugeriría dos cosas. En primer lugar, haga lo que hacen otras herramientas de monitoreo, como New Relic, y use la API de creación de perfiles .NET 1 . En segundo lugar, registre eventos empresariales lógicos en su lógica empresarial . Mantener un registro de ciertos eventos es la lógica empresarial.
Y, normalmente no sugeriría AOP para cualquier tipo de registro 2 . En mi experiencia, o quieres todo , lo que significa que estás usando un generador de perfiles, o quieres eventos lógicos / de negocios. Y en el último caso, creo que es más sencillo invocar al registrador en la lógica empresarial.
1. Pero en serio, ahorre miles de horas de esfuerzo y simplemente use una herramienta de perfil existente ...
2. ¡Por supuesto, esto supone que comparte mi opinión de que un aspecto no es un gran lugar para ocultar las reglas de negocios!
fuente
Claro, puedes usar AOP fácilmente para esto. Simplemente refactorice las partes
en métodos separados (como debería haber hecho para hacer que su código sea más limpio). Ahora puede configurar fácilmente su marco AOP para registrar las llamadas de método que elija ( como se muestra aquí ). La persona que llama puede registrar la excepción directamente, no es necesario usar AOP para sacar esto de la lógica empresarial.
A tu edición:
¿Por qué no debería? Si, en un "contexto de lógica de negocios", desea registrar "algo" que valga la pena registrar, y si a este "algo" se le puede dar un nombre razonable, en la mayoría de los casos tendrá sentido refactorizar el código en un método en su propio. Si desea usar AOP, requerirá que estructure su código de una manera que probablemente debería haberlo estructurado independientemente del requisito de registro. Puede interpretar esto como una desventaja de AOP, o puede interpretar esto como un beneficio, ya que le brinda una retroalimentación donde se puede mejorar la estructura de su código.
fuente
A menos que el registro sea parte de los requisitos comerciales, es mejor, como usted dice, mantenerlo completamente fuera de su código.
Eso significa que realmente no desea registrar cosas como "paso 1 completo". Aunque inicialmente puede ser útil para la depuración, en la producción solo va a generar gigabytes de basura que nunca verá.
Si Step1Complete es un tipo de evento de negocios que requiere más acción, entonces puede exponerse a través de un buen evento a la antigua sin obligarlo a inyectar un ILogger o similar en su clase
fuente
Con la ayuda de algún patrón común, puede extraer el código de registro de su lógica empresarial. Sin embargo, es posible que no valga la pena hacerlo.
Por ejemplo, mediante el uso de listener (artesanía uno o usando bus de eventos, etc.), su código se verá así
Al implementar el registro en el oyente, la lógica de registro ya no está en su lógica empresarial.
Sin embargo, puede encontrar que esto no siempre es realista, ya que es posible que no siempre pueda definir un evento significativo de su lógica.
Otro enfoque es a través de mecanismos como Dtrace en Solaris que le permiten inyectar en procesos en ejecución (creo que hay una manera de hacer algo similar en C #?) Para que el registro y las reuniones estadísticas se puedan definir en tiempo de ejecución. Todavía hay otros inconvenientes.
fuente
Otro enfoque es separar el registro de negocios y el registro técnico. Luego, podemos llamar al "registro de negocios" "Auditoría" y aplicar un conjunto específico de reglas comerciales, como el término de almacenamiento y las reglas de procesamiento, como el Monitoreo de la actividad comercial.
Por otro lado, el registro técnico, o simplemente "Registro", es un medio de último recurso para dejar un rastro de problema técnico. Debe ser asíncrono, rápido, tolerante a la falta de persistencia del mensaje de registro. Además, los mensajes de registro deben pasar por el menor número posible de servidores proxy para estar cerca de la fuente del problema.
La lógica de The Logging es bastante variable y está estrechamente relacionada con la implementación, entonces, ¿realmente necesita separarlo del código?
La lógica de The Audit debe considerarse una lógica de dominio y manejarse en consecuencia.
Por ejemplo, en la arquitectura hexagonal puede haber un puerto de auditoría junto con puertos de clientes, almacenamiento y MQ (y, posiblemente, métricas y control). Sería un puerto secundario, es decir, la actividad en este puerto es activada por el núcleo del negocio, en lugar de por sistemas externos.
fuente
Formas de evitar iniciar sesión directamente en una clase o método:
Lanza una excepción y haz tu registro en un bloque catch más arriba en el árbol de llamadas. Si necesita capturar un nivel de registro, puede lanzar una excepción personalizada.
Realice llamadas a métodos que ya están instrumentados para el registro.
fuente
¿Es realmente necesario separar su registro de su lógica empresarial? El registro realizado se corresponde con la lógica comercial escrita y, por lo tanto, tiene sentido estar en la misma clase / función. Más importante aún, ayuda a facilitar la lectura del código.
Sin embargo, en caso de que realmente quiera segregar el registro de su lógica comercial, debería considerar lanzar excepciones personalizadas y entregar esas excepciones para el registro.
fuente
No, no en c #
OP, la respuesta a su pregunta específica es no, no en c #. Puede haber otros lenguajes de AOP más nativos, pero todos los enfoques de AOP en C # que he visto solo pueden aplicar comportamientos esperados en el contexto de un punto de unión , lo que significa que debe haber un flujo de control entre un bloque de código y otro. Los comportamientos esperados no se ejecutarán en medio de un método, excepto, por supuesto, llamando a otro método.
Podrías "apsect-ize" ciertos bits de registro
Dicho esto, puede extraer ciertas preocupaciones relacionadas con el registro, pero no con la escritura del registro. Por ejemplo, un punto de corte que se ejecuta al ingresar a un método podría establecer un contexto de registro y generar todos los parámetros de entrada, y al salir podría detectar excepciones o confirmar un registro para el almacenamiento permanente, ese tipo de cosas.
La escritura de registros no es un aspecto, de todos modos
De todos modos, agregaría que la escritura de registros no es realmente una preocupación transversal. Al menos no depurar el registro. Mi evidencia de esto es que no podría escribir un requisito transversal que explique completamente lo que haría este aspecto; es específico para cada caso, porque el propósito de escribir el registro es reflejar lo que está sucediendo con el lógica, y la lógica en cada método debe ser razonablemente única (ver SECO ).
En otras palabras, existe una dependencia lógica inextricable entre la escritura de registros y el material sobre el que se escribe. No puedes generalizarlo.
Pero la auditoría es
Si tiene algún tipo de requisito de registro funcional (por ejemplo, el registro de auditoría en apoyo de un requisito de no repudio ), entonces algunos argumentarán (y yo estaría de acuerdo) que si necesita ejecutar estas escrituras de registro en medio de un método, no ha estructurado su código de manera consistente con el pensamiento orientado a aspectos. Si esto ocurre, debe extraer el código en métodos separados hasta que obtenga el nivel de granularidad que necesita.
fuente