@huacnlee 是吗,那我有时间再去测试一下,也把 Ruby China 源码读一读。
@huacnlee 一个月之前做通知系统用过 message_bus,也是因为省事,方便跟 Rails 应用共享 session 信息。后来碰到一个问题是 Sidekiq 中发送通知没效果,还是切换回 Faye 了。这点不知道 Ruby China 有没有碰到过?
React 的概念确实深刻地影响到了 Angular 和 Ember。从这方面来说 React 的创新很有指导意义。
Angular 2.0 的 change detection 机制跟 React 非常类似。沿着 component tree 往下扫,结合 immutable data 会有很高的性能。
Ember 的 Glimmer Engine 也是借鉴的 Virtual Dom,不过优化成 diff value 而不是 diff dom 了。目前未完成状态下的 demo 性能还是不错的。虽然还没达到当初 HTMLBars demo 时几乎等同于 dom API 的性能。
@dfguo 请问你们有用 immutable.js 配合 React 的经验么?想了解一下这方面的知识,但网上很多资料都比较初级和概念化。
@Victor 嗯,这个是 pub/sub 模式的特点,你总结的比我好,就不多说什么了。所以为了避免误会我才加上了 开发者自己也需要去一个一个排查才知道 。这点是我比较在意的。因为能够维护的前提在于“开发者知道自己在干什么”。
最开始我去翻 Service Object 的目的很简单:
Wisper 是个好东西,作者也考虑很周到,代码写在 initializer 里面还特意提醒读者这样做是 threadsafe 的。前一篇回复是想说太过灵活的工具有可能造成一些新的 trivial choices,总结相关的最佳实践又要花一番功夫了。
@whitecrow 这个例子里 ClientListener 的用途是比较泛的。它就是个总的 callback,里面调用两个 Service Object。如果本来就是强耦合关系,我会选择直接把两个 Service Object 写进 OrderReview。还可以省一个中间类。
class ClientListener
def order_create(order)
Client::Charge.call(order)
Inventory::UpdateStock.call(order)
end
end
当然,在更加灵活多变的场景下单独抽一个类是必然的选择。只是抽象层次有时候也是跟代码易读性成反比的,然后也会造成维护成本提升。好的结构是为了更好地维护代码,但维护代码并不一定需要完美的解耦和层次。
@est 上面的帖子就是个例子,我是用在 tap 里面。目的嘛:
proc 被隐蔽地用在很多地方。如果有时候需要像 lambda 那样 return 的时候,可以用 next 代替。
赞一个,上次写 Service Object 的文章只是把 Wisper 简单地看了一下。楼主这篇文章又让我把 Wisper 过了一遍。
个人感觉这是一个可以用在很多地方的 gem,十分灵活。但也是这点反而导致我不知道怎么用了。比如全局 listeners。
我是看楼主的文章才知道全局 listeners Global Listeners 的。Wisper 官方的解释是方便按关注点切分模块(报表,日志,等)。除此之外还可以设置局部的 listeners。
order_review = Financial::OrderReview
order_review.subscribe(ClientListener.new)
order_review.execute
但这里隐藏的问题是,某些情况很难判断应该用全局 listeners 还是局部 listeners(这不仅仅是职责切分的问题)。并且两个都有各自的优缺点。
全局 listeners 只用在 initializer 里面定义,看起来集中化了,但对发布者而言,它完全不知道哪些类会响应消息,开发者自己也需要去一个一个排查才知道。我不知道在同步模式下订阅者抛出异常会不会导致发布者挂掉,如果是这样的话,那就跟把逻辑塞进 ActiveRecord callback 有一样的问题了:一块逻辑有多个看不见的依赖逻辑,所以改动时牵一发动全身。我猜测 Wisper 的全局 listeners 更适合搭配异步模式,它也支持订阅者在 Sidekiq 这类异步任务里跑。
局部 listeners 面对以上的情况有很大的好转,因为代码更集中,易于查看和修改。但这里有另外的问题:
比如上面的例子也可以改成:
class OrderReview
def self.execute
ClientListener.new.order_create
end
end
BTW 感觉 Wisper 这个 API 似乎把 subscribe 理解反了,怎么看都应该是 ClientListener subscribe OrderReview 才对。
以上想法是基于代码维护性的方面思考的。也仅仅是个人看法。希望楼主分享下自己在什么场景下使用 Wisper 这种 gem 的。也让大家开阔一下视野。
@est 实际证明对非 enumerator 的 block 也有效果。
mobile 开发用 Bootstrap 3 不大合适,主要是 UI 风格感觉有点不搭调。我知道的 mobile UI framework 里只有 Foundation for Apps 和 Ionic 是用 flexbox 做 grid 的。这也间接说明了 flexbox 在 mobile 上的可用性。
@ming_relax 根据你的情况,感觉找一个能结合 Rails 和 Redis 的 pub/sub 的 gem 是一个可行的方向。因为你需要 pub/sub 的机制来获取通知,这不适合用 job 或者定时任务去做。我大概用 "rails redis pub sub" 搜了下,有个方法 是把 redis 的代码放到 rake task 里面去。这个还比较可行。
或者你也可以放弃 redis 的 pub/sub,改用定时任务去不停轮询。即时度没那么高,但应该也够用。
或者尝试 JRuby?因为它没有 GIL 限制。不过踩坑估计更多。而且直接操作 thread 的代码维护成本比较高。edge case 也要注意。
@blacktulip The Road to Ember 2.0 是一个总览型的 RFC。部分特性的细节还在另外开 RFC 讨论,比如 Routeable Components RFC 。
@blacktulip Ember 虽然有很多名词和 Rails 是一样的,但如果照着 Rails 的思路去理解你就掉坑里去了。以下是我理解的各层作用。
Ember 的核心理念。主要负责调用 model 层获取数据,调用 view 层渲染页面。起一个连接和控制各层的作用。Ember 认为对 web app 而言 url 是其核心,url 和应用程序状态是互相映射的。任何一方改变都会引起另一方改变。所以 Route 被设计成支持嵌套结构的有限状态机。但是它并不保存应用程序状态,那是由 Model/Service/Controller 负责的。Route 只是承上启下的管理者。
如果对比 Rails 的概念的话,它就是 Rails 里的 Controller,所以就不用奇怪为什么推荐尽量把 action 写在 Route 里面了。
完全的 presenter,大部分情况用于保存和展示应用程序状态,所以这个对象被设计成 singleton 的。但也有少数情况不是 singleton 的(比如在 template 里用 render controller model)。因为设计容易让人迷惑,在 2.0 里会被 Routable Component 和 Service 代替。
类似 Backbone 的 View,整个 view 层的支撑架构。Ember 早期设计就是像 Backbone 看齐的。整个 app 的页面就是由 View 嵌套起来的。每个 template/helper 后面都有一个 View,甚至包括 if/else/each。只是 Ember 比较智能地管理了 View,大多数时候不需要操心这个。因为和 Component 在一起会有误用的情况,View 也会在 2.0 被废弃。有自定义 view 层逻辑请使用 Component。
和 Web Component 同样功能的东西。设计某部分是照着 Web Component 看齐的(只是各种 hook 方法名称不同)。用于抽象可重用的 view 层组件,或者封装应用程序专有的 view 层逻辑。
Handlebars 语法的模板。目前已经换成 HTMLBars。
和 Handlebars 里的 helper 差不多,Ember 加入了 data binding 的功能。一般用于扩展 template 的语法。也可以适用于不需要被页面标签封装的 view 层逻辑,比如 {{time-format}}。因为 2.0 的 Component 准备支持无标签的情况(RFC 里叫 Fragment),所以通常情况下用 Component 也足够了,除非需要扩展 template 语法。
跟 AngularJS 里的 Service 一样的概念。特点是 singleton。各种不适合放在 Route 和 Component 的逻辑都应该放在这里。用途比较灵活。其实它就是 Ember Object + inject API,没什么特殊的。
以上概念确实很多,这也是 Ember 学习成本比较高的原因之一。但 Ember 现在为了简化概念,已经计划把一些东西在 2.0 废弃掉了,所以想学 Ember 的话,着重在 Route, Component, Service 就行。
BTW 其实我还没提 Ember Data 的 Store, Model, Adapter, Serializer, Transform 呢……
虽然自己写代码时大多数会使用 lambda,但 Ruby 内建的方法(比如迭代器)都是用的 proc。因为:
目前貌似没发现 Ruby 内建方法使用 lambda 的情况。
一个有意思的地方是,因为上面的原因,proc 被隐蔽地用在很多地方。如果有时候需要像 lambda 那样 return 的时候,可以用 next
代替。比如:
user.save.tap do |success|
next unless success
send_notification
write_log
end
支持一个,回头看 PPT 做的挺好,可惜上次有事没去。
我现在的项目,测试比较惨,就不贴了…… 重构是为了更低成本地持续改进项目,而不是为了更优美的结构。如果你 自信已经搞懂了项目已有功能,并且有更好的办法让未来的功能实现起来更轻松 ,就小块小块地重构。不然碰到新功能或者要修复 bug,就只能沿用已有代码的逻辑,不停的打补丁,最后可维护性会越来越差。
+----------------------+-------+-------+---------+---------+-----+-------+
| Name | Lines | LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers | 2523 | 2010 | 50 | 263 | 5 | 5 |
| Helpers | 35 | 31 | 0 | 5 | 0 | 4 |
| Models | 2537 | 1938 | 39 | 197 | 5 | 7 |
| Mailers | 175 | 141 | 8 | 24 | 3 | 3 |
| Javascripts | 18302 | 13417 | 0 | 1995 | 0 | 4 |
@matrix_bin 马克飞象就是干这个事情的。可以说我是因为马克飞象才用 Evernote 的。
@blacktulip 国外资料 Ember 也不少,不管是 Google 的还是 SO 的,教程更多。不过哪个框架的教程都只对初学者有些帮助。国内就不说了,风吹过来什么种子就发什么芽。
@nightire 谢谢!有时间来上海玩一定通知你。
喜好正好相反。第一种:
其实 Hash 或者 Array 遵循一条规则 始终打逗号 即可。最坑爹的是 JavaScript 这种最后一个元素不能打逗号的,配合 ExtJS 这种拿 POJO 当配置的框架就是要人命。
小规模和短期维护的项目,随便拿什么都行。如果你需要的是中等规模(或者更大)和需要至少维护 1 年的项目,Ember 是比较合适的选择,因为它确实做到了宣扬的 stability without stagnation。
优点:
Ember.Object
的可能性。以上说的大部分都是和维护性和开发便利性相关。因为我觉得单纯的比功能,感兴趣的去各自的官网上看看就心里有数了。Ember, Angular, React 都不差,谁都有明星项目的例子,也不存在完全搞不定的弱点。开发者照自己 taste 选择就好。但是代码维护和开发效率直接影响每天的工作,至少我很重视这两点。
不过说到这两点就不得不提生态圈。这点无可否认 Angular 做的更好。出名的几个 UI 库都能跟 Angular 很方便地集成,开源又减轻了开发者个人的维护成本。这点在 bootstrap 一个项目的时候可以有非常大的提速。Ember 有了 addon 之后也能找到一些,但毕竟时间不长,还需要积累。
最后说几点 Angular 的:
@spacewander @mogodb Babel.js 不是仅仅是 compile 到 ES5 的,最低可以到 ES3,基本可以达到浏览器通用。至于 IE6 和 IE7 …… 管他们干嘛…… 过多考虑向后兼容,就别抱怨客户为什么死活不升级。
这种 monolith 项目不是谁都能驾驭得了的,看他们一堆 "We build our own XXX" ,也不是所有公司都有这种能力。
需要有后台人工操作,说明至少有基本的 CRUD,而且需要 web page。这种情况下还是建议 Rails。API 方面用 Rails 自带的 jbuilder 返回 JSON 就行。
但如果你需要认真设计 API,相比用什么 web 框架,其实你需要的是:
对于前者,几个不错的 gem 是 RABL,ActiveModel::Serializers, Roar
对于后者,JSON API,HAL,Collection+JSON 等都是可以考虑的设计。或者你可以参考某一个写自己的设计。
两种写法没有什么差别,差别只在思路方面。
如果只是 setTimeout 的情况,如 @lifuzho 所写的,setTimeout 可以给回调函数传参数,而回调函数本身就可以当做一个闭包隔离外部环境。所以不需要单独写闭包。
如果是通用情况,我觉得第二种写法好一些。更通用和直观。不用关心 for 循环里面具体是什么逻辑。
不过在循环中反复声明匿名函数会有额外内存开销,我记得有些检查工具比如 jshint 会提示的。抽成一个函数反复调用比较好。
var asyncPrint = function(i) {
setTimeout(function() {
console.log(i);
}, 100);
}
for (var i = 0; i < 10; i++) {
asyncPrint(i);
}
@liwei78 我说这话只是针对一些没经过自己思考就求答案的提问者,但往往这类问题总有大批的回答者。从短期来说,这是快速解决了别人的问题。但从长期来说,会让人失去独立思考的动力。所以不见得是帮助。
论坛是讨论问题的地方,每个人都希望从讨论中获得他人的观点,弥补自己的不足。虽然论坛也有解决问题的功能,但无疑 StackOverflow 和 SegmentFault 是更合适的地方。因为它们给好的问题更多出头的机会,给回答者更多的奖励和权限,这点对提问者和回答者都更有帮助。
说句题外话,这种现象的另一个原因是一些无趣的问题也有很多回答者。可能这确实是出于好心,但也会让提问者觉得发个帖子求助才是最有效率的解决方式。有时候,人之恶在于好为人师。
有了这种书,发现学习一生也是挺容易的嘛
Rust 势头真猛,除了前两列之外都表现很好。难怪被人评价“像 C 一样快,像 Ruby 一样安全”。写底层的新贵啊。