• 现在可以关注人了 at April 23, 2015

    @huacnlee 是吗,那我有时间再去测试一下,也把 Ruby China 源码读一读。

  • 现在可以关注人了 at April 23, 2015

    @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 的经验么?想了解一下这方面的知识,但网上很多资料都比较初级和概念化。

  • 发布 / 订阅模式 at March 31, 2015

    @Victor 嗯,这个是 pub/sub 模式的特点,你总结的比我好,就不多说什么了。所以为了避免误会我才加上了 开发者自己也需要去一个一个排查才知道 。这点是我比较在意的。因为能够维护的前提在于“开发者知道自己在干什么”。

    最开始我去翻 Service Object 的目的很简单:

    1. 代码逻辑比较集中,方便查看。
    2. 修改比较简单,不用担心触发 side effect。

    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 代替。

  • 发布 / 订阅模式 at March 31, 2015

    赞一个,上次写 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 面对以上的情况有很大的好转,因为代码更集中,易于查看和修改。但这里有另外的问题:

    1. subscribe 到底在哪里写比较好?如果写在调用 OrderReview 的地方,是不是说明还有其他调用 OrderReview 的地方不需要 subscribe ClientListener?
    2. 如果 subscribe 的模块基本不变,写在 OrderReview 的 initialize 里面是不是更省事呢?不过既然所有 subscribe 都写到一起去了,说明本身逻辑是有一定强耦合的,这时候可以直接抽 Service Object 是不是更简单呢?

    比如上面的例子也可以改成:

    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 上的可用性。

  • Unicorn 里创建线程 at March 26, 2015

    @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 的思路去理解你就掉坑里去了。以下是我理解的各层作用。

    Route

    Ember 的核心理念。主要负责调用 model 层获取数据,调用 view 层渲染页面。起一个连接和控制各层的作用。Ember 认为对 web app 而言 url 是其核心,url 和应用程序状态是互相映射的。任何一方改变都会引起另一方改变。所以 Route 被设计成支持嵌套结构的有限状态机。但是它并不保存应用程序状态,那是由 Model/Service/Controller 负责的。Route 只是承上启下的管理者。

    如果对比 Rails 的概念的话,它就是 Rails 里的 Controller,所以就不用奇怪为什么推荐尽量把 action 写在 Route 里面了。

    Controller

    完全的 presenter,大部分情况用于保存和展示应用程序状态,所以这个对象被设计成 singleton 的。但也有少数情况不是 singleton 的(比如在 template 里用 render controller model)。因为设计容易让人迷惑,在 2.0 里会被 Routable Component 和 Service 代替。

    View

    类似 Backbone 的 View,整个 view 层的支撑架构。Ember 早期设计就是像 Backbone 看齐的。整个 app 的页面就是由 View 嵌套起来的。每个 template/helper 后面都有一个 View,甚至包括 if/else/each。只是 Ember 比较智能地管理了 View,大多数时候不需要操心这个。因为和 Component 在一起会有误用的情况,View 也会在 2.0 被废弃。有自定义 view 层逻辑请使用 Component。

    Component

    和 Web Component 同样功能的东西。设计某部分是照着 Web Component 看齐的(只是各种 hook 方法名称不同)。用于抽象可重用的 view 层组件,或者封装应用程序专有的 view 层逻辑。

    Template

    Handlebars 语法的模板。目前已经换成 HTMLBars。

    Helper

    和 Handlebars 里的 helper 差不多,Ember 加入了 data binding 的功能。一般用于扩展 template 的语法。也可以适用于不需要被页面标签封装的 view 层逻辑,比如 {{time-format}}。因为 2.0 的 Component 准备支持无标签的情况(RFC 里叫 Fragment),所以通常情况下用 Component 也足够了,除非需要扩展 template 语法。

    Service

    跟 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。因为:

    1. proc 中 return 直接作用于外层的 scope。这点在迭代器中很常用。
    2. proc 参数验证没 lambda 那么严格,这点也在迭代器中很常用。

    目前貌似没发现 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 谢谢!有时间来上海玩一定通知你。

  • @nightire 可惜了,我在武汉,不在上海。不然跟你面谈聊聊应该挺有收获的。

    @qsun 你最后的一个例子应该可以用 service 来做,数据放在 service 里,socket.io 通知 service 更新,然后 sevice 可以同时注入 dashboard 和 friend_count_check 这两个 route。

  • @nightire 补充一句,EmberConf 2015 不是快来了,是已经开完了。所有演讲资料都在 这里 。BTW ng-conf 也是最近,不知道开完了没有,里面一个关于 component 的演讲挺不错。

    我一般就看看 Twitter 和 Ember Weekly。一个每天了解下动态,一个每星期汇总。

  • 我喜欢酱紫的 Hash at March 12, 2015

    喜好正好相反。第一种:

    1. 可读性不好,看不清楚嵌套结构。
    2. 写起来累,修改一个 key 还要批量修改。

    其实 Hash 或者 Array 遵循一条规则 始终打逗号 即可。最坑爹的是 JavaScript 这种最后一个元素不能打逗号的,配合 ExtJS 这种拿 POJO 当配置的框架就是要人命。

  • 小规模和短期维护的项目,随便拿什么都行。如果你需要的是中等规模(或者更大)和需要至少维护 1 年的项目,Ember 是比较合适的选择,因为它确实做到了宣扬的 stability without stagnation。

    优点:

    1. 稳定,我指的稳定是“文档写明白的就必定没有意外情况” 。从 1.0 到现在我用的 1.9,bug 几乎没碰过几个。
    2. 升级几乎无痛,大部分时候把新版本扔进去,测几个页面就 ok。
    3. 因为以上两点,升级到 Ember 2.0 应该也会很顺利。感兴趣的可以看 Ember 2.0 RFC。BTW 2.0 六月份发布。
    4. 积极跟进和拥抱 ES 标准。很多人知道 Ember CLI 现在集成了 Babel.js。但 ES6 module 是 Ember 去年就开始用的(最早在 Ember App Kit,到现在差不多 1 年)。最近 EmberConf 刚开完,core team 在讨论 ES class 代替 Ember.Object 的可能性。
    5. Ember Inspector,谁用谁知道。
    6. Ember CLI 和 Ember addon,打造生态圈的基础。

    以上说的大部分都是和维护性和开发便利性相关。因为我觉得单纯的比功能,感兴趣的去各自的官网上看看就心里有数了。Ember, Angular, React 都不差,谁都有明星项目的例子,也不存在完全搞不定的弱点。开发者照自己 taste 选择就好。但是代码维护和开发效率直接影响每天的工作,至少我很重视这两点。

    不过说到这两点就不得不提生态圈。这点无可否认 Angular 做的更好。出名的几个 UI 库都能跟 Angular 很方便地集成,开源又减轻了开发者个人的维护成本。这点在 bootstrap 一个项目的时候可以有非常大的提速。Ember 有了 addon 之后也能找到一些,但毕竟时间不长,还需要积累。

    最后说几点 Angular 的:

    1. Angular 2 已经没有 AtScript 了,直接用 TypeScript。原因又造轮子被群众吐槽太多了。其实它需要的也就是 annotation(和另一个特性,忘了)。而 annotation 也可以自己用 JavaScript 写,就是繁琐一点。
    2. annotation 准备被 TC39 加入 ES 标准了。因为 Ember 也可能用到,两个 MVC 框架利益达成一致了。
    3. Google 承诺 Angular 1 到 2 有 migration path。也是被群众吐槽不得不改的结果。
    4. Angular 2 我从去年就开始听说(跟 Ember 2.0 RFC 发布时间差不多),到现在还是 alpha。真正开始项目肯定还是选 Angular 1 的。至于升级,这点见仁见智了。Google 目前给出的信息太少。
    5. Angular 2 的 route 内部使用的 Ember 的 route-recognizer
  • @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 框架,其实你需要的是:

    1. 一个构建 JSON 的 gem。
    2. 一个 JSON API 标准。

    对于前者,几个不错的 gem 是 RABLActiveModel::SerializersRoar

    对于后者,JSON APIHALCollection+JSON 等都是可以考虑的设计。或者你可以参考某一个写自己的设计。

  • 闭包的写法应该用哪种 at February 25, 2015

    两种写法没有什么差别,差别只在思路方面。

    如果只是 setTimeout 的情况,如 @lifuzho 所写的,setTimeout 可以给回调函数传参数,而回调函数本身就可以当做一个闭包隔离外部环境。所以不需要单独写闭包。

    如果是通用情况,我觉得第二种写法好一些。更通用和直观。不用关心 for 循环里面具体是什么逻辑。

    不过在循环中反复声明匿名函数会有额外内存开销,我记得有些检查工具比如 jshint 会提示的。抽成一个函数反复调用比较好。

    var asyncPrint = function(i) {
      setTimeout(function() {
        console.log(i);
      }, 100);
    }
    
    for (var i = 0; i < 10; i++) {
      asyncPrint(i);
    }
    
  • 《提问的智慧》 at February 24, 2015

    @liwei78 我说这话只是针对一些没经过自己思考就求答案的提问者,但往往这类问题总有大批的回答者。从短期来说,这是快速解决了别人的问题。但从长期来说,会让人失去独立思考的动力。所以不见得是帮助。

    论坛是讨论问题的地方,每个人都希望从讨论中获得他人的观点,弥补自己的不足。虽然论坛也有解决问题的功能,但无疑 StackOverflow 和 SegmentFault 是更合适的地方。因为它们给好的问题更多出头的机会,给回答者更多的奖励和权限,这点对提问者和回答者都更有帮助。

  • 《提问的智慧》 at February 23, 2015

    说句题外话,这种现象的另一个原因是一些无趣的问题也有很多回答者。可能这确实是出于好心,但也会让提问者觉得发个帖子求助才是最有效率的解决方式。有时候,人之恶在于好为人师。

  • 发现了个防身利器 at February 12, 2015

    有了这种书,发现学习一生也是挺容易的嘛

  • Rust 势头真猛,除了前两列之外都表现很好。难怪被人评价“像 C 一样快,像 Ruby 一样安全”。写底层的新贵啊。