软件设计的思考

最近回想之前写烂的程序,对软件设计方式进行了一些思考,经历了迷茫的过度之后,多少也有了一些认识,不管认识是否正确,人总是在思考中前进的。引用毕加索的话:画乃我思所获,非我见所得。

之前一家公司项目经理极度强调设计,他所言都是书上所讲,我无法辩驳,况且关注软件设计并不能说是坏事,但现今回想,感觉他所说的理论都过于理论,照本宣科而已,我不知道他是否有过成功或者失败的大型项目设计经验。软件的设计是一门实践课,不是读书能学来的能力。

关于面向对象,从开始学习面向对象开始,就被java的一切皆对象的思想误导了,c++不是java。所谓的面向过程还是面向对象,为了解决软件危机而引出的,但谁也不会认为一个扫雷的程序会引发软件危机,所以系统级别的面向对象才是真的面向对象,比如Linux内核,一切皆文件的思想,谁也不能否认这是非常完美的面向对象思想,可Linux内核全部用c语言实现,并没有一个C++所谓的“类”存在。所以正如软件工程所强调的,面向对象仅仅是一种思想,而不是某个具体的实现,如果写扫雷的时候其中充斥着面向对象,弄的一切皆对象,反而违背了面向对象的真正含义,这种面向对象的经验也不能用于大型项目。

之前公司的项目为了隔离ICE,几乎把每个应该是结构的地方都弄成了类,不止于此,还把每个这样的类抽象出接口,几乎一个存储操作也得走好几个接口才可实现,类过于繁杂,层次过深。虽然其中每个地方都符合软件设计的规范,也符合设计模式,但这简直是对面向对象的滥用,再好的理论也不能防止人滥用。

软件工程是一门大开大合的理论,为了解决软件生产随规模增大复杂度增大的问题,目的为了大规模项目具有可控性,犹如关羽的大刀,只有恢弘的战场上才可展现其威力,而对于被大刀划分出来的细微模块,犹豫巷战,还不如匕首来的轻巧,巷战时使用大刀,无非是自我束缚。一直在想,程序中没有类,没有继承,没有多态,那程序是不是就一定不是面向对象了呢?类似面向对象这种软件工程思想,类似于从战局上把握全局,而具体每一个功能实现,都是小小的战斗,战斗和战略本是两种不同的理论,能够从战略上做出很好决策的不一定也适用于战斗(失街亭的马谡就是个例子^_^)。所以把面向对象、各种设计模式用于某一个结构体的实现,完全是对软件工程的曲解。软件工程不是写几个小程序就能领悟得了的,如果有人给你讲面向对象,你先问他,设计过近百万行的项目么?

所以在全局上使用软件工程的相关理论把握项目不能失控,在某一细微功能实现上,应该尽力保持简洁,5行的代码远比50行的容易维护,不管你使用什么高深的理论都是如此。从细小的代码上应用“一切皆对象”,代码量将为了这些设施成倍增长,为后来人的维护造成极大的麻烦,但若从全局上划分面向对象,仅仅是一种划分方式,并不会对代码量造成多大影响,我想,这才符合软件工程的初衷,也符合“简单即完美”。Unix和Linux秉承这一思想,影响至今。

再来讨论C++这门语言,首先这门语言非常复杂,是对智力的考验,有些语法非常出色,极大简化了程序开发,但是他所造成的结果并不如他所期待的那样,C++是为了大型软件所设计的,开发小规模项目并不见得轻松,而大型软件所使用的面向对象却应是全局的划分,而C++却是从最细小的地方提供面向对象的语法支持,这不是与软件工程相违背么!而且C++这种机制还容易误导人们从最小的地方使用类的思想,而且,C++提供的机制是为了让防止别人滥用类,提供了一些私有机制,不过这种机制越来越复杂,反而更容易让人滥用。还是那句话,多好的理论和多好的机制都不能防止别人滥用,会C++语法的人很多,但是最终懂面向对象的人很少,滥用的人越来越多,这就是最好的证明,C++的各种语法都不能促人做出更好的设计!!!

而且C++一些看似很自动化的语法,恰恰使人麻痹,相反使用c虽然得自己“手工处理”,但却能警醒人们更加合理的使用。无怪乎Linux内核好几百万的代码全部使用纯c来开发,仍然保持着近乎完美的设计!c够轻巧也更不容易滥用。这里倒不是说哪种语言更好,只是说软件设计的思想。

再说局部开发的goto,任何教科书上都讲,不可使用goto,似乎每个人都有这样的意识不去用goto,但存在即合理,在c函数中如果有多处返回的错误处理部分,goto恰恰使代码更为简洁合理,这是goto的正确用法之一,如果不滥用goto,它能使代码更为清晰,比之前项目经理所说的do {} while(false) 更加合理,所以照本宣科的去学用什么不用什么,而不去想这么做的目的,将会带领项目最终走向地狱。在局部编码中,一切规则都是为了让人易懂易改,一切与之违背的即使经典理论也应摒弃。

在前项目经理推荐阅读《代码大全》,其中类和接口设计部分所言,类继承不可超过三层!否则徒增复杂度,他没有阅读此书么?

另外还有一些编码规范的解释,不过这点虽然重要但不是关键,最好的编码规范也不能保证你的代码易于理解(但最烂的规范却必定能使你的代码不能理解)。代码容不容易理解关键要看代码的组织方式,能不能达到“自说明”的程度。乍一看有板有眼但不能理解的代码比比皆是,无论做什么,都只有一个目的,让读代码的人“易读易改”。

最后感谢两个说我代码烂的人,第一个人说的很对,代码很烂,我自己都读不懂了,我也在迷茫思考,不过别人看不懂在于设计,那么复杂的设计即使我能写出来别人也不容易看懂,设计不是我的,我也没有太负责的去纠正这些,导致代码烂有多方面因素,我后来已经思考。但另一个说我代码烂的人,我也承认代码写的不好,因为我正在转型,但是他承认我的代码一眼就能看懂,也非常容易改,那还要奢求什么呢?难道非得如他一般一个小问题都继承多态扩增好几倍的代码量别人都不懂才算写的好么?请尊重软件工程,不要滥用。

另外,NC大并发是我第一个设计的项目,一天未离开公司,我都会根据我所体会到的经验,修正之前的设计以达完美,自己能够掌控一个项目,应该说是比较幸福的事情,也应为这个项目负全责!

有些东西,看过不如改过,改过不如写过。一个项目总是看但不参与修改,也只能懂个皮毛,修修改改对一些细节理解的比较清楚,如果一直参与开发项目,得到东西就会很多。一个项目在初期或者重构期,总是能很学到最多的东西;一旦这个项目成型,需要改改Bug,这时参与进去的人便不会学到很多构架方面的东西了;当项目已经完成,这时参与进去的开发人员学到的东西便少的可怜了。

当然不能否认,看一些优秀的代码也能学到很多东西,但往往这些东西不会对自己造成深刻的影响,除非自己曾经已经构建过相似的东西,以此引起共鸣,比如有apache经验再去看nginx,可以在很短的时间领悟其精髓。每次看开源的代码,都在想,如果看完了,抛弃这些东西,让我从头去写一个类似的东西,我能够完全构建出来么?开源软件看的比较多的除了以前工作中需要用的openvpn,就是nginx了,看过以后对它的架构有一定的感悟,但让我重写一个,想想都有点发怵,即使再多看几遍,照猫画虎的仿出来,也不明白为什么这么写比较好,为什么就不能用其他方法么,我只能看到作者的重点,却看不到作者所走的弯路。这也就是为什么代码只是项目的一部分,另一部分在于代码的演进,而人往往能看到代码的价值,却忽略代码演进的价值。代码可以很容易看到,代码演进即使有svn,git版本维护,也难让人理解精髓,这里的演进就是一个人的经验所在了。

Built with Hugo
主题 StackJimmy 设计