在开发项目时,会遇到这样的情景: “这块是处理数据的代码,为什么会在 controller 出现?应该写在 model 中” “这块代码是业务逻辑处理,应该写在 controller,不应该放在 model 中” “什么?你说这是业务处理?这明明是纯数据处理,与业务无关。你说说什么是业务处理?" "你看 controller 其他方法多简洁,数据处理都放在 model 中,而你这个方法多庞大,你应该让 controller 简洁,数据处理都仍给 model 不行吗?
你们有没有出现类似这样的情景?到底,哥们觉得,哪些写在 controller,哪些写在 model 呢?
业务层应该在 action 里处理,同时也要处理从事务层抛过来的异常。事务层,也可以说是 model 层吧,进行数据库的操作,同时不进行异常的处理,直接抛出,由 action 处理。另外还有个服务层。 在 Java 里,尤其是 SSH 里,这些层次关系是相当的明显的。但是在 Rails 里,也应该如此。
我个人的习惯: 一些常用的东西,方便放到 model 中的,就放 model 不常用,稍微复杂,不方便放 model,放 controller 的多个 private 小函数中 不常用,很复杂,不方便放 model,另外写一个类专门处理
坚持一个原则,保持 action 中尽量无逻辑
我都 是尽量写在 model 里,这样思维上会尽量把业务逻辑拆分为功能逻辑 而且 model 不管是从测试还是调试都比 controller 方便多了,所以放在 model 里比较好
model 处理业务层,良好的接口也是很重要的,方便写测试。controller 处理 view 层传过来的数据,这个处理也可以理解为“逻辑”,但是和 model 的业务逻辑是不一样的。
controller 负责页面流的跳转,业务逻辑处理当然是放到 model 中,对于较复杂或者多个 model 可以公用的逻辑,可以放到 lib 中,甚至可以单独做一个 gem
在 rails 社区,一开始提倡的是,富模型,薄控制器。 但是近几年,更大的趋势是,模型也逐渐在减肥,于是乎 DCI 等模式也被应用上来了…… 具体的请自行 google:DCI、rails
同意#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
前两天看到 infoq 的 grails 最佳实践,有一句可以拿来参考下: “不允许控制器充当其他角色。控制器的角色就是接受传入的请求、检查权限等、问 Domain 或 Service 要结果、将结果用所需的格式(如 HTML、JSON 或 XML)返回给请求者。要让控制器保持苗条。别让它执行业务逻辑、查询或更新。”