¿Es posible mantener el código de registro completamente fuera de la lógica de negocios?

7

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 de negocios? por ejemplo

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 se debe dividir en partes más pequeñas.

¿Es posible mover por encima del código de inicio de sesión 3 fuera del método? ¿Cuál es la mejor práctica para tal situación?

    
pregunta Charlie 16.03.2017 - 02:19

8 respuestas

1

Seguro !

Pero en mi experiencia, hay dos tipos generales de registros útiles :

Todo registros: registros creados a través de la API de creación de perfiles. Bueno para identificar problemas de rendimiento y reportar excepciones. Muy ruidoso.

Registros de eventos empresariales : Registros invocados en lógica empresarial. Cualquier cosa que le importe al negocio. Ruido mínimo. Sólo notables, lógicos, eventos "empresariales". Bueno para auditar y KPI's ...

Por lo tanto, sugeriría altamente dos cosas. En primer lugar, haga lo que hacen otras herramientas de monitoreo, como New Relic, y use el. API de creación de perfiles NET 1 . En segundo lugar, registre los eventos empresariales lógicos en su lógica empresarial . Mantener un registro de ciertos eventos es lógica de negocios.

Y, normalmente, no sugeriría AOP para ningún tipo de registro 2 . En mi experiencia, o bien desea todo , lo que significa que está usando un generador de perfiles, o quiere eventos lógicos / comerciales. Y en este último caso, creo que es más sencillo simplemente invocar al registrador en la lógica de negocios.

1. Pero en serio, ahórrate miles de horas de esfuerzo y solo usa una herramienta de perfilado existente ...

2. Por supuesto, esto supone que compartes mi opinión de que un aspecto no es un gran lugar para ocultar las reglas comerciales.

    
respondido por el svidgen 17.03.2017 - 16:13
8

Claro, puedes usar AOP fácilmente para esto. Simplemente refactoriza las partes

  • Obtener usuario por ID
  • paso 1
  • paso 2

en métodos separados (como debería haber hecho para que su código sea más limpio). Ahora puede configurar fácilmente su marco AOP para registrar las llamadas de método de su elección ( como se muestra aquí ). La persona que llama puede registrar la excepción directamente, sin necesidad de usar AOP para obtener esto de la lógica de negocios.

A tu edición:

  

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 ser dividido en pedazos más pequeños

¿Por qué no debería? Si, en un "contexto de lógica de negocios", quiere registrar "algo" que vale 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 utilizar AOP, será necesario 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 interpretarlo como un beneficio, ya que le brinda una retroalimentación en la que se puede mejorar la estructura de su código.

    
respondido por el Doc Brown 16.03.2017 - 08:31
2

Con la ayuda de un patrón común, puede extraer el código de registro de su lógica empresarial. Sin embargo, puede que no valga la pena hacerlo.

Por ejemplo, mediante el uso de un oyente (handcraft one o utilizando un bus de eventos, etc.), su código se verá como

public void SomeDomainMethod(string id)
{
   //Get user by Id
   User user = Users.Get(id);
   if (user == null)
   {
      listener.OnUserNotFound(userId);
      throw new InvalidOperationException("user is not existed");
   }

   //Step 1 
   while(true)
   {
       //do something
   }
   listener.OnStep1Finished(......);

   ...

}

Al implementar el registro en la escucha, la lógica de registro ya no está en su lógica de negocios.

Sin embargo, puede que esto no siempre sea realista, ya que no siempre puede definir eventos significativos de su lógica.

Otro enfoque es a través de un mecanismo como Dtrace en Solaris que le permite inyectar en procesos en ejecución (creo que hay una forma similar de hacer C #?) para que el registro y las reuniones estadísticas se puedan definir en tiempo de ejecución. Todavía hay otros inconvenientes.

    
respondido por el Adrian Shum 16.03.2017 - 05:30
2

Otro enfoque es separar el registro comercial y el registro técnico. Luego podemos llamar "auditoría" al registro de negocios y aplicar un conjunto específico de reglas de negocios, como el término de almacenamiento y reglas de procesamiento, como el monitoreo de la actividad de negocios.

Por otro lado, el registro técnico, o simplemente "Registro", es un último recurso para dejar un rastro de un problema técnico. Debe ser asíncrono, rápido, tolerante al error de persistir en el mensaje de registro. Además, los mensajes de registro deben pasar por el menor número de proxies posibles para estar cerca de la fuente del problema.

La lógica de The Logging es bastante variable y está estrechamente unida a la implementación, ¿entonces realmente necesitas separarlo del código?

La lógica de la auditoría 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 los puertos 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 empresarial, en lugar de por sistemas externos.

    
respondido por el iTollu 16.03.2017 - 06:12
2

A menos que el registro sea parte de los requisitos del negocio, es mejor, como usted dice, mantenerlo completamente fuera de su código.

Eso significa que realmente no quieres registrar cosas como "paso 1 completo". Aunque inicialmente podría ser útil para la depuración, en producción solo va a generar gigabytes de basura que nunca verás.

Si Step1Complete es un tipo de evento empresarial que requiere una acción adicional, puede exponerse a través de un evento antiguo y antiguo sin obligarlo a inyectar un ILogger o similar en su clase

    
respondido por el Ewan 16.03.2017 - 07:28
1

Formas de evitar el registro directamente en una clase o método:

  1. Lance una excepción y realice su 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.

  2. Realice llamadas a métodos que ya están instrumentados para el registro.

respondido por el Robert Harvey 16.03.2017 - 03:56
1

¿Es realmente necesario separar su registro de su lógica empresarial? El registro realizado se corresponde con la lógica de negocios escrita y, por lo tanto, tiene sentido estar en la misma clase / función. Más importante aún, facilita la legibilidad del código.

Sin embargo, en caso de que realmente desee separar el registro de la lógica de su negocio, debería considerar la posibilidad de lanzar excepciones personalizadas y entregar esas excepciones para el registro.

    
respondido por el user88748 16.03.2017 - 06:20
0

No, no en c #

OP, la respuesta a su pregunta específica es no, no en c #. Puede haber otros lenguajes AOP más nativos, pero todos los enfoques de AOP en c # que he visto solo pueden aplicar comportamientos relacionados en el contexto de un join point , lo que significa que tiene que 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ía "visualizar" ciertos bits de registro

Dicho esto, podría extraer ciertas inquietudes relacionadas con el registro, pero no la escritura del registro. Por ejemplo, un punto de corte que se ejecuta en la entrada a un método podría configurar un contexto de registro y generar todos los parámetros de entrada, y al salir podría detectar excepciones o enviar un registro al almacenamiento permanente, ese tipo de cosas.

Registrar escribir no es un aspecto, de todos modos

Añadiría que la escritura del registro no es realmente una preocupación transversal, de todos modos. Al menos no depurar el registro. Mi evidencia de esto es que no se pudo escribir un requisito transversal que explique por completo 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á pasando con el lógica, y la lógica en cada método debe ser razonablemente única (consulte DRY ).

En otras palabras, existe una dependencia lógica inextricable entre la escritura del registro y el contenido 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 es compatible con un requisito de no repudio ) entonces algunos argumentarían (y estoy de acuerdo) que si necesita ejecutar estas escrituras de registro en medio de un método, no ha estructurado su código de una manera que sea 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.

    
respondido por el John Wu 17.03.2017 - 17:48

Lea otras preguntas en las etiquetas