记录仪包装的最佳实践 [英] logger wrapper best practice

查看:237
本文介绍了记录仪包装的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用一个nlogger在我的应用程序,也许在未来,我将需要更改日志系统。 所以我想用一个日志门面。

I want to use a nlogger in my application, maybe in the future I will need to change the logging system. So I want to use a logging facade.

你知道现有的例子如何写这些的人什么建议? 或者只是给我链接到一些最佳实践在这方面。

Do you know any recommendations for existing examples how to write those ones ? Or just give me link to some best practice in this area.

推荐答案

我以前用的日志外墙如 Common.Logging (甚至隐瞒自己的 CuttingEdge.Logging 库),但现在我使用的依赖注入模式这让我躲在我自己的(简单)的抽象,坚持两者的依赖倒置原则接口分离原则(ISP),因为它有一个成员,因为该接口是由我的应用程序定义的;不是外部库。最小化的知识,你的应用程序的核心部分有关于外部库的存在,效果更佳;即使你不打算永远取代你的日志库。外部库hard依赖使得它更难测试code,并与复杂这是从来没有专门为您的应用而设计的API应用程序。

I used to use logging facades such as Common.Logging (even to hide my own CuttingEdge.Logging library), but nowadays I use the Dependency Injection pattern and this allows me to hide loggers behind my own (simple) abstraction that adheres to both Dependency Inversion Principle and the Interface Segregation Principle (ISP) because it has one member and because the interface is defined by my application; not an external library. Minimizing the knowledge that the core parts of your application have about the existence of external libraries, the better; even if you have no intention to ever replace your logging library. The hard dependency on the external library makes it harder to test your code, and complicates your application with an API that was never designed specifically for your application.

这是什么抽象往往看起来像我的应用程序:

This is what the abstraction often looks like in my applications:

public interface ILogger
{
    void Log(LogEntry entry);
}

// Immutable DTO that contains the log information.
public class LogEntry 
{
    public readonly LoggingEventType Severity;
    public readonly string Message;
    public readonly Exception Exception;

    public LogEntry(LoggingEventType severity, string message, Exception exception = null)
    {
        Requires.IsNotNullOrEmpty(message, "message");
        Requires.IsValidEnum(severity, "severity");
        this.Severity = severity;
        this.Message = message;
        this.Exception = exception;
    }
}

另外,这种抽象可以推广一些简单的扩展方法(允许接口留窄,并保持秉承ISP)。这使得code这个接口更简单的消费者:

Optionally, this abstraction can be extended with some simple extension methods (allowing the interface to stay narrow and keep adhering to the ISP). This makes the code for the consumers of this interface much simpler:

public static class LoggerExtensions
{
    public static void Log(this ILogger logger, string message) {
        logger.Log(new LogEntry(LoggingEventType.Information, message));
    }

    public static void Log(this ILogger logger, Exception exception) {
        logger.Log(new LogEntry(LoggingEventType.Error, exception.Message, exception));
    }

    // More methods here.
}

由于接口只包含一个方法,你可以很容易地创建一个 ILogger 实施了的代理来log4net的,NLOG或任何其他日志库和配置DI容器中有一个 ILogger 在其构造类注射吧。

Since the interface contains just a single method, you can easily create an ILogger implementation that proxies to log4net, NLog or any other logging library and configure your DI container to inject it in classes that have a ILogger in their constructor.

请注意,这与单一方法的接口进行通信具有静态扩展方法是从具有许多成员的接口有很大不同。扩展方法只是创建一个 LogEntry 消息,并通过 ILogger 界面上的唯一方法传递给它的辅助方法。有许多成员的抽象使得它很难使实现(如嘲笑,适配器和装饰)这样的抽象。

Do note that having static extension methods that communicate with an interface with a single method is quite different from having an interface with many members. The extension methods are just helper methods that create a LogEntry message and pass it through the only method on the ILogger interface. Having an abstraction with many members makes it hard to make implementations (such as mocks, adapters and decorators) for such abstraction.

当你做到这一点,有几乎没有任何需要一些记录外墙静态抽象(或任何其他库)可能会提供。

When you do this, there is hardly ever any need for some static abstraction that logging facades (or any other library) might offer.

这篇关于记录仪包装的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆