问题是这样的。
一个MyService类里面,有一个MyResponse runService()函数。这个runService函数会调用一个web service来得到MyResponse对象。这个MyResponse对象在runService()函数中被缓存,然后返回。
现在的目标是,在runService返回以前,先把MyResponse clone一下,然后如果MyResponse.getCensus().getSalary()返回的带有几毛几分的零钱,就把这个salary truncate成整数。
需求不难,一个直观的解决方案是:
CloneUtil是现成的。只要写一个SalaryTruncationUtil类就算完工了。
可是问题出现在,这个系统存在着一个ResponseManipulator接口(在另外一个package里面)。
ResponseManipulator的接口如下:
从签名上,可以看出一个ResponseManipulator负责操作一个MyResponse,然后返回一个新的(或者原来的MyResponse)对象。
同时,另外还现存一个ChainResponseManipulator类,它负责把若干个ResponseManipulator对象串起来:
以及一个已经写好的DeepCloneManipulator类来负责对一个Response对象的clone。
于是,我的pair决定这样写:
当然,还要实现一个TruncateSalaryManipulator。实现起来非常简单,就不写了。
我反对这个设计。虽然两者在代码量上不相伯仲,但是我认为这个设计无谓地增加复杂性,有一种绕着弯子解决简单问题的感觉。一个简单的顺序操作非要用一个特殊的接口和一个特殊的ChainResponseManipulator来实现。
一般来说,用接口是为了得到多态,降低耦合。可是在pair的代码里,该有的依赖一个没少,这个接口就显得意义寥寥。
而且这样做其实增大了MyService的依赖,因为凭空多了对ResponseManipulator和ChainResponseManipulator的依赖。
另外,ChainResponseManipulator对debug也不是非常友好,你单步运行每一个manipulator只能在ChainResponseManipulator的代码中,而不是MyService的代码中。
pair的观点有三:
1。看不出我的方案比用Manipulator有什么简单性的优势。
2。ChainResponseManipulator这一套设施已经存在,又不需要从头写。而且别人都是这么干的。
3。debug可以在每个不同的Manipulator类里面设置断点。
总而言之,没有达成一致意见。因为是pair主导键盘,所以最终pair的方案获胜。
今天在想怎么说服pair的时候,想了这么一个例子:
假设已经有一个StringAppender类:
那么在面对把两个对象连接成一个对象的时候,我们是:obj1.toString()+obj2.toString()呢?还是:new StringAppender(new Object[]{obj1, obj2}).toString()呢?
是不是已经有了的设施,为了保持一致性就必须要使用呢?即使有更简便的方法?
关于这个问题,你怎么看?
一个MyService类里面,有一个MyResponse runService()函数。这个runService函数会调用一个web service来得到MyResponse对象。这个MyResponse对象在runService()函数中被缓存,然后返回。
现在的目标是,在runService返回以前,先把MyResponse clone一下,然后如果MyResponse.getCensus().getSalary()返回的带有几毛几分的零钱,就把这个salary truncate成整数。
需求不难,一个直观的解决方案是:
java 代码
- MyResponse runService() {
- MyResponse response = call web service;
- cache response;
- response = (MyResponse)CloneUtil.cloneSerializable(response);
- SalaryTruncationUtil.truncateSalaryIfNecessary(response);
- return response;
- }
CloneUtil是现成的。只要写一个SalaryTruncationUtil类就算完工了。
可是问题出现在,这个系统存在着一个ResponseManipulator接口(在另外一个package里面)。
ResponseManipulator的接口如下:
java 代码
- public interface ResponseManipulator {
- MyResponse manipulate(MyResponse response);
- }
从签名上,可以看出一个ResponseManipulator负责操作一个MyResponse,然后返回一个新的(或者原来的MyResponse)对象。
同时,另外还现存一个ChainResponseManipulator类,它负责把若干个ResponseManipulator对象串起来:
java 代码
- public class ChainResponseManipulator implements ResponseManipulator {
- private ResponseManipulator[] manipulators;
- public MyResponse manipulate(MyResponse response){
- for(ResponseManipulator manipulator : manipulators) {
- response = manipulator.manipulate(response);
- }
- }
- }
于是,我的pair决定这样写:
java 代码
- MyResponse runService() {
- MyResponse response = call web service;
- cache response;
- response = getManipulator().manipulate(response);
- }
- ResponseMinipulator getManipulator() {
- return new ChainResponseManipulator(new ResponseManipulator[]{
- new DeepCloneManipulator(),
- new TruncateSalaryManipulator();
- });
- }
当然,还要实现一个TruncateSalaryManipulator。实现起来非常简单,就不写了。
我反对这个设计。虽然两者在代码量上不相伯仲,但是我认为这个设计无谓地增加复杂性,有一种绕着弯子解决简单问题的感觉。一个简单的顺序操作非要用一个特殊的接口和一个特殊的ChainResponseManipulator来实现。
一般来说,用接口是为了得到多态,降低耦合。可是在pair的代码里,该有的依赖一个没少,这个接口就显得意义寥寥。
而且这样做其实增大了MyService的依赖,因为凭空多了对ResponseManipulator和ChainResponseManipulator的依赖。
另外,ChainResponseManipulator对debug也不是非常友好,你单步运行每一个manipulator只能在ChainResponseManipulator的代码中,而不是MyService的代码中。
pair的观点有三:
1。看不出我的方案比用Manipulator有什么简单性的优势。
2。ChainResponseManipulator这一套设施已经存在,又不需要从头写。而且别人都是这么干的。
3。debug可以在每个不同的Manipulator类里面设置断点。
总而言之,没有达成一致意见。因为是pair主导键盘,所以最终pair的方案获胜。
今天在想怎么说服pair的时候,想了这么一个例子:
假设已经有一个StringAppender类:
java 代码
- class StringAppender {
- private Object[] objects;
- public String toString(){
- StringBuffer buf = new StringBuffer();
- for(Object obj : objects) {
- buf.append(obj);
- }
- return buf.toString();
- }
- }
是不是已经有了的设施,为了保持一致性就必须要使用呢?即使有更简便的方法?
关于这个问题,你怎么看?