从设计角度看Log()和Log(LogLevel)之间有什么区别吗?

时间:2014-11-24 10:39:52

标签: api log4net

我最近一直在想,从设计的角度看Log()和Log(LogLevel)之间有什么真正的区别吗?

例如,在log4net中,ILog接口的设计如下。

// Design A 
public interface ILog
{
    /* Log a message object */
    void Debug(object message);
    void Info(object message);
    void Warn(object message);
    void Error(object message);
    void Fatal(object message);

    // ... ignore more members
}

但我认为它等同于这样设计。

// Design B
public enum LogLevel
{
    Debug,
    Info,
    Warn,
    Error,
    Fatal
}

public interface ILog
{
    /* Log a message object */
    void Log(LogLevel level, object message);

    // ... ignore more members
}

那为什么log4net不使用设计B?有什么特别的原因吗?

我能想到的一个原因是,设计A减少了调用者的代码噪声,每次都指定类似LogLevel.Info的内容。

但是设计B也可以有一个好处,我们可以在一次通话中改变消息的严重性。例如logger.Log(some_bool_condition?LogLevel.Warning:LogLevel.Error)。但是,当然,我们可以创建一个包装来执行与设计A类似的操作。

1 个答案:

答案 0 :(得分:1)

从技术上讲,这两种方法都可以从ILog访问,因为它来自ILoggerWrapper。从那里你可以获得一个ILogger,它允许你直接调用方法作为你正在描述的方法B:

void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception);
void Log(LoggingEvent logEvent);

所以让ILog主要减少代码噪音,并且只是在幕后调用记录器:

// log4net.Core.LogImpl
public virtual void Info(object message)
{
    this.Logger.Log(LogImpl.ThisDeclaringType, this.m_levelInfo, message, null);
}

显然这里有一些不同解释的空间,但这就是为什么我认为最好使用Debug / Info / Warn / Error / Fatal方法而不是通用Log(级别)方法。通过强制您的代码使用一种方法,库强制它在撰写时断言信息在您应用范围内的重要性。

如果您可以将级别推迟到某个更高的层次结构,您只需说"哦,让呼叫者决定他们希望从我的组件中听到多少"。但是他们无法知道某些东西对你的组件是否重要。您的代码会塑造所需的信息;应用程序用户不想听到它让他通过配置让你的记录器保持沉默,但只有你的代码知道缺少的SQL服务器是否会引起警报或只是一些轻微的麻烦(来自最近的开发人员,其中一个数据库只要过去曾经回答过一次,我的组件服务器就会消失而没有问题。