【问题标题】:Cross cutting concern example横切关注点示例
【发布时间】:2014-07-05 05:12:42
【问题描述】:

cross-cutting concern 的好例子是什么? wikipedia 页面上的医疗记录示例对我来说似乎不完整。

从这个例子来看,为什么日志会导致代码重复(scattering)? (除了诸如log("....") 之类的简单调用之外,这似乎没什么大不了的)。

core concerncross-cutting concern 有什么区别?

我的最终目标是更好地理解 AOP。

【问题讨论】:

    标签: design-patterns aop cross-cutting-concerns


    【解决方案1】:

    在了解Crosscutting Concern之前,我们必须了解Concern

    关注是一个术语,指的是根据功能划分的系统部分。

    有两种类型的担忧:

    1. 代表主要需求的单一和特定功能的关注点称为核心关注点

      系统的主要功能称为核心关注点。
      例如:业务逻辑
    2. 代表次要需求功能的关注点称为横切关注点或系统范围关注点

      横切关注点是适用于整个应用程序的关注点,它会影响整个应用程序。
      例如:日志记录、安全性和数据传输是关注点应用程序的几乎每个模块都需要它们,因此它们是横切关注点。

    Courtesy

    此图表示一个典型的应用程序,它被分解为多个模块。每个模块的主要关注点是为其特定领域提供服务。但是,这些模块中的每一个也需要类似的辅助功能,例如安全日志记录和事务管理。横切关注点的一个例子是“日志记录”,它经常用于分布式应用程序中,通过跟踪方法调用来帮助调试。假设我们在每个函数体的开头和结尾都进行日志记录。这将导致横切具有至少一个功能的所有类。

    (Courtesy)

    【讨论】:

    • “横切关注点是一个适用于整个应用程序的关注点” ➤ 不确定这一点,因为事务管理不适用于“整个”应用程序,但仍然是一个横切关注点。说实话,这张照片没有告诉我,这只是令人困惑..
    • 很好的解释,但我对我们称之为这些关注点的图片有一点问题,横切而不是横切关注,我认为最好用横切来减少其他关注减少担忧,而不是另一种方式。喜欢面向方面的开发
    • 答案仍然不能解释简单地使用像 Log4j 这样的东西和像 LogManager.getLogger().info(ModuleName, msg) 这样的日志记录的问题
    【解决方案2】:

    我认为横切关注点最好的例子是事务行为。例如,必须在所有服务方法中放置带有提交和回滚调用的 try-catch 块将是令人厌恶的。使用 AOP 可以用来封装所需事务行为的标记来注释方法是一个巨大的胜利。

    作为横切关注点示例的另一个很好的候选者是授权。使用标记来注释服务方法,告诉谁可以调用它,并让一些 AOP 建议决定是否允许方法调用,这比在服务方法代码中处理更可取。

    使用 AOP 建议实现日志记录可能是一种获得更大灵活性的方法,这样您就可以通过更改连接点来更改记录的内容。在实践中,我不经常看到项目这样做。通常使用 log4j 之类的库,它可以让您在运行时按日志记录级别和类别进行过滤,如果需要,效果很好。

    核心关注点是应用程序存在的原因,即应用程序自动化的业务逻辑。如果您有一个物流应用程序来处理运输货物,那么确定您可以在卡车上装载多少货物或卡车可以采取哪些最佳路线来交付货物可能是核心问题。横切关注点通常是需要与业务逻辑分开的实现细节。

    【讨论】:

    • 因此,即使事务行为确实只存在于数据访问层,因为 try-catch 块在许多方法中重复,它也被认为是横切的。我最初的看法是横切意味着代码跨越了应用程序的多个层。
    • @jlars62:横切意味着它与特征成直角。
    • @jlars62:直角我的意思是:把一个特征想象成一堆层。一个横切关注点可能只适用于一层,但它对所有功能都是通用的。
    • @NathanHughes 授权就是一个很好的例子。我刚刚重构了我的应用程序,将所有授权代码放在一个横切的架构中,它清理了很多代码。我认为域就像一所房子。如果你有进入的钥匙,你可以在那里做任何你想做的事情(你被认为是所有者)。但你不会锁上房子里的每一扇门并要求钥匙进入。你要么加入,要么不加入。
    • “事务行为”可能对许多功能来说很常见,但这不会是“横切”,因为它没有“跨越”层。例如,日志记录是一个横切关注点的原因是因为我可能想要登录表示层、业务层、数据层等。
    【解决方案3】:

    除了公认的答案之外,我还想提及另一个横切关注点的示例:远程处理。假设我只想在本地调用我的生态系统中的其他组件,就好像它们正在运行一样。也许在某些情况下他们甚至会这样做。但现在我想在云或集群中运行我的服务。作为应用程序开发人员,我为什么要关心这方面?一个方面可以负责找出呼叫谁以及如何呼叫,必要时序列化传输的数据并进行远程呼叫。如果一切都在进程中运行,则方面只会转发本地呼叫。在被调用方方面,方面将反序列化数据,进行本地调用并返回结果。

    现在让我告诉你一个关于日志输出等“琐碎”事情的小故事:就在几周前,我为一个客户重构了一个复杂但不太大的代码库(大约 250K 行代码)。在几百个类中使用了一种日志框架,在另外几百个中使用了另一种。然后有几千行System.out.println(*) 确实应该有日志输出。所以我最终修复了分散在代码库中的数千行代码。幸运的是,我可以在 IntelliJ IDEA(结构搜索和替换)中使用一些巧妙的技巧来加快整个操作,但是你不认为这是微不足道的吗!当然,强烈依赖于上下文的调试日志将始终发生在方法主体中,但是许多重要类型的日志记录,例如跟踪方法调用(甚至是分层的带有很好缩进的输出),记录处理或未处理的异常,用户审计(记录对基于用户角色的受限方法)等可以很容易地在方面实现,而不会污染源代码。日常应用程序开发人员不需要考虑它,甚至不需要看到分散在代码库中的记录器调用。有人负责使方面保持最新,甚至可以在一个地方集中切换日志记录策略或整个日志记录框架。

    我可以对其他横切关注点提出类似的解释。保持代码干净,避免分散和纠缠 IMO 是一个专业问题,而不是任何可选的问题。最后但同样重要的是,它使代码保持可读、可维护、可重构。阿门。

    【讨论】:

    • 请问你是如何隔离代码库中分散的日志的?
    • 这是一个非常笼统的问题。所以我的一般答案是:通过识别日志记录模式,然后将它们中的每一个分解成一个方面(或现有方面的建议),只留下那些不符合使用模式的人。这些比您乍一看可能要少,因为这种重构也会使您重新考虑整个日志记录策略,例如清洁编码类和方法名称,以使通用日志记录更具可读性,从而减少自定义日志消息。
    【解决方案4】:

    我从 Wikipedia 中发现这一点非常清楚:

    如果编写用于处理医疗记录的应用程序,这些记录的索引是一个核心问题,而记录对记录数据库或用户数据库或身份验证系统的更改历史记录将是横切关注点,因为它们交互包含程序的更多部分。

    往往是交叉关注的示例包括:

    业务规则

    缓存

    代码移动性

    数据验证

    特定领域的优化

    错误检测和纠正

    国际化和本地化,包括语言 本地化

    信息安全

    记录

    内存管理

    监控

    坚持

    产品特点

    实时约束

    同步

    事务处理

    上下文相关帮助

    【讨论】:

      【解决方案5】:

      交叉关注点是无论应用程序类型如何都应该始终存在的场景。

      例如日志记录、安全性、性能分析、本地化、可访问性、事务等。 无论我们构建的软件是什么,都需要日志记录(否则有人将如何调试或从产品数据中获取一些相关信息)。只有真正的用户才能以正确的权限集进入应用程序,所以需要安全性(身份验证/授权等)。我们需要知道您的应用程序是如何执行的,然后我们需要进行分析。 如果应用程序被国际用户使用(使用他们自己的本地化语言),那么我们需要在应用程序中支持相同的应用程序。 可访问性是残疾人使用我们的应用程序的可用性案例。

      现在,无论我们的应用程序是基于桌面还是基于 Web 等。如果最终用户需要在生产环境中跨地域使用它,那么就需要交叉切割。 到目前为止,我还没有说任何关于应用程序的全部内容等,但给出了在将其发布给生产环境中的最终用户之前应该解决的问题列表。这就是关于横切关注点的全部内容(需要由所有应用程序/方法/类处理,即在各个级别)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-19
        • 2011-08-01
        • 2020-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多