Dav*_* J. 20 ruby-on-rails mongoid
您认为使用域逻辑回调的优缺点是什么?(我在Rails和/或Ruby项目的上下文中讨论.)
为了开始讨论,我想在回调中的Mongoid页面中提到这个引用:
使用域逻辑的回调是一种糟糕的设计实践,并且当链中的回调暂停执行时,可能导致难以调试的意外错误.我们建议只将它们用于跨领域的问题,例如排队后台工作.
我很想听听这个说法背后的争论或辩护.它是否仅适用于Mongo支持的应用程序?或者它旨在应用于数据库技术?
似乎"Ruby on Rails指南"对ActiveRecord验证和回调可能不同意,至少在涉及关系数据库时.举个例子:
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => :paid_with_card?
end
Run Code Online (Sandbox Code Playgroud)
在我看来,这是一个实现域逻辑的简单回调的完美示例.它似乎快速有效.如果我要接受Mongoid的建议,那么这个逻辑会转向哪里?
nat*_*vda 28
我真的很喜欢为小班使用回调.我发现它使一个类非常易读,比如像
before_save :ensure_values_are_calculated_correctly
before_save :down_case_titles
before_save :update_cache
Run Code Online (Sandbox Code Playgroud)
现在可以清楚地知道发生了什么.
我甚至觉得这个可以测试; 我可以测试方法本身是否有效,我可以单独测试每个回调.
我坚信类中的回调只应该用于属于该类的方面.如果你想在保存时触发事件,例如,如果对象处于特定状态时发送邮件,或者记录,我会使用观察者.这尊重单一责任原则.
简而言之:
和往常一样:所有的建议必须采取一些盐.但根据我的经验,观察者的表现非常好(并且也鲜为人知).
希望这可以帮助.
编辑:我已经将我的答案结合在一些人的建议上.
基于一些阅读和思考,我已经对我所相信的一些(暂定的)陈述:
语句"使用域逻辑的回调是一种糟糕的设计实践"是错误的,如所写的那样.它夸大了这一点.回调可以是适当使用的域逻辑的好地方.这个问题不应该是如果域模型的逻辑应该在回调中去,这是什么样的领域逻辑有道理进去.
声明"使用域逻辑的回调...可能导致在链暂停执行中的回调"时为难以调试的意外错误.
是的,回调可能会导致影响其他对象的连锁反应.在某种程度上,这是不可测试的,这是一个问题.
是的,您应该能够测试业务逻辑,而无需将对象保存到数据库.
如果一个对象的回调因为你的敏感性而变得过于膨胀,那么可以考虑其他设计,包括(a)观察者或(b)辅助类.这些可以干净地处理多个对象操作.
"只使用[回调]来解决交叉问题,例如排队后台工作"的建议很有趣,但却被夸大了.(我回顾了跨领域的问题,看看我是否可能会忽视某些事情.)
我还想分享一些我对博客文章的反应,我已经阅读了关于这个问题的讨论:
Mathias Meyer的2010年帖子,ActiveRecord的Callbacks毁了我的生活,提供了一个视角.他写:
每当我开始在Rails应用程序中为模型添加验证和回调时[...]它只是感觉不对.感觉就像我正在添加不应该存在的代码,这会使一切变得复杂得多,并且变成隐式代码.
我发现最后一个声明"明确变成隐含代码"是一种不公平的期望.我们在这里谈论Rails,对吧?!如此大量的增值是关于Rails"神奇地"做事情,例如没有开发人员必须明确地做.享受Rails的成果并批评隐含代码似乎并不奇怪吗?
仅根据对象的持久性状态运行的代码.
我同意这听起来很令人讨厌.
难以测试的代码,因为您需要保存对象以测试业务逻辑的各个部分.
是的,这使测试变得缓慢而困难.
因此,总而言之,我认为Mathias在火灾中添加了一些有趣的燃料,尽管我并未发现所有这些都令人信服.
在James Golick的2010年帖子中,Crazy, Heretical 和Awesome:The Way I Write Rails Apps,他写道:
此外,将所有业务逻辑耦合到持久性对象可能会产生奇怪的副作用.在我们的应用程序中,当创建某些内容时,after_create回调会在日志中生成一个条目,用于生成活动源.如果我想创建一个没有记录的对象,比如在控制台中,该怎么办?我不能.拯救和伐木永远结婚,永恒.
后来,他找到了它的根源:
解决方案实际上非常简单.对问题的简化解释是我们违反了单一责任原则.因此,我们将使用标准的面向对象技术来分离模型逻辑的关注点.
我真的很感激他通过告诉你何时适用以及什么时候没有:
事实是,在一个简单的应用程序中,肥胖的持久性对象可能永远不会受到伤害.事情比CRUD操作复杂得多,这些事情开始堆积起来并成为痛点.
| 归档时间: |
|
| 查看次数: |
3537 次 |
| 最近记录: |