Language agnostic OOP上下文中的正确日志记录

Language agnostic OOP上下文中的正确日志记录,language-agnostic,oop,logging,Language Agnostic,Oop,Logging,自从我第一次开始学习面向对象编程以来,我一直在努力解决一个问题:应该如何在“适当的”OOP代码中实现记录器 这里,我指的是一个对象,它有一个方法,我们希望代码中的每个其他对象都能够访问该方法;这个方法将输出到console/file/whatever,我们将使用它来记录日志——因此,这个对象将是logger对象 我们不想将logger对象建立为全局变量,因为全局变量是坏的,对吗?但我们也不希望在每个对象中调用的每个方法的参数中传递logger对象 在大学里,当我向教授提出这个问题时,他实际上无法

自从我第一次开始学习面向对象编程以来,我一直在努力解决一个问题:应该如何在“适当的”OOP代码中实现记录器

这里,我指的是一个对象,它有一个方法,我们希望代码中的每个其他对象都能够访问该方法;这个方法将输出到console/file/whatever,我们将使用它来记录日志——因此,这个对象将是logger对象

我们不想将logger对象建立为全局变量,因为全局变量是坏的,对吗?但我们也不希望在每个对象中调用的每个方法的参数中传递logger对象


在大学里,当我向教授提出这个问题时,他实际上无法给我答案。我意识到实际上有一些包(比如Java)可以实现这个功能。但我最终想要的是,是如何正确地以面向对象的方式实现这一点的知识。

您可以查看Singleton模式。

将记录器创建为Singleton类,然后使用静态方法访问它。

我一直使用Singleton模式实现日志对象。

我认为您应该使用AOP(面向方面编程)对于这一点,而不是OOP。

您确实希望将记录器建立为全局变量,因为全局变量并不坏。至少,它们本身并不坏。记录器是正确使用全局可访问对象的一个很好的例子。如果您想了解更多信息,请阅读有关单例设计模式的内容。

实际上是单例/global方法在我看来效果很好。全局方法最好只是一个框架,您可以将不同的侦听器(观察者模式)连接到该框架,例如,一个用于控制台输出,一个用于数据库输出,一个用于Windows事件日志输出,等等

但是要注意过度设计,我发现在实践中,只有全局方法的单个类可以非常好地工作

或者您可以使用您所使用的特定框架提供的基础设施。

来自Microsoft的模式与实践小组的是在OOP环境中实现日志框架的一个很好的例子。他们有一些关于如何实现日志应用程序块和所有源代码的很好的文档可供您自己查看或修改

还有其他类似的实现:


他们实现企业库日志应用程序块的方式是使用一个静态
Logger
类,该类包含许多实际执行日志操作的不同方法。如果您正在查看模式,这可能是Singleton模式的更好用途之一。

有一些经过深思熟虑的方法一些解决方案涉及绕过OO并使用另一种机制(AOP)

日志本身并不太适合OO(这没关系,不是所有东西都适合OO)。如果您必须自己实现它,我建议在每个类的顶部实例化“Log”:

私有最终日志=新日志(本)

然后,所有日志调用都很简单:log.print(“嘿”)

这使得它比单件更容易使用

让您的日志记录器找出您要传递的类,并使用该类对日志进行注释。因为您有一个日志实例,所以您可以执行以下操作:

log.addTag(“账单”)

日志可以将标签账单添加到每个条目中,这样您就可以对显示进行更好的过滤


log4j和链锯是一个完美的开箱即用的解决方案——如果你不仅仅是学术型的,那么就使用它们。

我完全支持AOP和log4*。这确实帮助了我们。 谷歌给了我一个例子。你可以试着搜索更多关于这个主题的信息。

(IMHO)“日志记录”的发生方式不是你的解决方案设计的一部分,它更多的是你正在运行的任何环境的一部分,比如Java中的系统和日历


您的“好”解决方案是一个尽可能松散地耦合到任何特定日志记录实现的解决方案,因此请考虑接口。我将查看Sun如何处理它的示例,因为他们可能提出了一个非常好的设计,并为您提供了所有可供学习的内容!

使用静态类,它具有最小的开销,并且是ac可从简单程序集引用中的所有项目类型访问

请注意,单例是等效的,但涉及不必要的分配

如果您使用的是多个应用程序域,请注意,您可能需要一个代理对象来从主域以外的域访问静态类

此外,如果您有多个线程,则可能需要锁定日志函数,以避免交错输出

仅凭IMHO日志记录是不够的,这就是我为什么要写的原因


祝你好运!

也许以一种透明的方式插入日志更应该属于面向方面的编程习惯用法。但我们这里讨论的是面向对象设计

在我看来,单例模式可能是最有用的:您可以通过LoggingService类的公共静态方法从任何上下文访问日志服务

虽然这看起来很像一个全局变量,但事实并非如此:它被正确地封装在singleton类中,并且不是每个人都可以访问它。这使您可以更改日志记录的处理方式,即使在运行时,但可以保护日志记录的工作不受“vilain”代码的影响


在我工作的系统中,我们创建了许多日志记录“单例”,以便能够区分来自不同子系统的消息。这些子系统可以在运行时打开/关闭,可以定义过滤器,可以写入文件…你可以这么说。

我过去通过向基类添加日志记录类的实例来解决这个问题(或接口,如果语言支持),用于需要访问日志记录的类。当您记录某个内容时,日志记录程序将查看当前调用堆栈并确定调用
public class MyLogger 
{
    public static void Log(String Message) {}
}
public interface ILog 
{
    void Log(String message);
}

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