收藏 分销(赏)

大道至简软件工程实践者的思想.docx

上传人:xrp****65 文档编号:8886307 上传时间:2025-03-06 格式:DOCX 页数:81 大小:581.71KB 下载积分:10 金币
下载 相关 举报
大道至简软件工程实践者的思想.docx_第1页
第1页 / 共81页
大道至简软件工程实践者的思想.docx_第2页
第2页 / 共81页


点击查看更多>>
资源描述
大道至简 ——软件工程实践者的思想 周爱民(Aimingoo) 著 序 2004年11月初爱民(Aimingoo)第一次把他的书稿给我,我翻看了一下,第一反应讲的是感想。这不错,在技术界就是需要有真正实践经验的专家把他的思考和心得与我们分享。Aimingoo在Delphi领域颇有名气,其技术钻研的深度直达系统核心层,从其著作《Delphi源代码分析》可见一斑。不过接下来第二反应就是太薄了,能不能加厚啊。比如说这些感悟都是有其来源的,可以把实际案例啊,背景故事啊都加上。不然太薄了,出版社没有办法出版啊。——国家对于出版的书号是有严格控制的,所以书号是有成本的。一本讲技术高端的图书销量肯定是有限的,以现实情况而言,如果很薄定价就只能比较低,成本无法回收。而且内容只是心得,没有案例,读起来也很硬,对读者的要求也很高,销量可能就更少了。 爱民听完我的意见,还是坚持这本书就是这样的风格。出厚书违背了他的本意,要不然怎么叫“大道至简”。书稿在2005年3月杀青后,我从7月开始在《程序员》上陆续选择其中的三章发表,看看读者的反馈。不过限于篇幅,删掉了一些内容,不能完整体现出作者系统思考的脉络,也比较遗憾。 2005年11月爱民跟我讨论到即使没有出版社愿意出版印刷,也要把他的作品用电子版问世,并邀我作序。我十分感慨,在这个浮躁功利的社会,难得还有这样的朋友。 现在,我又仔细从头到尾读了一遍。很多作者写书是为厚而厚,大部分内容都是水分,作者原创经验精华只有很少,甚至没有。而这本书是作者从事十年开发工作的总结,虽然不厚,却闪烁着独立思考的光芒。 世界“虽变化万端,而理为一贯。”作者在软件开发一线浸淫近十年,回头思考何为开发的本源?这些理论、方法的本质为何?粗粗一看,这些道理稀松平常,专家教授无数著作早就谈过,还用作者来写吗?其实不然,理论都是从实践而来,但我们学习软件开发的时候,是先掌握这些专家总结的果实,而不是探求本源,所谓“知其然而不知其所以然”。这些道理看似都知道,但却没有真正体会上身,在实践中最重要的去应用这些道理,而不是方法。 大多数人看书都希望学到一些招数、方法,能尽快在工作中用上,这是不错。但要想真正达到更高境界,就必须明白背后的道理。真正的专家是从根上解决问题的,所以大物理学家杨振宁在北京大学针对本科生讲物理学,讲得深入浅出,大受欢迎,就是因为杨先生可以从历史本源来剖析物理定律公式。 只有招数,不明道理,碰到变化的情况,就束手无策了。而在软件开发中,每个团队、每个项目都不是尽然相同的。明白道理,才能知变通之道。 这本小书不是一本教你项目管理,软件工程或者编程技巧的书籍,他是一本闪烁思考光芒的技术散文集,我衷心祝愿这本书的读者,能把这本书当作一位朋友的思考,一位朋友的总结,来参照自身,这样就会有收获,有想法了。 我也和爱民建议,这本书的很多主题还可以展开,无论是批评,还是讨论,只要有兴趣的朋友,可以给爱民,我或者《程序员》杂志社写信,我们诚恳邀请各位来共同思考,共同把实践经验与大家分享,这样意义也就更大了。 期望大家的参与,谢谢。 蒋涛 2005.11月 jiangtao@ 注:关于书的序的讨论,参见附录之一。 电子版发布前言 我终于决定发布这本书的电子版了。 完成这本书的时候,我已经在这个行业里做了十年了。这十年来,我对自己的经历做过两次回顾。第一次是关于技术的,这造就了那本《Delphi源代码分析》,是讨论开发的技术和方法细节的。第二次就催生了这本《大道至简》,讨论的则是工程、管理中的思想。 我其实是很希望这本书能放在读者的书架案头,而不是放在电脑的某一个目录中。因为它应当是一本可以阅读和品味的书,而不是在电脑中备查的技术资料。 然而,我在决定担任这家公司的软件架构师的同时,我就意识到,我没有足够的精力来运作这本书。——我的意思是如果要把他做成纸质的书的话,我没有足够的精力。 出版商是要寻求利润的。——于此,我一早就知道。但我从来不知道:到底一本书簿一点或者厚一点,哪个会让出版商更有利润。 我只想写一本“阐明软件工程的思想核心”的书。这本书要很容易就读明白,还要很容易就想通,还要很容易就知道:工程其实很简单,只是大家把它做复杂了。 然而问题是:我把它写得太简单了,以至于只写了110页,就没有必要再写下去了。 我当然可以把一本书写得很复杂,或者很厚。这很容易,就如做Coder一样:把代码写烂或者写乱都很容易,要想写得简洁却远非易事。 代码写得太简洁,老板会认为你在偷懒;书写得太薄,出版社就不愿意出。我看来是忘掉了侯捷先生说过的“买书如买纸”,以书的厚薄来论价值的故事。 忘掉了就忘掉吧。好的一面是现在书变成了电子版,大家终于可以读到它了。不好的呢?我想大概不要钱的东西很难得到珍视吧:如果下载这本书只是因为收集,而不是阅读,那会是让我感到比讨论“买书如买纸”这样的事更为难过的。 好吧。希望你能象对待纸质书籍那样来阅读这本《大道至简》。放心,我并不介意你把它打印出来放在床头。 补充声明:我保留在传统媒体(书籍、杂志)上刊载、出版本书的权利。但允许任何人在网络上非商业性地、自由地、不加修改地传播这本书的电子版本。 周爱民 2005年10月14日 mailto:aim@ 目录 1. 编程的精义 1. 编程的精义·······················································11 2. 会或者不会写程序·············································13 3. 程序 = 算法 + 结构········································14 4. 语言··································································16 5. 在没有工程的时代·············································16 2. 是懒人造就了方法 1. 是懒人造就了方法·············································18 2. 一百万行代码是可以写在一个文件里的············20 3. 你桌上的书是乱的吗·········································23 4. 我的第一次思考:程序=算法+结构+方法··········25 3. 团队缺乏的不只是管理 1. 三个人的团队····················································29 2. 做项目 = 死亡游戏 ?·······································31 3. 做ISO质量体系的教训·····································33 4. 谁动摇了你的制度?·········································36 5. “那我们就开始开发吧”··································38 6. 组织的学问:角色·············································39 7. 跟随蚂蚁。但不要栽进蚂蚁洞里。···················42 8. “什么是增值税发票?”··································44 4. 流于形式的沟通 1. 客户不会用C,难道就会用UML吗?··············48 2. 项目文档真的可以用甲骨文来写·······················50 3. 最简沟通···························································53 4. 为不存在的角色留下沟通的渠道·······················57 5. 流于形式的沟通················································60 5. 失败的过程也是过程 1. 做过程不是做工程·············································63 2. 做过场·······························································65 3. 实现,才是目的················································65 4. 过程不是死模型················································66 5. “刻鹄类鹜”与“画虎类狗”··························69 6. 工程不是做的,是组织的··································71 6. 从编程到工程 1. 语言只是工具····················································73 2. 程序··································································75 3. 方法··································································75 4. 过程··································································76 5. 工程··································································78 6. 组织··································································80 7. BOSS·································································82 8. 上帝之手···························································84 7. 现实中的软件工程 1. 大公司手中的算盘·············································87 2. 回到工程的关键点·············································92 3. 思考项目成本的经理·········································94 4. 审视AOP··························································97 5. 审视MDA························································100 8. 是思考还是思想 1. 软件工程三个要素的价值·································103 2. 其实RUP是一个杂物箱···································104 3. UML与甲骨文之间的异同·······························105 4. 经营者离开发者很远,反之亦然······················106 5. 矛盾:实现目标与保障质量·····························107 6. 枝节与细节······················································108 7. 灵活的软件工程···············································110 第1章 编程的精义 “虽我之死,有子存焉;子又生孙,孙又生子;子又有子,子又有孙。子子孙孙,无穷匮也。而山不加增,何苦而不平?” ——《愚公移山》,《列子·汤问篇》 1. 编程的精义 仅仅就编程序来说,实在是一件很简单的事,甚至可以说是一件劳力活。两千年前的寓言中,已经成就了一位工程名家:愚公。在这位名家的身上,浓缩了项目组织者、团队经理、编程人员、技术分析师等众多角色的优秀素质。他的出现,远远早于计算机发展的历史,甚至早于一些西方国家的文明史。 汤问篇中所述的愚公移山这一事件,我们看到了原始需求的产生: “惩山北之塞,出入之迂” 我们也看到了项目沟通的基本方式: “聚室而谋曰” 然后,我们看到愚公确定了一个项目的目标: “毕力平险,指通豫南,达于汉阴” 并通过研讨,择定了一个井然有序的、可以实现的技术方案: “扣石垦壤,箕畚运于渤海之尾” 在这个项目中,动用了三名技术人员和一名工程管理人员: “(愚公)率子孙荷担者三夫” 并获得了一名力量较弱,但满富工作激情的外协: “邻人京城氏之孀妻,有遗男,始龀,跳往助之” 基本上,这已经描述了“愚公移山”整个工程的概况。接下来,我们应该注意到愚公作为编程人员的基本素质。在与“河曲智叟”的对答中,他叙述了整个工程的实现程序: “虽我之死,有子存焉”,这里描述了可能存在的分支结构,即“IF”条件判断。 “子又生孙,孙又生子;⋯⋯子子孙孙,无穷匮也”,这里描述了完成这个工程所必须的循环结构。 作为优秀的程序分析师,愚公论述了这个循环的可行性:由于“山不加增”,所以条件“山平”必将成立(“何苦而不平”),所以这不会是一个死循环。 在愚公的论述中,我们看到了编程的根本:顺序、分支和循环。庞大若“愚公移山”这样的工程,都是可以通过这样简单的编程来实现的。这,就是编程的精义了。 2. 会或者不会写程序的问题 我经常会被人问到“(我)能不能学会写程序”这样的问题。 这个问题由来以久。上溯七、八年,程序员还是少有人从事的职业。听说的人少,真正了解的人也不多。而当一个程序软件被装在电脑里并开始运行时,人们便开始惊讶于程序员的厉害。所以“能不能学会写程序”甚至成了一些人对自己的智力考评,所以便有人向我这样发问。 愚公都能明白的编程精义,那些向我发问的智叟们又怎么会不明白呢? 所以除了先天智障或后天懒惰者,都是可以学会写程序的。如果你能确信,自己知道在早上起床后需要: 如果天冷则先穿衣服后洗漱 如果天热则可反之 日复一日直到死亡 那么你就可以开始编程了。甚至,如果你认为以下条件成立: 如果有类似于生病、不能行动、以及意外的紧急事件,则当日可以略过 那么你就可以开始向设计师发展。因为你已经具备了一项常人不具备的基本素质:折衷。 3. 程序 = 算法 + 结构 编程作为一种行为,只需要知道其逻辑方法就可以了。所谓编程实际上是把一件事情交给计算机去做,你认为这件事该如何做,就用“程序语言”的形式描述给计算机。如果你原本就不明白如何去做,那么你也不要期望计算机去理解你想要做什么。 所以编程的第一要务是先把事情分析清楚,事件先后的逻辑关系和依赖关系搞清楚,然后再去代码实现。一接到任务就开始Coding的程序员,通常就是加班最多的程序员。 记住:积极工作和勤于思考都要占时间。 第一个完成关于编程本质的思考的人,提出了一个公式“程序 = 算法 + 结构”。这个公式的精彩之处,在于它没有任何的地方提及到Code。甚至可以说,在这个公式里,代码是不存在的。 存在的只是思想。 算法是对一个程序的逻辑实现的描述,而结构是逻辑实现所依附的数据实体。只要开发人员将这个程序的算法设计出来了,把结构描述出来了,那么程序就已经定型了。剩下的事,简而言之,就是劳力活。 在计算机专业所学的课程中,同时讲述算法和结构的,是“数据结构”。现在,你放下手边这本书,再去读读被你扔到不知哪个角落的《数据结构》,你仔细看看,在所有的算法描述中,有且仅有三种执行逻辑:顺序、分支和循环。简单若顺序表,复杂如树、图,它们的算法都是用上面这三种执行逻辑来描述的。 4. 语言 当你熟悉了一门语言之后,你会发现,编程语言只有喜欢与不喜欢的问题,没有会不会的问题。任何的一门语言,你都可以在两周内掌握并开始熟练编程。因为任何的一门语言,他们的底层函数库都是那么的相似,而他们API都是那样的依赖于操作系统。A语言里有的,B语言里也基本都有。 通常而言,语言的差别主要表现在适用范围上。一些语言适合做数值处理,小数点后可以精确到原子级,而小数点前则可以表达到宇宙之无穷;另一些语言则适合做图形处理,它的底层函数库比其它语言可以快上十倍或数十倍;还有一些语言则适合于做网页,要用它来做一个通讯薄软件都将是史无前人的挑战。 成天讨论这门语言好,或者那门语言坏的人,甚至是可悲的。不但是悲其一叶障目,更要悲叹于那种大愚若智的自得心态。 5. 在没有工程的时代 在没有工程的时代,上面所说的就是一个程序员的全部。他们掌握了一门语言,懂得了一些生活中最常见的逻辑,他们用程序的方式思考和学习了一些算法,并根据前人的经验,把这些算法跑在了一些数据结构之上,最后,我们就看到了他们写的程序。 在没有工程的时代,出现了非常非常多的人物。其中算法大师,有游戏大师,有语言大师,有挣钱的大师⋯⋯ 唯独,没有工程大师。嗯,可以理解嘛,那是没有工程的时代。好蛮荒,好远古的。 第2章 是懒人造就了方法 “僰蘭道有蜀王兵,亦有神作大滩江中。其崖崭峻不可破,(冰)乃积薪烧之。” ——《华阳国志》 1. 是懒人造就了方法 战国时期的李冰凿了一座山。 史记中说是“蜀守冰凿离堆”,是说李冰在成都的时候凿出了离堆。一说是李冰将都江堰附近的玉垒山凿了一个大口子,叫宝瓶口,而凿的石头就堆成了离堆。另一说,则是李的确是凿了一座“(溷)崖”,但是是在沫水,亦即是今天的大渡河。 在哪里凿的山,是史学家都说不清楚的事。但的确凿了一座山,而且方法是“(因)其崖崭峻不可破,(冰)乃积薪烧之”。 我们已经看到事物的进化了。同是战国时代,《列子·汤问篇》里的愚公就要“碎石击壤”,而李冰就已经懂得“积薪烧之”了。 会有人说愚公是“碎石”,并没有说他“碎石”的方法究竟是“斧钺以凿之”,还是“积薪以烧之”。但想想那个时代,如果有人懂得了烧石头这个方法,哪能不立即载文志之,永世传承。 再说了,愚公嘛。愚者怎么会呢?这还需要分析吗?需要吗? 所以愚公会凿,而李冰会烧。那李冰又是为什么会用“烧”这种方法来碎石的呢?如果李冰也象愚公那样日复一日地督促着他的团队凿石开山,那他一定没有时间来学习、寻找或者观察,当然也不会发现“烧”这种方法可以加快工程进度,使得一大座山短时间就被哗啦哗啦地给“碎”掉了。 要知道李冰的团队可是成百上千人,要修堰筑坝,还要“凿离堆”,当然还要吃喝啦撒睡。所以李冰如果忙起来的话,他必然是“受命以来,夙夜忧叹”,必然食难下咽,睡无安枕。反之,李冰一定是个闲人,可以闲到没事去看火能不能把石头烧爆。 这么大个工程里,如果有一个人会闲到看火烧石头,那他一定很懒。那么多事堆着不去做,去看烧石头,你说他不是懒是什么。 正是一个懒人造就了“烧石头”这个“碎石”的方法。愚公太勤快了,勤快得今天可以比昨天多凿一倍的石头。或者在愚公的项目计划案的首页里就写着朱笔大字:“吾今胜昨倍许,明胜今倍许,而山不加增,何苦而不快。”但是越发的勤快,愚公将越发没有机会找到更快的方法, 人的精力终归是有极限的。提出新的“方法”,解决的将是影响做事成效的根本问题。而愚公可以多吃点饭,多加点班,但突破不了人的精力的极限。 记住,在两千年前的某一天,闲极无聊的李冰下厨给夫人炒了一个小菜,他突然发现垒灶的鹅卵石被烧得爆裂开来,遇水尤甚。从此《史记》上记下了“蜀守冰凿离堆”,而《华阳国志》上记下了他做这件事的方法“积薪烧之”。 在差不多同一时间,愚公在山北之塞“碎石击壤”。 2. 一百万行代码是可以写在一个文件里的 早期写程序,都是将代码打在穿孔纸带上,让计算机去读的。要让计算机读的纸带当然是连续的,这无需多讲。其实我也没有那样写过程序,真实的苦楚我也不知道。 后来有了汇编语言,可以写一些代码了。这时的代码是写在文本文件里,然后交给一个编译器去编译,再由一个链接器去链接,这样就出来了程序。 第一个写汇编的人,可能写的是有名的“Hello World”程序,那个程序写在一个文件里就行了。所以后来就成了习惯,大家都把代码写到一个文件里。早期的汇编语言里,GOTO语句是用得非常非常频繁的,将一个语句GOTO到另一个文本文件里去,既不现实也不方便。所以大家习以为常,便统统地把代码写到一个文件里。 再后来出了高级语言,什么C呀,Pascal呀之类的。既然大家已经形成习惯了,所以很自然地会把一个程序写到一个文件里。无论这个程序有多大,多少行代码,写到一个文件里多方便呀。 直到如今语言发展得更高级了。可是程序员的习惯还是难改,一旦得了机会,还是喜欢把代码写到一个文件里的。 好了,有人说我是想当然尔。En,这当然是有实据的。记得Delphi 1.0版发布的时候,全世界一片叫好声。连“不支持双字节”这样的大问题,都不影响他在华语地区的推广。然而不久,爆出了一个大BUG!什么大BUG呢?Delphi 1.0的编译器居然不支持超过64K的源代码文件! 这被Fans们一通好骂。直到我用Delphi 2.0时,一个从VB阵营转过来的程序员还跑过来问我这件事。好在Delphi 2.0改了这个BUG,这让当时我的面子上好一阵风光。 64k的文件是什么概念呢? 1行代码大概(平均)是30字节,64k的源代码是2184行,如果代码风格好一点,再多一些空行的话,差不多也就是3000行上下。 也就是说,在Delphi 1的时代(以及其后的很多很多时代),程序员把3000行代码写到一个文件里,是司空见惯的事了。如果你不让他这样写,还是会被痛骂的呢。 所以呢,按照这一部分人的逻辑,一百万行代码其实是可以写在一个文件里的。不单可以,而且编译器、编辑器等等也都必须要支持。这才是正统的软件开发。 勤快的愚公创造不了方法。这我已经说过了。对于要把“一百万行代码写到一个文件”,查找一个函数要在编辑器里按五千次PageDown/PageUp键的勤快人来说,是不能指望他们创造出“单元文件(Unit)”这样的开发方法来的。 然而单元文件毕竟还是出现了。这个世界上,有勤快人就必然有懒人,有懒人也就必然有懒人的懒方法。 有了单元文件,也就很快出现了一个新的概念:模块。把一个大模块分成小模块,再把小模块分成更细的小小模块,一个模块对应于一个单元。于是我们可以开始分工作了,一部分人写这几个单元的代码,另一部分则写那几个。 很好,终于可以让源代码分散开来。结构化编程的时代终于开始了,新的方法取代了旧的方法,而这一切的功劳,是要归终于那个在按第5001次PageDown键时,突然崩溃的程序师。他发自良心地说:不能让这一切继续下去了,我一定要把下一行代码写到第二个文件里去。我发誓,我要在编译器里加入一个Unit关键字。① 3. 你桌上的书是乱的吗? 几周之前,在一所电脑培训学校与学生座谈时,一个学员问我:“为什么我学了一年的编程,却还是不知道怎么写程序呢”。 我想了想,问了这个学员一个问题:“你桌上的书是乱的吗?” 他迟疑了一下,不过还是回答我道:“比较整齐。” 我当时便反问他:“你既然知道如何把书分类、归整得整整齐齐地放在书桌,那怎么没想过如何把所学的知道分类一下,归纳一下,整整齐齐地放在脑子里呢?” 如果一个人学了一年的编程,他的脑袋里还是昏乎乎的,不知道从哪里开始,也不知道如何做程序。那想来只有一个原因:他学了,也把知识学进去了,就是不知道这些知识是干什么的。或者说,他不知道各种知识都可以用来做什么。 其实结构化编程的基本单位是“过程(Procedure)”,而不是上一小节说到的“单元(Unit)”。然而在我看来,过程及其调用是CPU指令集所提供的执行逻辑,而不是普通的开发人员在编程实践中所总结和创生的“方法”。 这里要提及到CPU指令集的产生。产生最初的指令集的方式我已经不可考证,我所知道的是CISC指令集与RISC指令集之争在1979年终于爆发。前者被称为复杂指令集,然而经过Patterson等科学家的研究,发现80%的CISC指令只有在20%的时间内才会用到;更进一步的研究发现,在最常用的10条指令中,包含的流程控制只有“条件分支(IF...THEN...)①”、“跳转(JUMP)” 和“调用返回(CALL/RET)”⋯⋯ 于是CISC被RISC(精简指令集计算机)替代了。动摇CISC指令集地位的方法,就是分类统计。 正如CISC指令集搅乱了一代程序设计师的思路一样,大量的知识和资讯搅乱了上面给我提问的那位学员的思想。他应该尝试一下分类,把既有的知识象桌子上的书一样整理一下,最常用的放在手边,而最不常用的放在书柜里。如果这样的话,我想他已经在九个月前就开始写第一个软件产品了。 你桌上的书还是乱的吗? 4. 我的第一次思考:程序 = 算法 + 结构 + 方法 我的第一次关于程序的本质的思考其实发生在不久前。那是我在OICQ上与Soul的一次谈话。 Soul(王昊)是DelphiBBS现任的总版主,是我很敬重的一位程序员。那时我们正在做DelphiBBS的一个“B计划II”,也就是出第二本书。他当时在写一篇有关“面向对象(OOP)”的文章。而我正在写《Delphi源代码分析》,在初期的版本里,有“面向对象”这一部分的内容。我们的对话摘要如下①: ① Turbo Pascal 3.0中才开始有了Uses和Unit关键字。在ANSI Pascal标准里并没有它。 ① 在x86系统中,循环是用条件分支来实现的,而且条件分支指令并不是IF...THEN...,这里用这两个关键字,仅用于说明问题。 ① 这段对话的确很长。如果你不是非常有经验的程序员,那么不能完整地阅读和理解这段文字是很正常的。部分读者甚至可以跳过这段引文,直接阅读后面的结论。而有兴趣的读者,可以在我的网站上读到它的全文( ① 片面地理解成“三人为众”是不对的。“三”在这里是虚词,指的是很多人的意思。然而,古人以“三”来泛指很多人或者群体,则是很值得玩味的事。 ① 软件工程中有专门的学科来研究项目的工期问题。学者们试图寻找公式来计算项目的复杂度,从而计算出所需的工时和人月。然而在实践中,这被认为是不可行的。 ① 这里的“完成”是指告一段落,或者说是阶段性的结束了。完成,并不等于完善。而完美,则更是无可企及。 ① 我非常不情愿给出一个模型来让读者跟随,但如果没有这样的一个模型,我想接下来的讲述可能会令很多人如坠雾里。明确的组织机构,既是团队的关键,也是我们思考问题的基础。 ② 我试图找一个单词来表现这个模型的简单和粗糙。我得到的一个建议是Rough(粗糙的)。然而我更愿意溯源到这个单词在古英语中的形态(Ruh),希望我这样一再强调,能让你真正地注意到:“R模型”是一个原始而且粗糙的东西。 ① 现实的情况未必如此。但UML这个名词起码显示了它本源性的期望:Unified Modeling Language(统一模型语言)。 ① 至于是“内有猪”还是“下有猪”的问题,不是我们要争论的。有些考古学家根据甲骨文的象形来认为古人与家猪是杂居的,但我想那时的猪可能还比较野性,因此这种可能性还是小些。 ① 这是极限编程的特征之一,指的是要求客户可以在程序员开发的第一现场,随时可以向程序员确认完成功能的有效性,以及修正需求或者先前的需求描述。 ① 大多数的软件公司已经意识到版本管理的重要性。然而项目各个阶段的文档、代码及其它输入输出都是具有版本问题的。单一的版本管理软件并不能胜任这些。因此我仍旧采用相对原始的、编写History这样的方法,来弥补ClearCase、SourceSafe、CVS等这些软件的不足。 ① 在2001年进行一次公司的内部培训时,我在幻灯片中画下这张图。半年后,我去北京读研时又看到了它,不过是画在《软件工程——实践者的研究方法》这本经典巨著中,第四层的“实现对象”是叫做“质量焦点”,名字则是“软件工程层次图”。其实所谓“经典”也是对既有知识的总结。大师们所知的,与你所思考的未必就有天壤之别。 ① 《三十六计》更多的时候是被当成方法论来读的。其根源在于“计谋”本身只是方法,而不是战略。 ② 如今这样的战役正在国外软件与国内软件之间进行着。而战局,并不是民族热情或者政府保护可以扭转的。 ① 顺便告诉你一个秘密,给予你奖励的决定通常是你的上司,而不是纪效经理作出的。 ② 不过,可能你仅受雇于你的上司,你习惯于把他叫作BOOOOSS则是另外一回事。 ① 我的确画出的线而不是点,“关注点”只是一个概念。如果你非要去发现一个“点”,那么你可以用几何的目光,关注于弧线与直线的切点。然而,这样的结果将是你彻底的忽视了“关注点”的本质含义。 ① 我经常注意到的成本因素包括时间、人力、资金和客户成本。而大多数情况下,人们不会把客户的数量以及耐心当做(客户)成本来计算。而在我的项目规划中,这是成本。 ① 人们在争论Aspect到底应该译成“切面”还是“方面”这件事上花了很多功夫。其实,就如同讨论前面的“关注点”究竟是“点”还是“线”的问题一样,他们陷入了细节。如果这些细节被作为问题持续下去,那么可能有一天台海战争将不是发生在军队之间,而是在程序员之间:到底是“物件”,还是“对象”? ② 在C中,这个名词是“结构(Struct)”。很多人不会承认“对象是有继承关系的记录”这样的观点。是的,所有的教科书上都不会这样写。但是从数据结构本身以及数据结构在语言中的实现来看,对象终究是记录。记录是平板化的内存存储体系中所能表达的最复杂的单一数据体。 ① 我写书的习惯是先写前言,这相当于大纲。因此所谓“现在”,是指我写下前言的这个时候:2004.11.01凌晨5时。 ① 你当然也可以由此反推出第7章的部分内容并不重要。的确,那只是我思考事物的一种方式,我希望你看到本书中讲的思想是如何被实例化的。但对于本书来说,如同我一再强调的那样:这是枝节。 Soul:我在写书讨论“面向对象的局限性” 我 :En.这个倒与我的意见一致。哈哈哈。 我 :“绝对可以用面向过程的方法来实现任意复杂的系统。要知道,航天飞机也是在面向过程的时代上的天。但是,为了使一切变得不是那么复杂,还是出现了‘面向对象程序设计’的方法。” 我 :——哈,我那本书里,在“面向对象”一部分前的引文中。就是这样写的。 Soul:现在的程序是按照冯。诺伊曼的第一种方案做的,本来就是顺序的,而不是同步的。CPU怎么说都是一条指令一条指令执行的。 我 :面向过程是对“流程”、“结构”和“编程方法”的高度概括。而面向对象本身只解决了“结构”和“编程方法”的问题,而并没有对“流程”加以改造。 Soul:确实如此。确实如此。 我 :对流程进一步概括的,是“事件驱动”程序模型。而这个模型不是OO提出的,而是Windows的消息系统内置的。所以,现在很多人迷惑于“对象”和“事件”,试图通过OO来解决一切的想法原本就是很可笑的。 Soul:我先停下来,和你讨论这个问题,顺便补充到书里去。 我 :如果要了解事件驱动的本质,就应该追溯到Windows内核。这样就涉及到线程、进程和窗体消息系统这些与OO无关的内容。所以,整个RAD的编程模型是OO与OS一起构建的。现在很多的开发人员只知其OO的外表,而看不到OS的内核,所以也就总是难以提高。 Soul:OO里面我觉得事件的概念是很牵强的,因为真正的对象之间是相互作用,就好像作用力和反作用力,不会有个“顺序”的延时。 我 :应该留意到,整个的“事件”模型都是以“记录”和“消息”的方式来传递的。也就是说,事件模型停留在“面向过程”编程时代使用的“数据结构”的层面上。因此,也就不难明白,使用/不使用OO都能写Windows程序。 我 :因为流程还是在“面向过程”时代。 Soul:所以所谓的面向对象的事件还是“顺序”的。所以我们经常要考虑一个事件发生后对其他过程的影响,所以面向对象现在而言是牵强的。 我 :如果你深入OS来看SEH,来看Messages,就知道这些东西原本就不是为了“面向对象”而准备的。面向对象封装了这些,却无法改造它们的流程和内核。因为OO的抽象层面并不是这个。 我 :事件的连续性并不是某种编程方法或者程序逻辑结构所决定的。正如你前面所说的,那是CPU决定的事。 Soul:比如条件选择,其实也可以用一种对象来实现,而事实没有。这个是因为cpu的特性和面向对象太麻烦。 我 :可能,将CPU做成面向对象的可能还是比较难于想象和理解。所以MS才启动.NET Framework。我不认为.NET在面向对象方法上有什么超越,也不认为它的FCL库会有什么奇特的地方。——除了它们足够庞大。但是我认为,如果有一天OS也是用.NET Framework来编写的,OS一级的消息系统、异常机制、线程机制等等都是.NET的,都是面向对象的。那么,在这个基础上,将“事件驱动”并入OO层面的模型,才有可能。 Soul:所以我发觉面向对象的思维第一不可能彻底,第二只能用在总体分析层上。在很多时候,实质上我们只是把一个顺序的流程折叠成对象。 我 :倒也不是不可能彻底。有绝对OO的模型,这样的模型我见过。哈哈~~但说实在的,我觉得小应用用“绝对OO”的方式来编写,有失“应用”的本意。我们做东西只是要“用”,而不是研究它用的是什么模型。所以,“Hello World”也用OO方式实现,原本就只是出现在教科书中的Sample罢了。哈哈。 Soul:还有不可能用彻底的面向对象方法来表达世界。 因为这个世界不是面向对象的。 是关系网络图,面向对象只是树,只能片面的表达世界。所以很多时候面向对象去解决问题会非常痛苦。所以编程退到数据结构更合理,哈哈。 我 :如果内存是“层状存取”的,那么我们的“数据结构”就可以基于多层来形成“多层数据结构”体系。如果内存是“树状存取”的,那么我们当然可以用“树”的方式来存取。——可惜我们只有顺序存取的内存。 我 :程序=数据+算法 ——
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服