Solstice的“朴实的C++设计”一帖中的OO问题的争吵似乎告一段落。在那个帖子里,有人说我的观点跳跃性太强,其实不然。一方面我不觉得有些话说得太明了有什么用。能懂的人点一下自然知道你说什么;不懂的人要说明白的话还要给他补最初级的概念课,那就冲淡了帖子的主题,一会儿就水得不知道跑到哪里去了。
另一方面有些话是故意卖了些破绽,不过Solstice同学为人还是很厚道的,基本上打不还手,骂不还口。从恶意地想,可能是已经看破了我的把戏,所以不向前,这样一方面保护了自己的弱点,一方面还显得很大度。所以很多手里暗藏的ZhaDan没有发出,只靠一块板砖了事,不免寥寥。
其实对于Solstice的所谓“纯对象”设计最大的漏洞,在于它不可能实现真正的动态类型判定。刨除以虚函数表为基础的多态,或者是不为我们倡导的指针强制类型转换,C++的其它东西,都是静态的,是编译器玩的技巧。用boost玩儿的再花,也不可能超越这个藩篱。所以这是所谓纯对象不可能任务之一。
其次,各位真的以为所谓的pImpl也好,C++多态也好,有任何的区别么?C++的虚函数表本质上也不过是编译器替你做的一点儿工作,在对象中插入了一个隐含的指针。pImpl本质上是个一模一样的东西。转换成汇编代码,除了pImpl模式多了一个函数跳转,除了虚函数表和pImpl指针使用的寄存器可能不同,其余的东西看不出有任何的区别。原因何在?pImpl也好,delegate也好,其实就是一种变通的继承关系,就是自己用编码做了一些编译器同样的事。从设计角度上来说,如果你使用UML设计了A同时继承B和C,而你又不想使用多继承,就完全可以把其中任一个转为delegate模式而不会产生任何问题。
再其次还是忍不住说一下,boost这个东东真的有那么好?C++的template和GP设计出来的东西,僵化程度绝对是强于OO设计的。OO至少还提供了多态这种和稀泥的把戏。在template库里,如果你想引入一些新的东西,90%以上你是需要另起炉灶的。这是个什么代价?读读boost有多少行就明白了。
而boost的本质,是预编译。也就是和宏同样的东西。除了加入了强类型支持,以及一些让人根本看不懂的编译错误之外,模板不能比宏提供更多的东西。C语言的高手甚至可以用宏定义自己的语言。从boost的实现上看模板离开宏还不能干太多的事情。
通过引入boost而降低程序复杂度,很有可能只是表面现象。因为你引入了一个超级大的模板库,也就是无数的外部依赖。在标准化以及被主流编译器支持之前,有些特性还是少用为好。而从C++标准委员会的恶劣历史来看,这个周期很有可能是我们还需要再等5年到10年。
我个人的感觉,C++的风格,如果写小型程序,各种流派各有所长。而大型工程,还是以“杂拌儿”的风格为好。OO的风格当然也可用。我认为需要谨记的是:template模式要慎用;类型继承3层或超过3层的要慎用;受其它模块调用的类最好用虚基类,Facade模式隔离内部细节。在确定是完全局部化的问题里,我认为就百无禁忌了。
关于OO设计更倾向于完美设计的问题,我没有考察过,所以不做评论。但是个人以为,追求“完美设计”应该是个软件工程上的问题,出现这个问题,更应该做检讨的是开发流程,而不是编码技术。
另一方面有些话是故意卖了些破绽,不过Solstice同学为人还是很厚道的,基本上打不还手,骂不还口。从恶意地想,可能是已经看破了我的把戏,所以不向前,这样一方面保护了自己的弱点,一方面还显得很大度。所以很多手里暗藏的ZhaDan没有发出,只靠一块板砖了事,不免寥寥。
其实对于Solstice的所谓“纯对象”设计最大的漏洞,在于它不可能实现真正的动态类型判定。刨除以虚函数表为基础的多态,或者是不为我们倡导的指针强制类型转换,C++的其它东西,都是静态的,是编译器玩的技巧。用boost玩儿的再花,也不可能超越这个藩篱。所以这是所谓纯对象不可能任务之一。
其次,各位真的以为所谓的pImpl也好,C++多态也好,有任何的区别么?C++的虚函数表本质上也不过是编译器替你做的一点儿工作,在对象中插入了一个隐含的指针。pImpl本质上是个一模一样的东西。转换成汇编代码,除了pImpl模式多了一个函数跳转,除了虚函数表和pImpl指针使用的寄存器可能不同,其余的东西看不出有任何的区别。原因何在?pImpl也好,delegate也好,其实就是一种变通的继承关系,就是自己用编码做了一些编译器同样的事。从设计角度上来说,如果你使用UML设计了A同时继承B和C,而你又不想使用多继承,就完全可以把其中任一个转为delegate模式而不会产生任何问题。
再其次还是忍不住说一下,boost这个东东真的有那么好?C++的template和GP设计出来的东西,僵化程度绝对是强于OO设计的。OO至少还提供了多态这种和稀泥的把戏。在template库里,如果你想引入一些新的东西,90%以上你是需要另起炉灶的。这是个什么代价?读读boost有多少行就明白了。
而boost的本质,是预编译。也就是和宏同样的东西。除了加入了强类型支持,以及一些让人根本看不懂的编译错误之外,模板不能比宏提供更多的东西。C语言的高手甚至可以用宏定义自己的语言。从boost的实现上看模板离开宏还不能干太多的事情。
通过引入boost而降低程序复杂度,很有可能只是表面现象。因为你引入了一个超级大的模板库,也就是无数的外部依赖。在标准化以及被主流编译器支持之前,有些特性还是少用为好。而从C++标准委员会的恶劣历史来看,这个周期很有可能是我们还需要再等5年到10年。
我个人的感觉,C++的风格,如果写小型程序,各种流派各有所长。而大型工程,还是以“杂拌儿”的风格为好。OO的风格当然也可用。我认为需要谨记的是:template模式要慎用;类型继承3层或超过3层的要慎用;受其它模块调用的类最好用虚基类,Facade模式隔离内部细节。在确定是完全局部化的问题里,我认为就百无禁忌了。
关于OO设计更倾向于完美设计的问题,我没有考察过,所以不做评论。但是个人以为,追求“完美设计”应该是个软件工程上的问题,出现这个问题,更应该做检讨的是开发流程,而不是编码技术。