首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算表达式是面向方面编程的替代方法吗?

计算表达式是面向方面编程的替代方法吗?
EN

Stack Overflow用户
提问于 2016-08-09 20:58:55
回答 1查看 294关注 0票数 2

计算表达式是面向方面编程的替代方法吗?

这是F#管理横切关注点的解决方案。

我看了下面的文章,不禁想到了AOP (即面向方面的编程)。

文章中,作者提供了一个处理日志记录的计算表达式的示例,但它隔离了代码的实际日志记录方面,而不混淆业务逻辑的主要意图。

我的想法准确吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-10 05:59:52

是的,monads是一种很好的(且惯用的)方法来解决交叉关注点等问题。monad是一个更普遍的概念,但它们的用途之一是在系统中建模效果。

在FP行话中,“效果”这个词通常意味着一个副作用.许多交叉关注点,如日志记录、审计、性能监视、缓存和计量(根据定义)都有副作用。因为它们涉及到将数据‘写入’到次要的有状态资源,所以可以使用State或Writer monads建模。

其他跨领域的关注点,如认证、授权和验证,通常可以通过Reader monad (或者,可能的话,State monad)来解决。

F#计算表达式在一元组合子上提供语法糖(本质上是返回和绑定),这与Haskell的do表示法一样。然而,与Haskell相反,您必须自己为monad定义计算表达式生成器,除了少数已经内置到语言中的表达式生成器(asyncseq)。

使用单一广告来解决交叉关注点是一种不同于AOP的方法。

在面向对象编程中,AOP有两种截然不同的处理方式:

  • 装潢工
  • 编译时编织,其中典型的.NET示例是PostSharp。

正如我在我的书中解释的那样,我认为编译时编织是解决问题的一种困难和不灵活的方法。使用装潢工是实现相同目标的一种更优雅和灵活的方法。

我发言的动机是我倾向于将关切分开。

如果在OOP中使用编译时编织,通常会有如下代码(C#示例):

代码语言:javascript
复制
[Log]
public void SaveOrder(Order order)
{
    // Implementation goes here...
}

这里的问题是,虽然这些关切是分开的,但它们仍然是耦合的。除非重新编译,否则不能决定不从SaveOrder登录。

使用计算表达式有点类似:

代码语言:javascript
复制
log { return saveOrder order }

再一次,横切的关注是与执行一起汇编的.

然而,相似之处在于,可以使用一元组合器将关注点组合在一起,这在编译时编织中是不容易的。在OOP中,您不能轻易地采用不记录的方法,当您将对象组合在一起时,“神奇地”让它记录下来。

另一方面,使用monad,您可以使用纯函数并使用一元上下文编写它。这种后期绑定的日志记录是在结构上等同于使用解码器

因此,我认为将计算表达式用于横切关注点是合适的,只要将这些代码推迟到应用程序的入口点( 成分根)即可。

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

https://stackoverflow.com/questions/38860307

复制
相关文章

相似问题

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