http://community.csdn.net/Expert/topic/3364/3364776.xml?temp=.1997949
其实也没说出什么对问题有帮助的话,相反,基本上是在争论中跑题。
让我大跌眼镜的是,这么基础的问题的竟然这么解释都不能理解,而且,这么缺乏常识还这么自信。看来,虽然说真理越辨越明,但辩论绝不是传播知识的好方法。
帖子乱七八糟扯了一堆,简单摘抄如下:
问:如何抽象业务接口
……需要将这里东西抽象成接口,以应对需求变化;我现在的问题:有什么方法抽象,才能形成比较好的接口。按照什么样的原则等。
m:
(1)尽量采用可扩展的接口!
(2)垂直方向上多层次的接口(两到三层的继承)!
(3)水平方向上不要铺得太广(同一层面的接口不要太多)!
(4)在接口的参数设置上要有灵活性
我:
象这样写,实在是不知所云,也不知是我的理解力的问题还是阅历有限。
m:
^_^,无语!继承和接口最小化不会没有听说过吧?我要向你学习了,你问这个问题我这样回答你说一点不懂?
(1)尽量采用可扩展的接口(不要限死接口的功能)
void DoSomething(const int nType)
{
swtich(nType)
{
case 1: TryDo1();break;
case 2: TryDo2();break;
........................
case N: TryDoN();break;
default:break;
}
}
你可能只实现了TryDo1,TryDo2,但是后面的功能要先留出来!!!!!
……(后面的解释不写也罢)
我:
从上面你的解释来看,好像你对面向对象的了解相当的浅。提到的预留接口和灵活性之类,基本上还停留在函数级别上,这种设计主要是协调程序间模块的关系的(且不论这几条设计原则是否成立),似乎对抽象业务接口没什么帮助。
m:
至于说到我说的这几条对抽象业务接口没有什么帮助,那也确实对,因为我没有看到过应该怎样抽象业务接口,但是这是设计接口的原则
j:
你这个叫过度设计,……
我们设计的原则是什么?越简单越好,你怎么能预知未来的客户需求呢?
m:
我听了这句话“我们设计的原则是什么?越简单越好,你怎么能预知未来的客户需求呢?”好惭愧哦,我觉得我已经不好开口说自己读了多少软件工程的书,原来书上说的都是错的!
我:
我们设计程序,不论采用了什么技术和设计方法,有一点是必然的:
你不可能在所有的向度提供最大程度的灵活性!!!
不论什么设计和方法,都必然在提供某种灵活的同时在其他方面导致复杂和修改成本……
不可能所有的方面提供灵活性,就要求我们作出取舍,那么什么样的取舍是合理的呢?当然是让结构与实际问题的结构相近,从而程序中刚性的地方在现实中也是全局和稳定的,而现实中灵活的部分在程序里也以局部和易于变化的方式实现。
如果现在我们打开两个程序,一个是学生的学籍管理,另一个是商品的订单管理。结果发现,两个程序看起来似乎一模一样……这就说明程序极其缺乏业务模型,同样也可以肯定程序在面对修改的时候很可能非常脆弱。比如学生原来是固定学时制的,现在变为了学分制;或者商品因为促销需要打折。程序员很可能会长大嘴巴,好像不认识客户一样的看着提出这种修改的人,好像在程序完成以后提出这样修改简直就是抢劫,却忘了再现实中这些情况是多么的普遍和顺理成章。因为他在设计程序的时候根本就没有想过在编一个学籍管理的软件,而只是要把一堆数据从这里搬到那里而已。
m:
假如要是像我说的那样把接口留下来,恐怕不会有这样的问题吧。……
//输入学生成绩,T_SCORE为学分,T_CREDITHOUR为学分
SetScore(float fNum, int nType = T_SCORE/*T_CREDITHOUR*/)
你说来说去我都不知道你是什么观点了,^_^
……
还有不要什么都走极端,我说预留接口,不是说要预留成千上万个,什么事情走了极端都是不好的。
我:
对于应对变化的问题,你当然可以预留接口啊,……问题是,我再重复一遍:
你不可能在所有的向度提供最大程度的灵活性!!!
就像你自己也说,不能走极端,不能留成千上万的接口。那么必然存在留什么不留什么的权衡。而单独说要预留,你又怎么知道什么时候是太多呢?
下面举一个面向对象用滥了的例子吧,……
现在要编写一个画图程序,把很多长方形画到屏幕上。聪明的程序员开始编程了,非常简单,他写了这么一段程序……:
for each rect do
Draw(rect.top, rect.left, rect.right, rect.bottom: Integer);
不过聪明的程序员很聪明,他猜到客户不会那么好说话,明天他就会要画三角形了,或者是5边型。稍稍想想,新的接口出来了:
Draw(SharpPoints: array of Point; PointNum: Integer);
……客户还可以要求画圆,椭圆,甚至圆角方形,这个不难,只要让接口“可扩展”就好了。
Draw(SharpPoints: array of Point; PointNum: Integer; SharpType: TSharpType);
……到此为止了么?聪明的程序员又想到,客户可能要画空心的和实心的两种图案,那么需要加入一个参数,可能要画不同粗细的图形,再加入线的粗细参数,还有不同的线的色彩,不同的填充色彩……
够了!聪明的程序员想到了那句名言:“不要什么都走极端”,看起来这个接口已经不错了,为什么还要加那些东西,那是走极端的做法。我相信客户不会想要什么不同粗细和颜色的图形的。于是,聪明的程序员就正式用这个接口作为应对客户需求变化的信心来源了。因为它是“可扩展”的。
m:
……你为什么画什么图形都用Draw一个接口呢?
多边形用Draw可以,对于有弧度的图形你用留个
DrawEx(POINT ptCenter, int radius, float fStartAngle=0, float fEndAngle=360);
接口不就行了?
对于你说的粗细颜色,在接口最后加上带有默认参数值的参数倒不是不可以啊?
DrawEx(POINT ptCenter, int radius,
float fStartAngle=0, float fEndAngle=360,
HPEN pen=DEFAULT_PEN, COLORREF clr=COLOR_BLACK);
也许你永远不需要用最后两个参数,但是一旦你需要用那是多么方便!
我:
呵呵,看了你的这个回答,说明你确实要看看面向对象的基础知识了……
看来的确不应该和你争论这么多,浪费你学习的时间,其实没什么好处。
---------------------------------------
无语中,和一个人讨论了半天接口,发现他根本不懂面向对象。虽然我一开始就发现他面向对象的认识比较浅,不过没想到如此浅,根本就没有了解或者全是误解。
鲁迅说他不惮于用最坏的居心推测国人,我发现有时候要不惮于用最差的水平推测与你讨论的人。
想起了舰船上著名的失重贴。