c# - 方法中的日志记录以何种方式容易出错且具有侵入性?

标签 c# aop

我正在看书Adaptive Code via C# ,作者 Gary McLean Hall 说:

[Logging, and Transactional Code,] is laborious and error-prone, and it instantly pollutes every method with irrelevant boilerplate code, increasing the noise-to-signal ratio. Instead, you can factor out such cross-cutting concerns into encapsulated functionality and apply them to the code in a much less invasive fashion. The most common way of adding functionality non-invasively is through aspect-oriented programming.

对于这段代码:

public void OpenNewAccount(Guid ownerID, string accountName, decimal openingBalance)
{
    log.WriteInfo("Creating new account for owner {0} with name '{1}' and an opening balance of {2}", ownerID, accountName, openingBalance");

    using(var transaction = session.BeginTransaction())
    {
        var user = userRepository.GetByID(ownerID);
        user.CreateAccount(accountName);
        var account = user.FindAccount(accountName);
        account.SetBalance(opening Balance);

        transaction.Commit();
    }
}

我知道它很费力,而且它会做方法名称未指明的事情,例如日志记录,但我不明白为什么它容易出错。可能是因为您经常重复自己的话?

他的建议是改用这段代码:

[Logged]
[Transactional]
public void OpenNewAccount(Guid ownerID, string accountName, decimal openingBalance)
{
    var user = userRepository.GetByID(ownerID);
    user.CreateAccount(accountName);
    var account = user.FindAccount(accountName);
    account.SetBalance(opening Balance);
}

但如果您只是简单地寻找一个通用的记录器,那么您可以调用类似_log.Log() 的方法,这相对来说是相同的工作量。除非属性具有检查方法实现的能力,否则在这种情况下我看不出它们有多大值(value),只是它们提供了稍微更具描述性的代码。

最佳答案

cross-cutting concern日志记录示例。这被认为是横切,因为日志记录策略会影响记录系统的每个部分(至少它必须考虑到这一点)。在这方面,系统的每个部分都需要考虑一些事情,这意味着更改日志记录意味着您可能必须更改系统记录的每个部分,(例如添加更多相关信息)。 (此外,如果您忘记记录重要的内容,您可以称之为容易出错)。在实践中,日志记录通常是良性的,因此它是一个乏善可陈的例子,并且可以称其为容易出错。

我认为一个更好的例子是检查安全性。我不认为看到在各处剪切和粘贴安全代码会很容易出错,而且对该代码的更新可能会变得难以正确。

如果您需要更改安全/权限的实现方式(在非 Aspect 世界中),您(可以想象)需要重新访问每个进行安全检查的地方,因为安全检查分散在整个程序中。复杂的设计使得从设计/维护的角度来看很难考虑所有可能的交互。如果您有 [CheckSecurity] 属性,那么纠缠就会最少,并且永远不需要重新访问需要检查安全性的每个函数。

这里的关键是 Aspects 会根据检查在编译时/运行时更改代码。因此,如果您需要更改检查安全凭证的方式,您只需转到代码中的一个位置。这与仅使用单一方法/函数进行安全检查有很大不同,因为函数无法检查它们的堆栈并根据调用者改变它们的行为。 c# 中的代码注入(inject)可以。

这是一个 PostSharp example1 example2和一个 podcast

关于c# - 方法中的日志记录以何种方式容易出错且具有侵入性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28910568/

相关文章:

c# - 从字节转换 unicode 字符

java - 从默认实现访问建议的对象方法

java - AspectJ:用于选择类上方法的目标与签名模式

java - 使用Spring中的Aspects计算方法处理时间

java - BigInteger 构造函数的切入点

c# - 将信息从一个 View 模型传递到另一个 View 模型

c# - MVC 验证低于/高于其他值

c# - 如何使 IsolatedStorageSettings 在设备/模拟器关闭后仍然存在?

java - Spring AOP 复杂切入点

c# - C# LINQ 方法链中赋值的编译器警告?