锁定老帖子 主题:我的酒窝
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-12-12
很不错的代码.
不过有几个问题.(字符串错误不说) private void checkInstanceType(final Object instance) { if (!cls.isInstance(instance)) 这个和 Implementor.proxy(SqlMapClient.class, new Object(){..} 是不是有点矛盾? MyMethod的用意好像是使得一些重载的方法亦可被intercept, 但这是必要的么? 1 如果只想intercept重载的方法中某一个方法? (可否设置一个flag?) 2 如果愿用继承的话,直接override Method中的equals似乎更简单,而且不用设置多层次的hashMap(这个会使语义更难懂) 那个sort是否只是为了debug? 没很详细研究,说错的地方,还望多谅解和指点. |
|
返回顶楼 | |
发表时间:2006-12-12
shaucle 写道 很不错的代码.
不过有几个问题.(字符串错误不说) private void checkInstanceType(final Object instance) { if (!cls.isInstance(instance)) 这个和 Implementor.proxy(SqlMapClient.class, new Object(){..} 是不是有点矛盾? MyMethod的用意好像是使得一些重载的方法亦可被intercept, 但这是必要的么? 1 如果只想intercept重载的方法中某一个方法? (可否设置一个flag?) 2 如果愿用继承的话,直接override Method中的equals似乎更简单,而且不用设置多层次的hashMap(这个会使语义更难懂) 那个sort是否只是为了debug? 没很详细研究,说错的地方,还望多谅解和指点. 1. checkInstanceType()判断的和proxy里面的那个不是一个class object。不矛盾。 2。MyMethod的作用有三个:缓存parameter types,不用每次生成一个数组对象;缓存depth,不用每次重新计算;支持Serializable。 3。sort是为了保证有重载的时候,f(String)被优先于f(Object)使用。比如: interface I { void f(String s); ... } class Impl { void f(Object s){...} void f(CharSequence s){...} } I impl = (I)proxy(I.class, new Impl()); impl.f("s");//calls Impl.f(CharSequence) 酱子就支持了parameter contravariance。加上返回值的covariance,基本比较duck typing了。 对了,哪里有字符串错误? |
|
返回顶楼 | |
发表时间:2006-12-13
哦,原来是你的构造方法public Implementor(Class implClass)把俺搞混了,(很容易把构造方法里的implClass和proxy方法里的asType混在一起)
为什么不把它(们)设为私有? 或简单的实现另一个包装类来提供对外的接口. 你的duck typing还不错,不过俺还去想想另一种实现方法,对于addMethod中的多层HashMap俺认为用对象模型可能更好. 350行,可能是帖错了吧 ^_^ |
|
返回顶楼 | |
发表时间:2006-12-13
taowen 写道 ajoo 写道 taowen 写道 nihongye 写道 就是重构起来麻烦点
这的确是一个问题。而且似乎没有什么好的解决办法做到重构安全。我能够看到的一个加强的地方是,验证new Object中每个方法是不是实现了要stub的接口或者具体类的方法。这样在改名了之后,可以fail fast,不会出莫名其妙的问题不知所以。 另外,不妨把酒窝当一个stub框架来做。 这样是可以,就是有点降低重用能力。我不能用一个Object给不同的interface做proxy么? 考虑可以在annotation上做文章。如果有一个@Override之类的annotation,那么就检查。 By default, every method is regarded as @Override, only the methods marked as @Aux will be escaped from the check. Otherwise, most of the methods have to be marked as @Override, which is not convinent. 几个原因让我对这个功能有点犹豫: 1。这个检查代价比较昂贵。基本上是现在要做的事情再多上一倍。 2。影响灵活性。比如你要是想从一个已有的类继承,然后用这个子类来动态实现接口,而基类里面已经有了额外多余的public method,怎么办?总不能跑到基类里面去加@Aux吧?或者现在基类没有多余方法,以后又突然增加了新的方法?我们一般作程序都有一个几乎是常识的假设:单单增加一个新的method,或者增加一个新的类,不会造成已有的代码失败。违反这个common sense有点怕怕。 3。对stub的情况,假设方法名字写错了,一运行unit test马上就会发现错误了。在方法里设置个断点也是比较有效的方法。 4。对在production code里面的动态implement,象场景二提到的那种,同样的,unit test必须要写的。而一旦有了unit test,错误也就会迅速体现出来了。 5。实现复杂度。需要实现一些额外的代码来做这件我还没拿定主意是否应当作或者怎么做最好的事。 6。在dimple的外围做这个type checker也不难。就是判断一个类里面的所有public method签名在另一个接口里面都有定义。这个判断代码甚至不需要依赖dimple现有的代码。如果真需要,做个add-on好了。 7。这个问题到底有多严重我还不是很清楚。如果用起来大家都觉得很担心把方法名字敲错,那么再想法子解决吧。ruby到处都是duck typing,也没看见大家很紧张的样子。 |
|
返回顶楼 | |
发表时间:2006-12-13
shaucle 写道 哦,原来是你的构造方法public Implementor(Class implClass)把俺搞混了,(很容易把构造方法里的implClass和proxy方法里的asType混在一起)
为什么不把它(们)设为私有? 或简单的实现另一个包装类来提供对外的接口. 你的duck typing还不错,不过俺还去想想另一种实现方法,对于addMethod中的多层HashMap俺认为用对象模型可能更好. 350行,可能是帖错了吧 ^_^ 不是贴错了。看来可能是javaeye的syntax highlight有bug。呵呵。召唤robbin。 |
|
返回顶楼 | |
发表时间:2006-12-13
ajoo 写道 shaucle 写道 哦,原来是你的构造方法public Implementor(Class implClass)把俺搞混了,(很容易把构造方法里的implClass和proxy方法里的asType混在一起)
为什么不把它(们)设为私有? 或简单的实现另一个包装类来提供对外的接口. 你的duck typing还不错,不过俺还去想想另一种实现方法,对于addMethod中的多层HashMap俺认为用对象模型可能更好. 350行,可能是帖错了吧 ^_^ 不是贴错了。看来可能是javaeye的syntax highlight有bug。呵呵。召唤robbin。 code highlight是用JS render出来的,太长的代码在不同的浏览器下面可能会不一样,我看着到挺正常的。 建议把代码打包作为帖子的附件上传。 |
|
返回顶楼 | |
发表时间:2006-12-13
引用 1。这个检查代价比较昂贵。基本上是现在要做的事情再多上一倍。 昂贵是指执行效率,占用空间,还是框架本身的代码行数?如果是框架作者的事情,那问题应该不大。做为一个feature排个序,有时间有必要就实现,没时间没必要就不实现。 引用 2。影响灵活性。比如你要是想从一个已有的类继承,然后用这个子类来动态实现接口,而基类里面已经有了额外多余的public method,怎么办?总不能跑到基类里面去加@Aux吧?或者现在基类没有多余方法,以后又突然增加了新的方法?我们一般作程序都有一个几乎是常识的假设:单单增加一个新的method,或者增加一个新的类,不会造成已有的代码失败。违反这个common sense有点怕怕。
那就区分对待好了。对于从Object继承下来的,明摆着就是一个同时实现一堆方法,但是又不想一次实现所有方法的语法糖。那就默认所有的方法都要改写要实现的接口的某个方法。对于从具体类集成下来的。那就不做检查。用@Override,让IDE给你检查好了。 引用 3。对stub的情况,假设方法名字写错了,一运行unit test马上就会发现错误了。在方法里设置个断点也是比较有效的方法。
是可以发现问题。只是加一点检查,可以fail fast。这和design by contract是一样的。没有那么多检查,代码该fail还是fail。只是多了一些检查,可以更快的失败,这样错误发生距离原因的距离就更近了一些。 引用 4。对在production code里面的动态implement,象场景二提到的那种,同样的,unit test必须要写的。而一旦有了unit test,错误也就会迅速体现出来了。 难道dimple不光是服务于测试的?在production里咋用? 引用 5。实现复杂度。需要实现一些额外的代码来做这件我还没拿定主意是否应当作或者怎么做最好的事。
实现复杂就先估计一下。列在TODO里。有时间再做。 引用 6。在dimple的外围做这个type checker也不难。就是判断一个类里面的所有public method签名在另一个接口里面都有定义。这个判断代码甚至不需要依赖dimple现有的代码。如果真需要,做个add-on好了。
最理想的是IDE的插件啦。Eclipse可以检查@Override,而且@Override的Retention Policy是Source级别的。如果有插件,也可以做到同样的便利程度。 引用 7。这个问题到底有多严重我还不是很清楚。如果用起来大家都觉得很担心把方法名字敲错,那么再想法子解决吧。ruby到处都是duck typing,也没看见大家很紧张的样子。
Ruby是Ruby嘛……到静态类型的语言中就该守静态类型的规矩,就应该利用静态类型带来的好处。在Ruby里还没法确定一个方法是不是存在于一个类中吧?只有调用了才知道(因为有method missing)。这就是Java的静态类型带来的束缚和好处。如果不利用,就浪费了。 |
|
返回顶楼 | |
发表时间:2006-12-13
1。这里主要是说效率。这个检查感觉几乎能占用整个处理逻辑的40%的时间。当然,我没有做过profile。如果dynamic proxy的创建需要的时间是大头的话,这个效率损失可能就可以忽略了。
2。是个方法。我本来是想判断isAnonymousClass()的。可惜这个判断只有到了java 5才存在。判断Object总感觉有点头疼医头的感觉,不够系统化。而且怎么判断?看这个类是不是super class==Object? 3。非常同意。要是我能找到100%满意的解决方法,早就做了。 4。dimple用来做拦截器亚。比如拦截Connection.close()方法阿。场景二描述的就是production code亚。 5。实现倒不太复杂。就是从400行变成450行的事情。 6。对亚。如果能通过ide来解决问题,那么在框架内部鼓捣就不是太必要了亚。所以我才犹豫呀。javaeye有eclipse插件的牛人么?强烈要求加入dimple! 7。不是尽量pragmatic嘛。如果dimple实用中并没有人抱怨这个问题,那么做它的动力就不大了嘛。 这个brainstorm挺好。继续。 ![]() |
|
返回顶楼 | |
发表时间:2006-12-13
啊,我还一直以为dimple是拿来做测试的stub用的呢。还是do one thing one time吧。这样可以支持得更好一些,顾虑也可以更少。你说的都在理。还是先用用吧,空说无益。
|
|
返回顶楼 | |
发表时间:2006-12-13
taowen 写道 啊,我还一直以为dimple是拿来做测试的stub用的呢。还是do one thing one time吧。这样可以支持得更好一些,顾虑也可以更少。你说的都在理。还是先用用吧,空说无益。
嗯。不过stub和拦截器是一样的用法阿。是一件事。只不过你能把它用在两种不同的地方罢了。 就象砖头可以用来造房子,也可以用来砸人。 |
|
返回顶楼 | |