• #50 楼 @woaigithub 就是 alias_method_chain 嘛,这个只是实现了 AOP 的部分功能而已。另一部分我在 4 楼已经描述了,这里才是真正的难点

  • #32 楼 @lgn21st 主要是不希望被外国的竞争对手获取到呗 毕竟底层是有软肋的 不过我觉得 声音应该是可以的公开的 :-) 当然 我不代表我公司啊

  • #32 楼 @lgn21st 呵 原来他这么有吸引力啊

  • 看上去我们 Team Leader 表现还行嘛 在同一场中仅低于 Terry 和 xdite,甚至高于第一场的 yedingding 到底是集中了全 Team 的智慧的 不过第一天的得分率实在太高了 确实比不过

  • Ruby Conference Taiwan at 2012年12月09日

    是啊 我 Team Leader 去了两天。做演讲的

  • 用 1 楼 @rociiu 的辦法就足夠了 配置文件,所有自動生成的文件 都必須遠離 git 庫。

  • #46 楼 @qhwa 怎么讲?

  • #39 楼 @luikore 那些语言也不是因为 AOP 而死掉吧。一门语言能流行的因素非常多,当然也包括运气。不能说一门语言因为有了什么特性而死掉了吧。

  • #40 楼 @googya 其实我写 JavaEE 只有几个月,作为学生作业,由于过于恶心而放弃了,不算 Java 阵营的吧。PHP 倒是玩了一年,也是学生时代。但是 Ruby 一年半了,而且是毕业后的第一份工作,算起来我算是比较红根苗正苦大仇深的 Ruby 程序员吧。

  • #37 楼 @nouse 哦 我见过,其实就是看了这个库让我觉得 Ruby 应该 native 的支持 AOP,因为语法实在过于复杂了,native 支持会好很多呢 不过这个库具体效果如何,我还没试过呢 等会尝试下:-)

  • #33 楼 @feitian124 二者不能类比,多态,接口是类型相关的问题,我说了 Ruby 和 Java 在这块地方有本质差异,所以 Java 的理论不适用于 Ruby。AOP 不是类型相关的问题,因此这不能证明 Ruby 不需要 AOP。

  • #31 楼 @feitian124 Ruby 是动态语言,Java 是静态语言,所以在涉及到类型的地方二者自然天差地远,但是这和 AOP 没什么关系啊。

  • #22 楼 @luikore 额 set_trace_func 还是有点缺陷,虽然能够完美实现在调用/返回一个匹配的方法前后执行一定的代码,但是似乎不能对参数进行匹配。此外我记得 AspectJ 能够修改被匹配方法的参数和返回值,还能抓住抛出的异常,还能拒绝调用被匹配的方法,这个不知道配合 alias 能不能实现

  • #26 楼 @nouse https://github.com/baccigalupi/aqua 这个??A Ruby Object Database?

  • #22 楼 @luikore 好吧 我承认这个方法经过封装能够达到我要的效果,除了 rdebug 没能 debug 进 proc 里面,不过已经差不多 OK 了,谢谢。

  • #13 楼 @jjym 都是小儿科的东西吧,Callback 的源码我都读过。ActiveSupport 不过是满足 Rails 框架自身使用需求而已,根本不能满足大型企业级系统更变态的需求。

  • #14 楼 @ywjno Java 式配置文件和注解不符合 Ruby 文化吧。

  • #16 楼 @Rei 功能确实挺恐怖的,所以才需要把可调试性考虑到范围内。

  • #17 楼 @luikore 我就是拿 Ruby 做大型系统的,需求各种变态,代码各种冗余+丑陋,很多代码甚至失去了可读性,而且很多流程直接涉及到钱,需要海量日志跟踪,这就是现实。如果都是小打小闹何须 Ruby,C 不也能搞定嘛? 你的一大堆抱怨归根结底是 Java 的问题,不是 AOP 的问题。我以前也遇到过类似的痛苦,但是我可没有怪罪到 AOP 上。 还有,我不觉得 AOP 是代码生成工具,它只是元编程的一种而已。

  • #10 楼 @jjym 求代码?

  • #9 楼 @fsword 额 其实 Java 程序员也不纠结有没有使用 Ruby。PHP 程序员也不纠结没有 Rails 这样的框架,那么 Ruby 和 Rails 是否也没有存在的必要?任何图灵完备的语言都可以解决任何问题,反正可以靠人力堆代码呢。

  • #7 楼 @luikore 日志很典型嘛。我们在讲 Transaction 的时候还不是都拿银行转帐做例子?

  • #5 楼 @luikore

    1. 那你如何解决我上面所述的大型系统的日志纪录问题呢?还是你认为大型 Ruby 系统是不存在的?
    2. 要解决一个问题就不得不更换语言不是很幽默嘛?
  • #3 楼 @Rei 说起来很简单 比如在一个复杂的系统中,我们有大量的重要方法现在需要纪录日志,比如纪录 stack,纪录传入参数,返回值等等。 传统的方法也就是最傻的办法是在这些方法前后增加 log 语句,但是这样做修改的规模可能非常大,并且有可能搜索不完全,比如那些要被动态 eval 那些字符串代码里可能也包含了这些重要方法,你用 grep 基本搜索不到,除此以外代码也不美观,也增加了耦合度(毕竟日志不是必需的逻辑,不该存在于重要的系统中)。直接在方法里面增加日志也不是很好的办法,虽然修改量很小,耦合度却增加了。 AOP 的解决方法是申请对某个类中的某些方法(可以用正则表达式匹配)进行代码注入,也就是在这个方法被执行前后增加所需的代码。 比如 UserShoppingSystem 和 EnterpriseShoppingSystem 里的 buy_products 和 sell_products 是重要方法,需要被纪录日志

    class UserShoppingSystem
      def buy_products(...)
         ...
      end
    
      def sell_products(...)
         ...
      end
    end
    
    class EnterpriseShoppingSystem
      def buy_products(...)
         ...
      end
    
      def sell_products(...)
         ...
      end
    end
    

    你当然可以遍历搜索代码,找到调用这些方法的地方来为其增加 log 语句,当然缺陷很明显,之前已经说了。 我现在用 AOP 代码(当然是我假象的)来解决这个问题

    aop /ShoppingSystem$/./_products$/
       around(method_name, params)
          log("#{method_name} #{params}")
          return_val = yield
          log("return: #{return_val}")
       end
    end
    

    只要上述代码可以被执行到(无论任何地方,没有执行先后次序的要求),以 ShoppingSystem 结尾的类中所有方法名以_products 结尾的方法,被调用前后都会先执行到相应的 AOP 代码。

    实现 AOP 的最大难度在于 Ruby 是可以动态添加和修改方法的,而且手段极多。Java 没有类似问题,所以简单。由于 AOP 并不是针对单一方法进行注入的,而是可以使用正则表达式对方法和参数进行匹配的。一个方法可能在 AOP 被申明后添加进去,如果仅仅只是添加在这个类本身,那还好点,有个 method_added 的 callback 可以用,但如果是添加在 Singleton 里呢,添加在 module 里然后 include 进去呢,在父类里添加呢?这些都不是容易实现的。 除此以外,由于 AOP 功能实在太强大,如果不注意有可能会产生非常奇怪的行为,引入 bug,因此需要支持良好的跟踪和调试。这些都不是一般的解决方案就能够解决的。

  • #1 楼 @Rei 还真的没有什么帮助 很多人把 AOP 想的太简单了我觉得 Ruby 实现 AOP 其实没有这么简单,AOP 本身非常灵活,Ruby 本身也非常灵活,把一个灵活的功能加入一个灵活的语言,这个难度不知道比加入到象 Java 这种死板语言中大多少倍。

    AOP 的解释我觉得问号课堂里面已经讲的很清楚了 你可以看看 http://mba.shengwushibie.com/itbook/BookChapter.asp?id=34730

  • Ruby 只是门语言 和云计算有什么关系啊

  • #16 楼 @knwang 对,但由于测试用例较多,单个用例代码较长,那我如何减少

    Adder.should_receive( :add).with(1,2,3)
      AbsoluteAdder.add(1,2,3)
    

    这段测试代码的冗余呢?

  • #13 楼 @knwang 是这样的一个测试,我写了一个 gem 用来包装另一个 gem,当我向 gem 的方法中传入预定的参数时,我 assert 那个被包装的 gem 的某个方法将收到某个参数,如果那个 gem 返回某些数据,assert 我的 gem 最终将返回某些数据。it 中的内容就是当传入简单的参数时,当传入较为复杂的参数时,当传入相当复杂的参数时等等。

  • 找到了这样一个办法

    describe ... do
      context ... do
        shared_examples ... do
          it ... do
            ...
          end
        end
    
        context ... do
          include_examples ... do
            let(:d1){...}
            let(:d2){...}
            let(:d3){...}
          end
        end
    
        context ... do
          include_examples ... do
            let(:d1){...}
            let(:d2){...}
            let(:d3){...}
          end
        end
      end
    end
    

    虽然还是没有完全达到预期,但是已经好多了

  • #8 楼 @knwang 不方便上真实代码啊 it 引号里面的内容很重要吗?