扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
缘起
2004、2005年随着公司业务的急剧增长、组织结构的剧烈变化以及新员工的大量涌入,给公司研发造成了巨大的影响。各种问题、矛盾、冲突相互交织,形成了前所未有的机遇和战场。战场之惨烈,各种思路、解决方案、流程推行的纷争,即给人带来了劳累,也带来了无限的快乐、激情、兴奋和价值。在我们部门内,对HP方法的困惑、组件的定义/实现/发展、平台和产品之间的冲突矛盾等等,带给我各式各样的问题和想法,这些问题、解决办法以及它们之间各式各样的关联,在这一年里时而让我感到窒息、时而让我充满了兴奋。对这些问题的思索,没有答案时难受的让我夜不能寐,看到曙光时又让我兴奋的无法成眠,而这篇文章的诞生,也是我整整几夜无法入睡的结果。文章的标题之所以命名为“百家争鸣之-破冰”,是因为在问题的探索过程中,我发现自己的想法、理念渐渐和其他人有着某些分歧,有时这些分歧让人倍感窒息,因为这些分歧让人感觉好像偏离了方向,以至于我原本想用“百家争鸣之-孤立危崖”为题来表明自己那种往前一步便跌入万丈深谷的彷徨、孤立、以及不容于世的危险处境,当然骨子里还有我决不言败的偏执,难道我真的会去跳崖吗:-) 其实,这些分歧中很多并不是真正的分歧,有些只是我基于自身经验的困惑或隐约觉察的某些问题,这些困惑或问题有时自己也没有想清楚真正问题的所在,也几乎无法用言语表达出来,更遑论说服别人。
推介书目排行榜
下面的这些书都是这一年里来我所阅读和学习过的,我按带给我启发和联想的深度和广度进行了排序,但我本身的阅读顺序却并非如此(345162)。这里我想表明的是阅读和学习方法的重要性,因为在发现它们时,我心里一直都带着许多强烈的困惑,在各式各样的书籍和文章中寻找的过程中,我发现了一些以前忽略的事实或一些奇妙的事情:
1、“金子总是会发光的”,这是在我看了其中的某些书后,在其他的杂志、书籍中偶尔发现原来它们早就被其他的人所发现,但是这些都隐藏在了背后,甚至是在不起眼的角落里。
2、当你带着问题和困扰时,你会发现上帝的提示无处不在,只是你能不能发现的问题,而发现之后所带给你的将是极大的快乐。
3、要让一部好书,发挥它的作用,需要带着许多的疑问和困惑,将书中所说,不断的和你的问题、经验进行对比,去寻找答案。
4、最重要的一点是“联想”,下面的每一本书,如果没有发挥自己的想象力,几乎每一本都将是平淡无奇的,或者只是让你解决了眼前的疑惑而获得暂时的快乐。下面的每一部书,带给我的都有着极其丰富的内涵,它们所引发的联想几乎每一部都让我感觉到自己可以据此引发出另外一部长篇大作。
排行 |
书名 |
首推第一 |
《C++多范性设计 Muti-Paradigm Design for C++》[James O.Coplien] |
最和脾胃第二 |
《软件工程的事实与谬误 Facts and Fallacies of Software Engineering》[Robert L.Glass] |
最具创新第三 |
《嵌入式系统的微模块化程序设计——实用状态图C/C++实现 Practical Statecharts in C/C++ Quantum Programming for Embedded Systems》[Miro Samek Ph.D.] |
开拓思路第四 |
《用UML设计并发、分布式、实时应用 Designing Concurrent, Distributed, and Real-Time Application with UML》[Hassan Gomaa] |
新QA必读第五 |
《CMMI精粹:集成化过程改进实用导论》(第二版) |
丰富经验第六 |
《面向模式的软件体系结构 卷3 Pattern-Oriented Software Architecture: Patterns for Resource Management, Volumn 3》[Michael Kircher, Prashant Jain] |
首推第一 《C++多范性设计 Muti-Paradigm Design for C++》[James O.Coplien]
这是一本难得的好书(只可惜翻译的比较烂),它所引发的思考、方向的延伸,几乎可以和下面每一部书挂上关联,也对我们认识世界、认识软件设计的实质有着重要的影响,只是书名掩盖了它的价值。为什么我会有前面“金子总是会发光的”的陈词滥调,一方面我个人的阅读感受认为这是极具价值的好书,一方面是一天我在书店里翻阅其他书籍(《设计模式精解》)时,在其背后作者的推荐书目中也郝然发现对该书的介绍,这是作者的原话“这本书的第2章~5章是必须读的,即使是那些非C++开发者。这本书的每个地方都包含了对共同点/差异点分析的最好的叙述。……”。其实这本书早就在我的书橱里了,这是一直没来得及看,直到一天和XX讲到产品线工程时,提到了共同性和差异性,这给了我强烈的启发,导致我回来后到处寻找有关产品线工程方面的书,可惜没找着,但是却让我在自己的书橱里翻出了所能找到的唯一关于共同性和差异性的这本书。阅读之后才发现自己错过了什么。该书给我的启发和联想实在太多,基本上每一个主题和方向都可以写出一篇论文或者大部头的著作来,这里不能一一详细的论述,仅在这里列出我从中获得的收获和所能看到的联想的方向:
1、抽象和具体化以及共同性和差异性之间的关系。抽象和具体化XX已有精彩的讲述,而共同性和差异性这是我们认识世界、分析问题的基本手段的体现,它与抽象和具体化相辅相成,涉及到对世界的认识、问题的分类等许多方面的内容。
2、“维度”的概念。世界通过某些纷纭复杂的共同性所构成的维度,组成了各式各样的系统,这促使对系统分层概念的进一步扩展。这些维度的交织让系统更象一个“立方体”而不是局限于分层,分层仅是从其中的某一个维度所看到的。这对理解对系统设计的原理有着重要的帮助,甚至可以和当前的热门话题“架构”关联起来,在“架构”中“关注点”的概念似乎和“维度”有些关系,但还是有着本质的区别,“关注点”更多的是从系统的外部所看到的系统方方面面的属性,而“维度”反映了一个系统的内在,通过这些内在属性使系统呈现了交织复杂的状况,只通过其中某种维度了解或构建系统都可能产生对系统的曲解和扭曲,或者再试图解释系统某一其他属性时会遇到无法逾越的鸿沟。
3、如何正确的看待结构化设计,面向对象设计、基于对象设计、面向方面设计、面向服务设计等等当前各式各样的设计方法的本质和它们之间的关系?这些种种的设计方法,乃至各式各样的编程语言都只是抓住系统中某一维度或者某些维度的组合,来试图表达和设计整个系统,比如结构化设计紧紧抓住了“Process过程”的维度,面向对象着紧紧抓住了“结构和行为”的维度等等。沿着这个方向甚至可以分析比较Java和C#的优劣异同。而下面推荐的第3本书籍《嵌入式系统的微模块化程序设计——实用状态图C/C++实现》其作者也是沿着“行为”维度而有着辉煌的成就,这是否有相当大的启发呢?
4、解决了我对HP方法中最大的困惑,也是我一直不能释怀的一点——“Process和模块”之间“鸡生蛋、蛋生鸡”的问题。
5、和XX有着重要分歧的看法:究竟应该如何看待系统设计,到底是存粹的自顶向下,还是混合着自底向上?在XX看来,似乎更倾向于存粹的自顶向下,而我一直以来对此都保持着中立的看法和怀疑,这本书加深了我对自己的信念。在我看来,“维度”扩展了看待系统的角度,存粹的自顶向下局限了我们观察系统的视野,也割裂了解决方案和实现方案之间的关系,这样的做法会扭曲我们对系统的理解甚至会对系统的设计方案产生重大的影响。这一点非常重要,因为它引发了其他众多的分歧:
“特性”的概念:这是XX所坚持反对的概念,并试图建立全模型解决问题。这种观点抹杀了原来产品设计中开发人员经常使用的基于模块所画的MSC图的作用,而这是针对特性的设计中的基本手段。个人认为MSC图对于现在程序架构已基本稳定的产品已经足够了,这也导致了我一开始就对在处于维护阶段的产品推行HP方法不感兴趣,因为这对提高现有产品质量不会有太大的帮助(形成这个结论还有其他的因素)。现在看来HP方法在进行设计验证时又回到了基于PID的MSC图的道路上,也加深了我的看法。不过我不反对建立全模型,因为全模型的缺乏在目前公司的软件设计中也引发了很多的问题,尤其是使所有基于项目开发生成的文档都被浪费掉了。在业界众多的敏捷方法论中,有一种基于特性的设计方法,这种方法正是采用了先由架构师创建系统的基本架构,然后再不断添加特性调整架构的策略。其实这里面更多的是有关架构知识的“显示继承”和“隐式继承”的争执。在维护项目里,由于架构已经基本稳定很难有较大的变化,这时使用基于模块的MSC图,是完全有能力保证设计的正确性的。正确性的关键,更多的是设计者是否意识到有相关受影响的模块的存在,在HP方法里则需要设计者意识到是否有相关受影响的Process。这个问题HP方法也不能予以解决,即使是存在一个全系统模型,也更多依靠的是设计者自身的经验、熟练程度和敏锐感。在这里,XX之所以有着如此强烈的反对,更多的是基于其自身开发经验所打上的某个深深的烙印。而这种基于经验的烙印,在我身上也同样有着一个,也是几乎没有人可以动摇的一点——“我们没有实现不了的需求,只有解决不完的BUG”。这个烙印也深深影响了我对HP方法的看法以及在解决产品问题时所采取的不同方向。在我看来,HP方法带给我们最大的益处,就是理清了“包需求、设计需求、设计规格”的概念以及如何表达它们,还有就是试图将系统、开发、测试领域紧密的结合在一起(不过这已经脱离了原先HP方法的范畴)。而HP方法中基于DFD的功能模型,对产品质量的促进是有限的,至少在短期内对产品质量的促进是无法体现的,它的价值也依然是在理解需求方面。再看现有产品中的问题,更多的是集中在程序实现结构不合理、设计缺乏灵活性等方面(至少是我的观点),而这些更多的集中在“结构”的维度上而不是“功能”,这也限制了DFD模型对产品质量的提高能力是有限的。也许,更好的问题应该是“到底产品中因为需求不对所引起问题有多少?需求不满足客户要求所造成影响的比例有多大?”。不过这些只是分歧,不会影响HP方法的推行,也不会造成在解决方法上的混乱。因为沿着我的思路,会更加注重Review/PC-Lint 等基本的质量保证活动,以及在现有设计中使用MSC图或者表格等所有能够清晰表达思路的方式和工具,甚至有时会直接介入设计、编码中,充当部分SE或开发者的角色,告诉他们缺了这个,少了那个,或者这样实现有问题。这和建立全模型没有任何冲突,只是层次上不同,也是互补的。沿着“功能”和“结构”的维度,再去考虑全模型,我会选择如何更好表达程序结构及其精巧设计的方向,虽然HP方法中也有模块结构的构建,但这种表达形式有着极大的限制,也似乎不能很好的和目前注重“结构”的架构很好的结合,当然完全抛弃“功能”也不可取。走得更远一些,基于全模型的开发方法很可能导致走向严格的瀑布模型上去,这里更多的是基于公司目标决定的走向,“如何平衡全模型的详细程度”很可能是其中的关键和难题。
关于组件化:这是一次PRQA工具评估上引发的一个分歧,XX认为组件化没有自顶向下的设计,使用PRQA工具来进行解偶的度量可能意义不大,以及软件总线的概念和基于软件总线的组件的概念。这里关于组件化缺乏良好设计这一点上,没有异议。存在的分歧只是在组件概念和度量解偶有没有用这两个方面上。关于对组件概念的看法上,我觉得XX和自己的观点都是正确的,事实上,很可能我和XX之间都没能很好的彼此理解对方对组件的看法。XX认为组件就是接口经过良好定义的固定的,可以直接插在软件总线上就可以使用的部件,这里的关键是软件总线和接口,而且更多的应用经验来源于COM、CORBA、中间件之类的概念。不过在当前的组件化中,没有这个软件总线。所以XX似乎不太认同现在所谓的组件化。不过从另一个角度来看,组件的基本思想是复用,观察的角度也可以扩展到共同性和差异性的分析上来,这样组件的核心集中在“接口”和对差异性的适应情况上来。可以从汽车生产线来观察,每一种型号的汽车都使用了大量的不同型号的螺丝钉,而且只使用这些固定型号的螺丝钉,这些螺丝钉拿到另外一种型号的汽车上可能根本不能使用。这样看组件需要有良好的差异性适应,并且它的适用范围应该有所限制,不要试图将某一种螺丝钉用于所有型号的汽车。基于软件总线的组件是一项庞大的工程而且可能会存在严重的性能问题,在当前的情况下,只需要牢牢抓住组件的共同性和差异性以及对差异的适应性上。而差异的适应性表明应该对组件所使用的范围有所限制,如果试图大规模的复用,很可能遭遇到前所未有的困难。而在这一点当前的组件化工作有着天然的优势——仅用于一个产品族。下面推荐的第二本书中[事实17 大规模复用最好适用于相关的系统,也就是依赖于具体应用领域,这样就限制了它的应用范围]也证实了这一点。这样要实现组件的关键,实质上还是在设计上,而设计的核心依然是程序结构实现的经验、技巧,在这里解偶、信息隐藏的基本原理依然发挥着重要的作用。而我隐隐感到PRQA在解偶的度量上有助于改善现有组件化程序,也能将一些不适合作做为组件化的部分给剔除出去,因为这一部分是目前影响组件化是否能够独立发布版本的关键。其实,我觉得让我自己利用PRQA去进行组件的改进,亲自动手改程序,肯定能收效,不过这似乎和我目前的主业不相关,而且时间也不允许,于是乎,会议上便顺水推舟,把这个任务给推掉了。
最和脾胃第二 《软件工程的事实与谬误 Facts and Fallacies of Software Engineering》[Robert L.Glass]
这是一本非常简洁的小书,甚至根本不需要细看,只要看看作者所一一列举的事实与谬误就足够了,但带给我们的警示意义却很重要。之所以把它称为“最和脾胃”,一方面是因为书中列出的每一条都能和自身的经验相契合,另一方面则是因为作者思考问题方式和做法也和自己有着某种相似,不过这很可能不是一件好事。
这里姑且摘录几条,共享之:
事实15 小规模的复用(子程序库)开始于50多年以前,这个问题已经得到很好的解决。
事实16 虽然每个人都认为大规模复用(组件)非常重要、非常急需,但是这个问题至今还没有基本解决。
事实17 大规模复用最好适用于相关的系统,也就是依赖于具体应用领域,这样就限制了它的应用范围。
[当前公司组件复用发展的道路很好的验证了上面的几点,也预示我们组件复用的道路依然漫长而困难。]
事实6 在学习新工具或者新技术的初期,程序员的工作效率和产品质量都会下降。只有克服了学习曲线以后,才可能得到实质性的收益。只有满足下面两个条件,采用新工具或新技术才有意义:(a)新东西确实有用;(b)要想获得真正的收益,必须耐心等待。
事实14 对于可行性调研的回答几乎总是“可行”。
事实41 维护开支通常占软件成本的40%~80%(平均为60%)。因此,维护可能是软件生命周期中最重要的阶段。
事实42 增强功能大约占软件维护成本的60%,错误更正仅占17%。因此,软件维护的主体是在就软件中加入新功能,而不是更正错误。
事实43 维护是解决方案,而不是问题。
事实45 更好的软件工程开发导致更多而不是更少的维护。
[这里需要提醒的是不要误解“事实45”的意思,这里指的是软件工程带来易于维护的软件而导致增加的功能更多。]
最具创新第三 《嵌入式系统的微模块化程序设计——实用状态图C/C++实现 Practical Statecharts in C/C++ Quantum Programming for Embedded Systems》[Miro Samek Ph.D.]
这本书应该是所有开发人员都应该看的书,这本书模仿面向对象中继承的概念,提出了“行为继承”(和某些面向对象论述中提及的“行为继承”不一样)的概念,这个概念对于层次状态机以及界面框架的实现都有所裨益。作者论述了层次状态机的各种可能实现,比较了优缺点,并基于这些分析,提出了自己的设计方案和C/C++的实现以及基于此原理的一个RTOS(不过不爽的是,网站上最新的源代码居然要收费了)。详细的内容这里就不做介绍了。这里我想说的依然是“金子总会发光的;当你心存疑问的时候,上帝的提示总是无所不在”:
有一次和别人闲聊时,他提到公司里有人写了篇文章提到了状态机的行为继承,当时一听就知道估计提出的人也是看了这本书,其实刚看过这本书时,我也想动手写文章,只不过是有想法没行动,另外自己私下里也向一些SE推荐过这本书,至于他们有没有去看过,就不得而知了。
后来在某一期《程序员》杂志中的一篇书评中,看到有人简单的提到了这本书——原来竟然是2004年里被誉为嵌入式程序设计领域中十几年来最有震撼力的一本书!想想也是,大多数嵌入式系统的书籍翻来覆去的都是那几板斧。有趣的是,这本书原来放在小卖部里放了很久似乎都没有人光顾,不知是《程序员》,还是公司里发表文章的老兄所起的作用,现在这本书几乎找不到了。
之所以会去看这本书,一方面是因为一直对目前实现状态机的方式感到不满意,一方面则是在学习HP方法时,看到层次状态机,一直没想清楚比较好的实现方式。其实,在看到这本书之前,我已经翻了不少关于层次状态机方面的论述文章。
当然最大的启发还得和第一本书联系起来。
开拓思路第四 《用UML设计并发、分布式、实时应用 Designing Concurrent, Distributed, and Real-Time Application with UML》[Hassan Gomaa]
这是XX推荐的一本书,也是一本让人希望一口气读完的书。书中描述了一种使用UML进行并发对象建模和体系结构设计的方法和过程。看这本书时,更多的是要考虑如何和公司目前的流程相结合,这也是每一种方法应用时需要考虑的。看这本书的时候,主要是因为某个项目希望使用HP方法,不过由于时间、精力的原因,后面几乎放弃了,不过模型还是保留了下来,虽然可能不尽人意。这里把部分经验贡献出来:
这本书中介绍的方法,很重视协作图的综合,可以看清楚模块之间存在的关联,和结构化方法有类似的好处。不过,目前的UML建模工具,似乎都不支持将单个用例分析中所生成的协作图进行综合的功能,导致综合必须手工进行,存在较大的困难,尤其是系统比较庞大的时候。
这本书在讲述方法时,是沿着在对系统所知甚少时,如何一步一步对系统进行分析/设计出来的思路进行写作的,这和结构化设计方法有些类似。但是其中非常细致的描述每一步的活动,容易在第一次尝试时让人步入歧途。这是我自己犯的一个错误,试图让开发人员将每一步思考的过程都在模型中予以体现,不过还好,他们发现有困难,结束了这个错误。这里有两点意义:一、设计过程有着众多思考,某些设计基于自身经验可以一步到位,不要试图沿着某种固定的思维方式要求设计者将整个过程一一记录;二、在今后推行建模的设计活动中,需要更加关注项目的讨论计划,因为基于建模的过程需要绘制大量的建模图形,图形的更改耗费较大,如果后期才发现严重问题,对进度有较大的影响,这迫使大家需要更关注前期的讨论过程。其实我们一直都强调讨论,不过以前的写作方式很难强迫要求,基于图形的建模过程会使这种情况有所转变。另外,大量充分的讨论也会引起最终评审时,缺陷发现数量会有较大的减少(臆想:如果没有降低,很可能讨论过程不是很充分),在一段时间内需要面对这种变化,重新建立相应的能力基线。
新QA必读第五 《CMMI精粹:集成化过程改进实用导论》(第二版)
这本书很薄,很适合CMMI的入门。里面对CMMI的模型原理、由来,以及各个KPA之间的关系讲得浅显易懂,也很容易引起阅读的兴趣,比看胶片或者E书要快也有趣的多。事实上,我自己周末的时候看得兴起,一直看到凌晨3点多,差点不想睡觉。如果新QA学习CMM的KPA后,在给其他人介绍时能够按着这本书中讲述的思路去总结写胶片,获得的收获会更多。
丰富经验第六 《面向模式的软件体系结构 卷3 Pattern-Oriented Software Architecture: Patterns for Resource Management, Volumn 3》[Michael Kircher, Prashant Jain]
这本书是本存粹的技术书籍,讲的是资源管理方面的主题,相对于其他的模式书籍(除了GoF之外)有着较高的抽象层次,所能引起的变化和对应的解决方案也较多。由于开发人员实际上都在不知不觉的应用着这些模式,所以更多的时候主要是增长经验。不过它引起我思考的其实是一些其他的方面:
长久以来程序中超大函数里丑陋的if else分支、大量重复的while循环等,一直都影响着组件的解偶和独立发布。虽然架构、高层模块划分以及“接口”都非常重要,可是如果没有在实现组件的差异适应性上的突破,始终会存在着鸿沟,这个鸿沟没有消灭,会给组件的独立发布带来很大的障碍也会影响架构实现的效果。目前虽然在功能配置参数上已经有所行动,但目前过多的功能配置参数对程序结构的影响依然让人担心,因为这增加了程序结构中更多的分支,互相之间的关联很有可能出现问题。出于对这方面的担心,平时写程序或人讨论时,如果有什么启发总是不自禁的会引发这方面的联想,这本书里提及的Lookup模式,也引起我某些方面的思考,虽然不一定会对当前状态有所帮助(没有实践过),但是却让自己对以前的编程经验、体会进行了串联和重整,重新思考了树、过滤器(不一定非要这样叫)、子节点查找策略、Map、状态机以及程序结构的本质。这些技术几乎是每个人都在自觉不自觉使用的,只是没有好好凝练,以至于编写的程序不够简洁难以维护,基于这些基本技术的组合,可以看到其广泛的应用,甚至是某些领域的关键技术,下面是我能联想到的一些应用场景:
破解程序中丑陋的if else,优化程序结构
基于DFD数据流图的验证实现
Excel 中高级过滤和数据透视表功能的实现
各种图形工作流、可视化编程环境的实现
面向对象语言中虚函数继承的实现
神经网络的实现
各种排序树、判定树、搜索树……
后记
长久以来,自己有着这样一个很深刻的体会:业务开发人员和平台开发人员几乎完全属于两个领域;业务开发人员对领域知识有着丰富的经验,要成为一个好的业务人员需要阅读大量的协议/标准,以至于业务开发人员在设计技巧、通用技术以及编程技能方面疏于学习;而平台开发人员刚好相反,在设计技巧、通用技术以及解决具体编程问题上有着丰富的经验和高超的技巧。这两方面的差异,很多时候导致了业务只关注产品中功能方面的属性,而平台则在产品的其他属性(如可靠性、性能、可维护性等等)方面发挥着重要的作用。由于业务功能始终是客户最关注的核心,导致长久以来,平台开发人员都隐藏在业务开发人员的光芒之后,属于真正的幕后英雄。这两年来,公司出于复用的需求,将平台开发从幕后提到了幕前,即给平台开发人员带来了机会,也带来了业务和平台之间的冲突,业务和平台就在冲突、磨合与平衡之间共同前进。这种差异,也导致了在两年里业务和平台所获得的成绩完全是不同的,我们也不能始终用同一种眼光去衡量两者之间的贡献:业务在运作方面和需求分析上有长足的长进,而平台则更多的是在提高产品质量、性能以及组件的测试方面踏着一个又一个坚实的脚印。其实,平台的特性决定了平台产品的运作必须在技术和流程管理两方面同时突破,因为技术的难题无法解决,始终会导致流程上有着难以解决的困难也会带来无止境的冲突和争吵。明白两者的差异,才能让我们在平衡平台和业务之间冲突时,作出更加合适的选择。沿着这方面的思考,几乎引发着我其他的话题——百家争鸣之争锋,来比较和阐明这一年里来业务和平台在各自的领域里所获得的成就。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者