首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无代码膨胀的日志记录

无代码膨胀的日志记录
EN

Code Review用户
提问于 2014-03-24 09:48:12
回答 7查看 12.7K关注 0票数 41

我想知道你们中是否有人知道任何最佳实践或设计模式,这样我就可以在我的程序中进行良好的日志记录,而不会让它们看起来混乱或臃肿。

我目前正在使用C#和NLog,但是我想这里的任何建议都是语言和工具不可知论的。

我们面临的问题是,我们希望拥有良好的日志记录,然而,我们似乎无法找到一种方法来绕过许多只需要日志操作的行,这些行可以转换成这样一个简单的方法:

代码语言:javascript
复制
void Foo()
{ 
    Bar bar = dbContext().Bars.First();
    bool someCondition = bar.DoSomething();
    if (someContition)
    {
        dbContext().FooBars.Add(new FooBar());
    }
}

变成这样的东西:

代码语言:javascript
复制
void Foo()
{ 
    _logger.Info("Getting first bar from database...");

    Bar bar = dbContext().Bars.First();

    _logger.Info("First bar returned from database, id = {0}", bar.Id);

    _logger.Info("Doing something on bar with id = {0}", bar.Id);
    bool someCondition = bar.DoSomething();

    _logger.Info("Something done on bar with id = {0}, response = {1}", bar.Id, someCondition);

    if (someContition)
    {
        _logger.Warn("Adding new FooBar to database");
        dbContext().FooBars.Add(new FooBar());
        _logger.Warn("Added new FooBar to database successfully");
    }
}

在这里,我们有比代码行更多的日志记录行。

然而,操作告诉我,这种级别的日志记录是必需的,目前仍然太粗糙。

有没有办法绕过这个丑陋的手工伐木,还是我被它困住了?

EN

回答 7

Code Review用户

回答已采纳

发布于 2014-03-24 10:00:04

可以想象,这种跟踪日志可以用Aspect来解决。

面向方面的编程允许您将样板样式的代码添加到您的程序中,而无需实际将样板内联编写。例如,您可以在每次程序输入方法时添加一个方面,而不是记录一个方法名称和参数,然后每次方法返回时都记录该方法名和返回值。

当然,您不一定要记录每个方法。相反,大多数方面框架允许您指示要添加样板的代码。

我对C#的了解还不足以推荐一个特定的面向方面的框架供您使用,或者为您提供适当的语法。抱歉的。

票数 30
EN

Code Review用户

发布于 2014-03-24 12:22:28

查看您的代码,我相信您的问题不仅是日志记录行很难看,而且它们比帮助您花费更多的风险:

  • 与注释一样,日志行维护经常被遗忘,并且可能会在更改时中断代码,或者--更糟糕的是--在试图通过读取日志文件来排除故障时(想想您将Bar bar = dbContext().Bars.First();更改为Bar bar = dbContext().Bars.Last();,但不更改日志文件的情况--日志会告诉您返回的第一个栏是X,现在您会抓挠头,这是怎么发生的?)
  • 如果需要的话,代码中的日志绝对不是针对级别Info的,更不用说级别Warn了--这些都是Debug日志。用调试日志填充您的文件将使您的日志文件很大,并且无法使用。
    • 只有在预期行为之外的事情发生时,才应该记录Warn日志,以便将故障排除生产集中在这一点上。
    • Info日志应该简洁,与事务数量成线性关系,并传递有价值的信息。
    • Debug日志通常是在您试图查找一个难以捉摸的bug时临时添加的,并且需要在特定代码中提供更多信息。在生产场景中,应该关闭这些日志。

这是暗示从您的职位,您收到了这一要求从业务小组。我很难理解为什么操作团队会要求您记录内部代码行为.它们可能要求您在特性级别上有特定的日志,但是有一个细粒度的日志记录要求似乎有违直觉,而不是他们的职责范围。

无论如何,为了解决第一个问题(并使您的代码更简洁),AFAIK的最佳策略是使用@BillMichell推荐的面向方面的编程

票数 20
EN

Code Review用户

发布于 2014-03-27 00:28:40

正如比尔·米切尔所指出的那样,面向方面的编程是添加样板日志代码的一种好方法,但是在本例中,我认为这并不是必要的--我会用一些好的老式重构来处理这个问题。

在您的示例中,Foo方法执行所有的日志记录,但是如果重要的是要记录您将要做的事情(或者您已经做了一些事情),那么最好将其记录在正在执行该操作的方法中,而不是在调用方法中。通过将数据库调用重构为单独的方法(无论如何,这些方法可能在不同的类上),并且重构日志记录调用非常容易,可以使Foo方法与以前一样可读性。

代码语言:javascript
复制
void Foo()
{
    Bar bar = GetFirstBar();
    bool someCondition = bar.DoSomething();
    if (someContition)
    {
        AddFooBar();
    }
}

Bar GetFirstBar()
{
    _logger.Info("Getting first bar from database...");
    return dbContext().Bars.First();
    _logger.Info("First bar returned from database, id = {0}", bar.Id);
}

void AddFooBar()
{
    _logger.Warn("Adding new FooBar to database");
    dbContext().FooBars.Add(new FooBar());
    _logger.Warn("Added new FooBar to database successfully");
}

bool DoSomething(this Bar bar)
{
    _logger.Info("Doing something on bar with id = {0}", bar.Id);
    // Implementation goes here
    _logger.Info("Something done on bar with id = {0}, response = {1}", bar.
    Id, someCondition);
}

因此,在回答更普遍的问题“如何在保持代码可读性的同时添加日志记录?”时,我将我的方法重构为更小的方法,直到每个方法都具有所需的可读性。

票数 9
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/45193

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档