Rails controller VS model

liwen_zhang · 2012年04月29日 · 最后由 edokeh 回复于 2012年05月14日 · 5127 次阅读

在开发项目时,会遇到这样的情景: “这块是处理数据的代码,为什么会在 controller 出现?应该写在 model 中” “这块代码是业务逻辑处理,应该写在 controller,不应该放在 model 中” “什么?你说这是业务处理?这明明是纯数据处理,与业务无关。你说说什么是业务处理?" "你看 controller 其他方法多简洁,数据处理都放在 model 中,而你这个方法多庞大,你应该让 controller 简洁,数据处理都仍给 model 不行吗?

你们有没有出现类似这样的情景?到底,哥们觉得,哪些写在 controller,哪些写在 model 呢?

写完测试就会知道了, 应该说了解到了

业务层应该在 action 里处理,同时也要处理从事务层抛过来的异常。事务层,也可以说是 model 层吧,进行数据库的操作,同时不进行异常的处理,直接抛出,由 action 处理。另外还有个服务层。 在 Java 里,尤其是 SSH 里,这些层次关系是相当的明显的。但是在 Rails 里,也应该如此。

我个人的习惯: 一些常用的东西,方便放到 model 中的,就放 model 不常用,稍微复杂,不方便放 model,放 controller 的多个 private 小函数中 不常用,很复杂,不方便放 model,另外写一个类专门处理

坚持一个原则,保持 action 中尽量无逻辑

个人一向认为,controller 不写逻辑,都交给 model,controller 只做调用

我都 是尽量写在 model 里,这样思维上会尽量把业务逻辑拆分为功能逻辑 而且 model 不管是从测试还是调试都比 controller 方便多了,所以放在 model 里比较好

model 处理业务层,良好的接口也是很重要的,方便写测试。 controller 处理 view 层传过来的数据,这个处理也可以理解为 “逻辑”,但是和 model 的业务逻辑是不一样的。

匿名 #7 · 2012年04月29日

controller 负责页面流的跳转, 业务逻辑处理当然是放到 model 中, 对于较复杂或者多个 model 可以公用的逻辑, 可以放到 lib 中, 甚至可以单独做一个 gem

在 rails 社区,一开始提倡的是,富模型,薄控制器。 但是近几年,更大的趋势是,模型也逐渐在减肥,于是乎 DCI 等模式也被应用上来了…… 具体的请自行 google: DCI、rails

http://rails-bestpractices.com/ 说到底还是经验的积累,看看最佳实践吧。

同意#3 楼@bluecoda 的观点,理论上是业务逻辑全部由 model 处理,不过这只是理想状态,只能尽可能地交给 model,controller 主要处理跳转

在 Java 开发中,通常会引入 Service 层和 DAO 层来弱化 Model 的作用,有些人将之称为『贫血模式』,而在 Rails 开发通常将业务逻辑封装到 Model 中,对应称之为『充血模式』

另外还有一套理论是 Domain-Driven Design,Rails 的有点像这个,不过我也不太清楚这方面

我们的团队也遇到过这个问题,为此,我们制定了一个原则,如下

Action 的原则

读数据的情况,只有两行代码 第一行 读数据 第二行 显示结果 比如

def show @product = Product.find_a_special_product(params) render_product end

写数据的情况,只有四行代码 第一行 读数据 第二行 写数据 第三行 显示成功的结果 第四行 显示失败的结果

def update @product = Product.find_a_special_product(params) if @product.update_a_product(params) redirect_to_product @product else render_product_update_fail end end

#1 楼 @Ddl1st 说实话,我们测试抓的比较弱,所以当你提醒从测试入手时,确实给了我一些灵感

#3 楼 @bluecoda #4 楼 @lucky215 #10 楼 @Zernel #7 楼 @sharp 哥们你们提的都是挺好的方案,目前我们的做法跟@sharp 说的很像:业务逻辑放在 model 中,controller 用于调用,全局/公用的逻辑放在 lib 中,项目间可复用的可能用于移植的写成插件/gem。

#9 楼 @xds2000 对,说到底我们的经验还不足,没有大牛给我们指导,而且实践的机会不多:现在还是学生,因此没这么多时间去实践,能经历一个中等项目的整个生命周期就两年多了。只能靠师兄的传承 + 摸索

#12 楼 @ery 约定成这样很好耶,而且一目了然。顺便提一下写数据情况的,我们已经把捕捉异常的封装起来了,所以不需要显示失败的结果,只需要能抛出异常,再通过汉化显示出来。所以按你的约定,可以改进成:第一行 读数据 第二行 写数据 第三行 显示成功的结果

#12 楼 @ery 这个原则值得学习,做个记号。

写测试代码的时候,就会体会到,便于测试,很多方法会放到 Model 层。

前两天看到 infoq 的 grails 最佳实践,有一句可以拿来参考下: “不允许控制器充当其他角色。控制器的角色就是接受传入的请求、检查权限等、问 Domain 或 Service 要结果、将结果用所需的格式(如 HTML、JSON 或 XML)返回给请求者。要让控制器保持苗条。别让它执行业务逻辑、查询或更新。”

#8 楼 @scriptfans 看了两天 DCI 相关的资料,挺有意思的,确实是一种好思路,感谢推荐

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册