Richie

Sometimes at night when I look up at the stars, and see the whole sky just laid out there, don't you think I ain't remembering it all. I still got dreams like anybody else, and ever so often, I am thinking about how things might of been. And then, all of a sudden, I'm forty, fifty, sixty years old, you know?

复杂度 - 软件开发中最值得警惕的问题

复杂度
画一个圆圈,圆圈里面的部分代表你已经掌握的知识,圆圈外面是你未知的领域,圆形的线条代表目前状态下,那些你已经认识到但还没有被掌握的区域。
结论是你掌握得越多,你所认识到未掌握的东西也越多。

如果把这个比喻用于软件开发过程,也是一个很有意思的现象:
这次圆圈里面的部分代表复杂度(且不管复杂度具体应当包括哪些,怎样衡量),圆圈外面的部分代表风险,圆形的线条则代表项目过程中有可能遇到的风险。
结论是复杂度越高,项目的风险越大。

从字面意义理解复杂度,上面的结论是显而易见的,但在具体项目中,我们却经常因错误的主观判断,被复杂度击倒。

有人会想到应当有个成熟度的因素,即对于同样的复杂度(尽管没有方法准确衡量,但我们假设在概念上已经有了),成熟度越高,风险当然就会越低,就是说上面这个比喻的结论是错误的。
其实,复杂度的概念中应当包含对成熟度的考量,因为显而易见的事实是,对于相同的问题,在问题域方面能力越强的人,完成它会越容易。就是说对于他而言复杂度比较低,但对于其他人可能复杂度就比较高。成熟度只是复杂度计算的一个因子,以反比的关系影响复杂度的值。

一些零散的思维
我们每天都在学习。拼命作项目过程中,我们会获得项目中使用的具体技术相关的知识,获得项目管理等项目过程相关比较综合的知识和经验。闲时总会阅读很多技术文章,有针对性地深入研究。这些行为都是在提高自身的成熟度,降低解决问题时的复杂度。

个人觉得对某项技术掌握非常好,引入到了团队/项目中,可结果不一定非常理想。因为使用相同的技术,对团队不同人而言复杂度不一样,它对团队整体的复杂度决定它的运用效果。

技术功底比较强的项目经理,或者技术经理/总监等,他们考虑问题会比较全面些,就是说根据他们的经验,对复杂度、风险方面的综合性考虑会比较多。因此就会出现很多的现象: 他们常常对某个实现方案想追根究底,对准备新运用的技术提出很多质疑。他们希望多了解,然后用自己的经验去计算这个复杂度的模型,进行评估决策。有时结果是坚决的反对使用某种技术或方案。
这个现象严重点的情况下,部属就会觉得比较压抑,没有太多发挥、锻炼的机会。
大家讨论比较多的一个管理方面的问题(也经常提到诸葛亮的例子),即领导太强,部属可能很弱。
这些情况下,出发点应当主要是想评估和控制复杂度,但采用的方式带来了管理上比较严重的负面效果。

商业产品的宣传资料都会宣扬产品的特点,而隐藏产品本身包含的复杂度。有时候组织的决策层极度看好这个产品带来的市场价值,却不了解它对于组织而言的复杂度,急切地在组织内推广运用,因此效果可能并不理想。有时开发者自己也因产品的特性而影响了对复杂度的考量,而觉得该产品解决特定问题很好,实际运用结果可能证实并非是一个好的解决方案。

对技术掌握的成熟度可以降低运用的复杂度,因此可以投入成本学习研究,可以降低复杂度;采用迭代过程循序渐进的方式运用,一方面将复杂度分散到各个迭代阶段进行解决,另一方面在迭代过程中逐步获得的知识,也可以降低复杂度。

越是放光的技术、思想,越有可能影响技术人员对它的复杂度的判断,因为人的思想是主观的、感性的。放光的技术、思想对技术人员的感性冲击,不亚于美女的效应,久经情场的老手对这种诱惑就能表现出比较强的把握度。

对复杂度的错误评估,经常是项目不顺利的根本原因。

复杂度并不适用于加法运算,例如同样的问题,分解成1000个功能点,对每个功能点采用复杂度最低的方案,这种情况该问题的总体复杂度可能并不是最低。例如采用一个复杂度较高、较通用一些的方案来解决这1000个功能点,或者是解决里面的500个功能点,这时该问题的总体复杂度可能更低(好像还是可以用加法得到这个结果,不过不是简单的∑min(Xn)的关系)。
这只是可能的情况,一个复杂度较高的解决方案在团队中的运用,前面已经提到了它的作用方式。
但这最有可能出问题,因为作为技术负责人而言,理所当然的觉得某个复杂度较高的解决方案,对于项目总体的作用效果可能会比较明显,即可以降低项目复杂度,但却忽略或过低的评估它在团队上的作用原则。

瀑布模型具有复杂度,如果组织在流程管理方面的成熟度很高,那么瀑布模型运用的复杂度就低,能够得到瀑布模型期望的效果。敏捷开发在开发流程上简化,降低流程管理本身的复杂度;结对编程能够提升个体的工作效率,提高质量,也能用复杂度来解释?也许,在有向心力的创业团队中,解决问题常能事半功倍;组织的各种激励策略,都是为了提高员工工作效率;领导力优秀的管理者,都有各自独特的方法激励部属。同样的问题,人们愿意投入更大的精力去解决、研究,其实一方面也就将学习,将自身能力提升的过程进行压缩(应当不止于此,个人、团队的效率问题可能并不是复杂度能够解释的)。
敏捷并非适用于所有组织,因为它将瀑布模型中被流程化的东西再次综合起来,转移到组织的个体单元上,也就是组织对流程管理的复杂度,被分发到组织的个体单元,辅助一些其它措施,例如迭代,例如结对编程中互相监督、学习、激励等方式,使得这个复杂度降低(其实就是跟前面将问题分解为1000个功能点的场景采用了相反的方式,也许这是管理方面跟技术方面的区别,也有可能是软件领域的管理跟其它领域的区别)。
如果这样来理解,可以比较明显的得到一个结论: 敏捷适合中、大型的组织,而并非小型组织。因为小型组织的竞争力,或者说运营管理的关键问题不在于流程上,而敏捷为了达到这个目的是添加了附加成本和风险的。人员流动而造成的组织知识的流失,影响比较大,拥有良好企业文化、理念、向心力的组织,运用风险会比较小,否则将是个巨大的隐患,或者以后可能需要投入弥补的成本将超越敏捷带来的效益。
这些可能就是敏捷过程与瀑布模型比较本质一点的区别: 关键复杂度所在的位置不一样。

如何运用
在管理中,一直在寻求量化的指标来进行考核、决策。既然复杂度好像是各个问题的本质,但它涉及的各个方面都只停留在经验层面,能否有一个公式进行计算?
例如一个项目开始,有可供选择的人员来建立项目团队,有可供选择的设计架构方案,以及各种平台、框架、技术等,如果对应这些组合都能计算出一个复杂度的值?
也许到达这种程度跟让计算机自己去做项目一样困难,也许以后会有类似的模型能够运用,目前我们只有考虑如何更全面、深入的认识复杂度这个概念,完善我们的经验模型(用经验去评估复杂度的逻辑思维模型),尤其是警惕美女效应。

把任何人在同一时间需要处理的本质(essential)复杂度的量减到最少;
不要让偶然性(accidental)的复杂度无谓的快速增长。
软件开发中任何其它技术目标都不如管理复杂度重要
--代码大全2
其中本质的(essential)属性指一件事物必须具备,如果不具备就不再是该事物的属性;偶然的(accidental)属性指一件事物碰巧具有的属性,有没有这些属性都不影响事物本身。

posted on 2008-02-18 01:38 RicCC 阅读(2473) 评论(17)  编辑 收藏 所属分类: Architecture & Design项目管理 流程管理

Feedback

#1楼  2008-02-18 02:38 光之追随者      

占1楼!   回复  引用  查看    

#2楼  2008-02-18 08:01 BlackCat      

不错   回复  引用  查看    

#3楼  2008-02-18 09:22 巫云      

已经审美疲劳,美女不再有效。   回复  引用  查看    

#4楼  2008-02-18 09:47 怪怪      

好文!   回复  引用  查看    

#5楼  2008-02-18 10:04 水煮 鱼      

对于复杂度问题,确实应该关注
我们公司目前主推圈复杂度,就是CC复杂度,并且还推出了复杂度的检查工具。   回复  引用  查看    

#6楼 [楼主] 2008-02-18 11:14 RicCC      

@巫云
境界不错了,不过我说的原因好像不是审美疲劳 ^-^   回复  引用  查看    

#7楼 [楼主] 2008-02-18 11:16 RicCC      

@怪怪
难得看到你这么简洁的回复阿,呵呵   回复  引用  查看    

#8楼 [楼主] 2008-02-18 11:17 RicCC      

@水煮 鱼
CC能够检查的太局限了,不过我讲的复杂度太范,用工具没法查,只能靠经验,在意识上强化   回复  引用  查看    

#9楼  2008-02-18 11:21 pk的眼泪      

有理.   回复  引用  查看    

#10楼  2008-02-18 19:26 Yannic Yang      

最近在思考一个东西:
传统的开发,比如瀑布模型,在于理论指导开发,事先建立一种开发的理论(架构设计),在整个过程中遵循它
敏捷过程,不论是Scrum,XP,共性在于他们用经验控制开发风险
目的都是控制开发中风险
所以只要能控制住整个开发的风险,怎么样都行
当在风险较大传统方式难以控制时,可以考虑使用敏捷过程 用经验来控制风险
假设项目本身就没什么风险,采用什么方式开发无所谓,怎么样都能完成任务   回复  引用  查看    

#11楼 [楼主] 2008-02-19 06:35 RicCC      

是的

首先早期在软件领域研究风险、质量问题时,就是从复杂度这个主要因素着手,留给现在有运用价值的一些东西就是CC复杂度方法、测试驱动(不可测试或难以测试就证明复杂度过高,或者没有正确认识而得到正确的解决方案)等

其次,瀑布模型运用得不好,证明的只是一个看似很平常的现象,即人类协同工作很难步调一致,很难管理。就像军队的方队走正步,方队越大要协调一致就越困难。把需要协调同步的单元缩小,在小的单元上进一步运用降低复杂度的措施,例如结对编程(有一半的作用跟TDD的原理类似,结对中总有一方具有测试用例代码的效果,只不过是用人的思维来进行测试验证而已,也应当就是你讲的经验控制风险的原因),这就是敏捷采用的方式

至于运用的基础/前提条件等,从文章和我回复的观点来看,是很明显的:
小型组织本来已经是小规模,已经具备敏捷期望的目标结构,这样的组织出了问题就应当去找根本原因,而不是来追敏捷这个概念,走一趟形式过场

同样,中、大型组织如果流程管理成熟度已经相当高,就没有必要用敏捷,因为敏捷同样有它的弱点,实施过程还包含极高的复杂度,就像古代军队作战,对阵的时候还来换阵形一样   回复  引用  查看    

#12楼  2008-02-21 09:13 乐子哥      

看得很晕,学习中。。   回复  引用  查看    

#13楼  2008-02-23 23:41 水煮 鱼      

@RicCC
复杂度这种东东
如果在代码规模比较小的时候,靠个人经验还比较好控制
但是当代码规模比较庞大时,如果不能量化,则非常难控制
以我们公司的代码为例:
目前公司内整个软件代码规模已经达到了10M行。由于员工能力参差不齐,经过很长时间的发展后,曾经通过CC复杂度的量化工具进行测试,某些函数光CC复杂度就达到了上百。优秀的软件公司,一般单个函数的CC复杂度约为7-15,所以无法量化的东西,能难推广。   回复  引用  查看    

#14楼  2008-02-23 23:46 水煮 鱼      

@RicCC
结对编程仅仅提高代码质量的一种方法而已
但是在现实工作中,由于上面的领导过于追求片面的效率
所以使用这种方法的,已经越来越少了。
悲哀...................   回复  引用  查看    

#15楼 [楼主] 2008-02-24 11:41 RicCC      

@水煮 鱼
在代码上做量化检测有难度有局限,但也是解决问题的根本入口。
现在来看各个流行的语言都太底层,增加了复杂度检测的难度,因为从这些代码要去理解业务语义基本不可能,可能这也是阻碍复杂度研究的根本原因。以后如果DSL能够发展和普及起来可能情况会很不一样。   回复  引用  查看    

#16楼 [楼主] 2008-02-24 11:49 RicCC      

@水煮 鱼
从管理角度来说,用经验来控制是目前比较可行的方案。我说的复杂度包括开发的流程、模式,系统架构、设计,以及到到代码层面甚至是每一个方法的编写。
先提取一些衡量复杂度的指导原则,然后把这个我所表达的思想武装大大小小的管理、设计负责人,让他们辅以自己的经验去发挥效应,应当是能够带来效果的。不过你提到的如规模变大、参差不齐等因素,可能同样会给这个过程本身带来无法应对的复杂性。将这种方式结合流程化管理也许可行。   回复  引用  查看    

#17楼  2008-03-14 09:08 Anthan      

之前有同事写过一个VS的小插件用来控制复杂度
只是一旦和开发成本联系起来,真正实行就比较麻烦了
  回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-02-24 08:33 编辑过
"五向定位"职业成长路线公开课(上海、南京、大连)
Google站内搜索


相关链接: