Pregunta

Aquí hay un problema con el que he luchado desde que comencé a aprender programación orientada a objetos:¿Cómo se debería implementar un registrador en código OOP "adecuado"?

Con esto me refiero a un objeto que tiene un método al que queremos que todos los demás objetos del código puedan acceder;este método generaría una salida a la consola/archivo/lo que sea, que usaríamos para registrar; por lo tanto, este objeto sería el objeto registrador.

No queremos establecer el objeto registrador como una variable global, porque las variables globales son malas, ¿verdad?Pero tampoco queremos que pase el objeto registrador en los parámetros de cada método que llamamos en cada objeto.

En la universidad, cuando le comenté esto al profesor, en realidad no pudo darme una respuesta.Me doy cuenta de que en realidad existen paquetes (por ejemplo, Java) que podrían implementar esta funcionalidad.Sin embargo, lo que en última instancia estoy buscando es el conocimiento de cómo implementar esto correctamente y de forma orientada a la programación orientada a objetos.

¿Fue útil?

Solución

hacer desea establecer el registrador como una variable global, porque las variables globales son no malo.Al menos no son inherentemente malos.Un registrador es un gran ejemplo del uso adecuado de un objeto accesible globalmente.Lea sobre el patrón de diseño Singleton si desea obtener más información.

Otros consejos

Hay algunas soluciones muy bien pensadas.Algunos implican pasar por alto OO y utilizar otro mecanismo (AOP).

El registro realmente no se adapta demasiado bien a OO (lo cual está bien, no todo lo hace).Si tiene que implementarlo usted mismo, le sugiero simplemente crear una instancia de "Registro" en la parte superior de cada clase:

registro final privado = nuevo registro (este);

y todas tus llamadas de registro son triviales:log.print("Hola");

Lo que lo hace mucho más fácil de usar que un singleton.

Haga que su registrador averigüe qué clase está pasando y utilícela para anotar el registro.Como tienes una instancia de registro, puedes hacer cosas como:

log.addTag("Factura");

Y el registro puede agregar la etiqueta factura a cada entrada para que pueda implementar un mejor filtrado para su visualización.

Sin embargo, log4j y motosierra son una solución perfecta lista para usar; si no solo estás siendo académico, úsalos.

Un registrador accesible globalmente es complicado de probar.Si necesita una función de registro "centralizada", créela al iniciar el programa e inyéctela en las clases/métodos que necesitan registro.¿Cómo se prueban métodos que usan algo como esto?

public class MyLogger 
{
    public static void Log(String Message) {}
}

¿Cómo se reemplaza con un simulacro?

Mejor:

public interface ILog 
{
    void Log(String message);
}

public class MyLog : ILog 
{
    public void Log(String message) {}
}

Siempre he usado el patrón Singleton para implementar un objeto de registro.

Podrías mirar el patrón Singleton.

Cree el registrador como una clase singleton y luego acceda a él mediante un método estático.

Creo que deberías usar AOP (programación orientada a aspectos) para esto, en lugar de programación orientada a objetos.

En la práctica, en mi opinión, un método singleton/global funciona bien.Preferiblemente, lo global es solo un marco al que se pueden conectar diferentes oyentes (patrón de observador), p.uno para salida de consola, uno para salida de base de datos, uno para salida de Windows EventLog, etc.

Sin embargo, tenga cuidado con el diseño excesivo, creo que en la práctica una sola clase con solo métodos globales puede funcionar bastante bien.

O podría utilizar la infraestructura que ofrece el marco particular en el que trabaja.

El Bloque de aplicación de registro de biblioteca empresarial que proviene del grupo de Patrones y Prácticas de Microsoft es un gran ejemplo de implementación de un marco de registro en un entorno de programación orientada a objetos.Tienen excelente documentación sobre cómo implementaron su bloque de aplicaciones de registro y todo el código fuente está disponible para su propia revisión o modificación.

Hay otras implementaciones similares: log4net, log4j, log4cxx

La forma en que implementaron el bloque de aplicaciones de registro de biblioteca empresarial es tener un archivo estático Logger clase con varios métodos diferentes que realmente realizan la operación de registro.Si estuvieras mirando patrones, este sería probablemente uno de los mejores usos del patrón Singleton.

Estoy totalmente a favor de AOP junto con log4*.Esto realmente nos ayudó.Google me dio Este artículo por ejemplo.Puedes intentar buscar más sobre ese tema.

(En mi humilde opinión) cómo ocurre el "registro" no es parte del diseño de su solución, es más parte de cualquier entorno en el que se esté ejecutando, como Sistema y Calendario en Java.

Su "buena" solución es aquella que está lo más débilmente acoplada posible a cualquier implementación de registro en particular, así que piense en las interfaces.comprobaría el rastro aquí Para ver un ejemplo de cómo Sun lo abordó, ya que probablemente idearon un diseño bastante bueno y lo presentaron todo para que usted pueda aprender.

use una clase estática, tiene la menor sobrecarga y es accesible desde todos los tipos de proyectos dentro de una simple referencia de ensamblaje

tenga en cuenta que un Singleton es equivalente, pero implica una asignación innecesaria

Si está utilizando varios dominios de aplicaciones, tenga en cuenta que es posible que necesite un objeto proxy para acceder a la clase estática desde dominios distintos al principal.

Además, si tiene varios subprocesos, es posible que deba bloquear las funciones de registro para evitar entrelazar la salida.

En mi humilde opinión, el registro por sí solo es insuficiente, por eso escribí CALMA

¡buena suerte!

Tal vez insertar el registro de forma transparente prefiera pertenecer al lenguaje de la programación orientada a aspectos.Pero aquí estamos hablando de diseño OO...

En mi opinión, el patrón Singleton puede ser el más útil:puede acceder al servicio de registro desde cualquier contexto a través de un método público y estático de una clase LoggingService.

Aunque esto puede parecer una variable global, no lo es:está correctamente encapsulado dentro de la clase singleton y no todos tienen acceso a él.Esto le permite cambiar la forma en que se maneja el registro incluso en tiempo de ejecución, pero protege el funcionamiento del registro del código 'vilain'.

En el sistema en el que trabajo, creamos una serie de 'singletons' de registro para poder distinguir mensajes de diferentes subsistemas.Estos se pueden activar/desactivar en tiempo de ejecución, se pueden definir filtros, es posible escribir en un archivo...Tu dilo.

Resolví esto en el pasado agregando una instancia de una clase de registro a las clases base (o interfaz, si el lenguaje lo admite) para las clases que necesitan acceder al registro.Cuando registra algo, el registrador mira la pila de llamadas actual y determina el código de invocación a partir de eso, configurando los metadatos adecuados sobre la declaración de registro (método fuente, línea de código si está disponible, clase que registró, etc.). De esta manera, se obtiene un mínimo Varias clases tienen registradores, y los registradores no necesitan configurarse específicamente con los metadatos que se pueden determinar automáticamente.

Este hace agrega una sobrecarga considerable, por lo que no es necesariamente una buena elección para el registro de producción, pero algunos aspectos del registrador pueden desactivarse condicionalmente si lo diseña de esa manera.

De manera realista, uso commons-logging la mayor parte del tiempo (trabajo mucho en Java), pero hay aspectos del diseño que describí anteriormente que encuentro beneficiosos.Los beneficios de tener un sistema de registro robusto en el que alguien ya ha dedicado mucho tiempo a depurarlo han superado la necesidad de lo que podría considerarse un diseño más limpio (eso es obviamente subjetivo, especialmente dada la falta de detalles en esta publicación).

He tenido problemas con registradores estáticos que causan problemas de memoria permanente (al menos, yo pensar ese es el problema), por lo que probablemente volveré a visitar los registradores pronto.

Para evitar variables globales, propongo crear un REGISTRO global y registrar sus globales allí.

Para iniciar sesión, prefiero proporcionar una clase singleton o una clase que proporcione algunos métodos estáticos para iniciar sesión.

En realidad, usaría uno de los marcos de registro existentes.

Otra posible solución es tener una clase Log que encapsule el procedimiento de registro/almacenado.De esa manera puedes crear una instancia de un new Log(); siempre que lo necesites sin tener que usar un singleton.

Esta es mi solución preferida, porque la única dependencia que necesita inyectar es la base de datos si inicia sesión a través de una base de datos.Si potencialmente está utilizando archivos, no necesita inyectar ninguna dependencia.También puede evitar por completo una clase/función de registro global o estática.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top