Rails 10 Most Common Rails Mistakes

hooopo · 2015年01月28日 · 最后由 jasontang168 回复于 2015年05月06日 · 4242 次阅读
  • Putting too much logic in the controller
  • Putting too much logic in the view
  • Putting too much logic in the model
  • Using generic helper classes as a dumping ground
  • Using too many gems
  • Ignoring your log files
  • Lack of automated tests
  • Blocking on calls to external services
  • Getting married to existing database migrations
  • Checking sensitive information into source code repositories

http://www.toptal.com/ruby-on-rails/top-10-mistakes-that-rails-programmers-make

"Blocking on calls to external services"

这个是没错,但是比如用 http 协议包装第三方服务(只能同步响应),比如查水费,需要 2 秒,这种场景怎么破?

最近老大分享好多好东西

#1 楼 @hjleochen 后台异步,通过 JS 通知页面结果。

-- "Putting too much logic in the model"

这个情况要如何处理呢?

#5 楼 @zgm 好的,多谢!

#1 楼 @hjleochen 换异步框架。goliath 什么的。哈哈。。

  1. Extract Form Objects

说到这里,我觉得还是 django 好啊。modelform 对付企业里常见的 CURD 开发简直是效率神器。

Rails 或者说 Active Model 里不允许定义好字段,这个太憋屈了。 ActiveRecord 的 enum 也是 bug 多多。

#8 楼 @est model 里加个 attr_accessor 不就可以在 form 里面使用了么

#8 楼 @est 和 python 不一样, ruby 的"字段"都是方法假装的, 其实和一般方法没实质区别 (顶多就是虚拟机有个取 ivar 加速的优化), 所以怎么搞都可以的, 给个 model 生成 api 或者 admin 的 gem 也有很多

#3 楼 @sakura79 我们也是服务接口,如果只是供页面使用这样的方式是可以的。 #7 楼 @est 谢谢,goliath 是个好东西,就是解决这样问题的,回头好好看看。

以前遇到的问题,后来写了个 socket server 用 select 的方式实现。

the biggest mistake: using Rails

staging 环境的数据库要比 production 环境的数据库慢 100 倍

#9 楼 @foxzool #10 楼 @luikore

我的意思是:一个 model 有什么字段,直接在 model 里定义了。而不是放到 migration 里。。。。这样做好处很多。最直接的好处就是比如 mysql 里不需要给与特殊权限 SHOW COLUMNS。然后生成表单什么的自然而然了。

最后,加个 enum 什么的搞个 symbole 和 int 的对应,不要太方便。

Lack of automated tests

其实我觉得情况恰好相反 Lack of manual tests, root cause 是 太懒

#14 楼 @est activerecord 首次开发的话直接编辑第一个 migration 就可以了

datamapper 和 mongoid 就是在 model 声明的, 但发布产品后你会发现改个字段心惊胆跳的...

#1 楼 @hjleochen 同问楼主 Ruby 里面远程慢速调用应该怎么异步化?线程还是?

#17 楼 @alsotang 之前说的那个后来没用 Ruby 了,如果只是 Ruby 项目那么线程应该可以的或者 select, epoll。如果在 Rails 里面似乎不不行的。 @est 说的 goliath 以及 em-synchrony 应该是挺好的解决方式.

#16 楼 @luikore 哈哈哈。是有这个感觉。

#18 楼 @hjleochen 如果不需要返回的远程调用,我自己写了个 hack,就是启动一个 nohup 的 curl 子进程。目前用来上传图片,效率刚刚的。超级稳定。而且自带重试啊有木有。

#18 楼 @hjleochen 在 controller 用 epoll 会不会显得太重啊

#19 楼 @est 当然如果不需要返回的这种 curl 或者原文说的任务队列都是可以解决的。 #20 楼 @alsotang controller 不能 epoll 方式吧。controller 还是要等待请求结果再进行响应的吧?

BTW:个人不喜欢 Form Objects 之类的东西,这不是 Java 的做法么,为什么呢?

"Putting too much logic in the model" "Functionality such as generating email notifications, interfacing to external services, converting to other data formats " 除了生成 Email 之外我稍微有点同意,其他放在 Model 里面真的有很大问题么?

职责不明确? 难道 Model 就是负责和数据库交道的?把自己转换为别的样子(converting to other data formats )展示给人家就不是自己的职责了?对外提供一个能力内部而使用别人的能力(external services),就 不能 是自己职责了?

文件太大、类太大? 其实文件行数多些应该不是非常大的问题,现在编辑器、IDE 这么好用。之前 C/C++ 的文件 2,3 万行也很正常的啊。

Form Objects、Service Objects 还有什么什么....越来越多的概念,越来越复杂的开发流程,这真的是你们想要的 Rails 么? 我觉得 Rails 已经非常复杂了,新手入门太难了。

如果当年我看到的 Rails 是这样子的,我觉得我应该是不会学的。当然我只是业余的写写 Ruby 和 Rails,以上只是我的一些疑问看法,欢迎指正。C 和 PHP 是世界上最好的语言 :)。

#21 楼 @hjleochen 提供一个 form 层主要方便跟 HTTP GET POST,特别是 HTML 表单打交道,少写很多代码。如果你没这个需求比如全 ajax 处理完当然可以不用 form 这一层。

@hjleochen @est 说来说去还是没能解答这个问题啊..大家不能讨论一下吗..

Blocking on calls to external services

@est 你是 V2EX 上那个 est 吗?

#1 楼 @hjleochen cc @alsotang 慢速外部请求调用这个情况太多了,我这边遇到两种 第一种类似查水表,解决方法是用 Sinatra 写了个服务,单独跑,这样就不阻塞网站的进程了,主要还是 Rails 目前还是多进程模型为主,IO 阻塞对于系统吞吐量影响还是挺大 第二种是业务中必须要同步调用外部 API,这种就不好说了,条件允许的情况可以变通业务逻辑,异步化(比如支付,增加支付处理中状态,支付的真实逻辑放在队列中实现),不能变通的,我目前还在思考的方案是启动两个 Unicorn master,其中一个专门负责复杂的业务逻辑(在 Nginx 中配置就好了)

#23 楼 @alsotang 我在隔壁是同一个 id。 #24 楼 @jasl 方法如你所说。goliath 可以跑任意 Rack 的 web app。goliath 又不会因为 IO wait 卡住整个进程,所以查水表的业务都用 Goliath 来单独跑,nginx 单独转发。

#25 楼 @est 恩,这种情况还是比较容易搞的,那种业务逻辑中要求同步调用的才是蛋疼...

#26 楼 @jasl 我会吐槽我厂之前码农用 http 相互调用这样的方式搞了一堆 web app 吗?

#27 楼 @est 你们这是 rpc 通信反模式吧。 cc @jasl IO 阻塞的问题,我以为一般是用线程来做,感觉用线程也还好吧?发多个请求然后 join 一下。

#28 楼 @alsotang 说的不是一回事,举个例子(因为具体情况比较复杂所以简化了下逻辑看上去可能不是那么合理):我们的生成订单的时候其中一步必须要调用一个外部 API,而同时用户需要立刻得知他创建订单的结果,以便进行后续的支付,所以这时候这个外部 API 必须同步的调用,恰好这个 API 又很耗时。这种情况下除非变通这个业务逻辑,否则没有任何技术手段来优化他。

#28 楼 @alsotang 哈哈。制造这玩意那逼还自豪得很。美名其曰云计算基础架构。张口闭口 Jeff Bezos 就是这样干的我们也得这样干。

#29 楼 @jasl 我跟你说说我现在工作时候的场景,我们现在工作都是用 node.js 的,在某个大厂的数据部门。有时候为了生成一个页面,要同时发出 10 个 io 请求,假如每个耗时 200ms 的,用 node.js 我们可以让 max time 不超过 200ms 太多。但如果用 ruby,顺序读取的话时间会变成 2000ms。 我想咨询的是,如果使用 ruby 的话,在这种场景下想并发地取数据的话,一般是用什么方式呢?

#29 楼 @jasl 不知道 fiber 能够解决这种问题么? 每次调用 api 的时候放在一个 fiber 里面,由代码来控制何时继续运行

#32 楼 @jayliud 不能,不是一回事,我说的这种情况也可以更抽象理解成:一个页面响应时间 必须 是数秒,如何优化。因为是必须,所以代码没有优化空间的。

#31 楼 @alsotang 我没在工作中遇到这种情况,但是 Fiber 和 Celluoid 应该是可以实现异步 IO 的,这个可以召唤 @luikore 来详细解答下,原来也是看他的帖子讲解异步 IO

#33 楼 @jasl 感觉你说的这个是业务逻辑层面的优化

Use too many gems 有争议,有测试保护,gem 比自造轮子靠谱

#35 楼 @alsotang 如果是我描述的这种情况,是的,因为在一些业务中长耗时的外部调用无法避免

mvc 都不允许太多 logic,那写到哪呢?

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