我想知道你们中是否有人知道任何最佳实践或设计模式,这样我就可以在我的程序中进行良好的日志记录,而不会让它们看起来混乱或臃肿。
我目前正在使用C#和NLog,但是我想这里的任何建议都是语言和工具不可知论的。
我们面临的问题是,我们希望拥有良好的日志记录,然而,我们似乎无法找到一种方法来绕过许多只需要日志操作的行,这些行可以转换成这样一个简单的方法:
void Foo()
{
Bar bar = dbContext().Bars.First();
bool someCondition = bar.DoSomething();
if (someContition)
{
dbContext().FooBars.Add(new FooBar());
}
}变成这样的东西:
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");
}
}在这里,我们有比代码行更多的日志记录行。
然而,操作告诉我,这种级别的日志记录是必需的,目前仍然太粗糙。
有没有办法绕过这个丑陋的手工伐木,还是我被它困住了?
发布于 2014-03-24 10:00:04
可以想象,这种跟踪日志可以用Aspect来解决。
面向方面的编程允许您将样板样式的代码添加到您的程序中,而无需实际将样板内联编写。例如,您可以在每次程序输入方法时添加一个方面,而不是记录一个方法名称和参数,然后每次方法返回时都记录该方法名和返回值。
当然,您不一定要记录每个方法。相反,大多数方面框架允许您指示要添加样板的代码。
我对C#的了解还不足以推荐一个特定的面向方面的框架供您使用,或者为您提供适当的语法。抱歉的。
发布于 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推荐的面向方面的编程。
发布于 2014-03-27 00:28:40
正如比尔·米切尔所指出的那样,面向方面的编程是添加样板日志代码的一种好方法,但是在本例中,我认为这并不是必要的--我会用一些好的老式重构来处理这个问题。
在您的示例中,Foo方法执行所有的日志记录,但是如果重要的是要记录您将要做的事情(或者您已经做了一些事情),那么最好将其记录在正在执行该操作的方法中,而不是在调用方法中。通过将数据库调用重构为单独的方法(无论如何,这些方法可能在不同的类上),并且重构日志记录调用非常容易,可以使Foo方法与以前一样可读性。
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);
}因此,在回答更普遍的问题“如何在保持代码可读性的同时添加日志记录?”时,我将我的方法重构为更小的方法,直到每个方法都具有所需的可读性。
https://codereview.stackexchange.com/questions/45193
复制相似问题