导语:他虽然是一名大学老师,但却有着十多年软件开发和项目管理经验,他曾任职于湖南移动、创智软件园、NIIT(印度国家信息技术学院)和长沙创智新程教育技术有限公司等机构,也曾为多所高校、软件培训机构担任讲师和多家公司提供企业内训服务。另外他还主持和参与了30多个软件项目的开发工作,涉及教育、电子商务(政务)、企业EAI、移动通信等领域,此外他还致力于科研研究。正是这种复杂的多重经历,让他对软件开发有着独到的见解和心得,为此CSDN记者对这位学者兼技术人进行了专访,希望大家看完后能够对软件开发之路有全新的认识,尤其是对软件开发人员至关重要的设计模式、数学修养、软件架构和重构方面。
刘伟,中南大学软件学院副教授,博士。中国计算机学会会员,美国计算机学会(ACM)会员,希赛教育集团企业内训讲师,新程教育集团顾问兼高级讲师,CSAI顾问团专业顾问及内训讲师。具有十多年软件开发、项目管理及IT教育培训经验,曾担任项目经理、系统架构师、软件工程师、IT培训讲师和高级讲师等职位。研究方向为软件工程与数据挖掘,目前正从事相关算法的研究与CASE工具的开发工作。著有:《设计模式》、《设计模式实训教程》、《设计模式的艺术——软件开发人员内功修炼之道》等书。同时也在编著新书《UML实用教程》和《C#设计模式》。
我与计算机的故事
CSDN:请和大家介绍下你及所从事的工作
刘伟:我现在主要从事软件工程和数据挖掘等领域的科研、教学和研发工作。具体工作包括:
CSDN:你并非计算机出身,是什么缘故促使你自学计算机课程?在学习上有什么心得可分享?
刘伟:严格来讲大学期间我并不是一名好学生,因为我没把时间和精力放在专业学习上,现在从事的工作也与大学所学专业没有关系,但我并不后悔,反而觉得大学四年让我更加清楚地知道自己想要什么,树立了更长远的目标,那几年也过得很充实,为之后的学习和工作奠定了很好的基础。
我大学本科学的是化学专业,不过从大一(1999年)开始就对计算机产生了极大兴趣,然后自学了所有计算机课程,大二开始在一些校办网站和软件公司兼职。在本科和研究生学习期间,我利用课余时间在多家软件公司兼职,也组织过团队在外面接一些项目。软件开发是极富挑战的创造性工作,我很享受那个集体力和脑力劳动于一体的过程,我想最根本的原因应该还是兴趣所在吧。
在大学期间,我对软件教育和技术推广也具有极大热情,2001年(19岁)开始在一些IT培训机构担任网页制作、SQL Server数据库等课程的兼职讲师,同时考取了高级程序员等证书,还获得了微软认证系统工程师和微软认证数据库管理员。
对于软件知识和技术的学习,我有以下几点建议,供参考:
2010年我在CSDN博客上发表了一篇文章,《写给明天的软件工程师——感悟篇》,大家如果感兴趣的话可以看看。
CSDN:你微博中用“软件兴邦,教育利民!致力于中国软件教育“作为座右铭,想传达什么?
刘伟:这包含了我的人生理想,我现在的目标是成为一名一流的IT教育工作者,这里的IT教育是广义的,除了高校教育、企业培训外,还包括职业教育等,我觉得一个行业要能得到更好的发展,应该有一套成熟、科学、合理的人才培养体系。现在软件行业的地位和重要性毋庸置疑,前段时间我在博客中转载了一篇文章《软件应用无所不在 正吞噬整个世界》,现在软件已渗入到各行各业,而且很多传统行业已经离不开软件的支持,例如:零售、交通、出版、医疗、招聘、娱乐、电信、教育等等,还有很多行业本身就是依托于软件的,例如电子商务、在线游戏等。网景公司创始人、硅谷著名投资人马克·安德森的这篇文章中,他列举我们所面临的三大挑战第二条就是人才问题,软件行业缺乏大量能够胜任的软件工程师、经理、营销人员和销售人员,他指出只有教育才能解决这个问题。正因为如此,我觉得自己的选择是非常正确的,我也希望自己能够通过努力,成为一名优秀的软件教育工作者。“软件兴邦,教育利民!致力于中国软件教育”这句话也是用来勉励自己,希望自己能够不断研究和探索软件人才培养的规律和模式,以便更好地从事软件教育工作。
数学之美:程序员应有的数学修养
CSDN:一名优秀的程序员和他的数学修养有没有什么联系?它给程序员带来的最大帮助是什么?
刘伟:我个人觉得是有联系,而且关系很密切。数学作为自然科学之母,更多的是培养人的逻辑思维能力,是思维的体操。
我们要区别一下合格程序员和优秀程序员,合格程序员可以完成一些常规的代码编写工作,例如CRUD,这里确实用不到太多的数学知识,但是如果希望能写出高质量的代码(例如具有良好的时间复杂度和空间复杂度),或者参与一些技术难度较大的软件开发工作(例如涉及到构建数学模型的软件,如交通调度系统、与电子商务有关的数据挖掘系统、计算机模拟药物设计软件等),良好的逻辑思维能力是必须的,而数学正可以培养这种能力。
良好的数学修养将让程序员在设计和实现软件时思维更严谨、思路更开阔、考虑也会更缜密,有助于写出高质量的软件,还有利于参与一些技术复杂度较高的软件,这对于个人综合素质的提高和职业发展都很有帮助。我建议大家有时间看看数学书,做做数学题,你能够从中找到快乐!
CSDN:那程序员如何培养自己的数学修养?应该培养哪些数学修养?
刘伟:2012年有三本书卖得很火,它们是:腾讯副总裁吴军先生的《数学之美》、日本资深技术作家结城浩的《程序员的数学》和北大高材生顾森的《思考的乐趣:Matrix67数学笔记》。而购买者绝大部分都是IT相关人士,当然最多的还是程序员。由此可见,很多一线程序员都意识到有时间应该学学数学,看看数学书,培养自己的数学修养。这是好事,说明大家都在努力求进步,都在努力提升自己的综合水平。我也读完这三本书,收益颇丰。
2006年我在CSDN博客上发表了一篇题为《浅谈程序员的数学修养》文章,很多人发表了一些不同的看法和意见,当然我在这篇文章中所写的很多都是个人观点,难免会存在一些考虑欠周全的地方,但对于一名优秀程序员是否应该具备一定的数学修养这个观点我还是坚持自己意见,我认为是肯定的。那么如何培养自己的数学修养,我在《浅谈程序员的数学修养》一文中有提到,大家感兴趣的话可以看看这篇文章,另外我还转载了几篇与之相关的文章:《数学是成就卓越开发人员的必备技能》和《编程需要知道多少数学知识》,有一些不同的声音,大家都可以看看。
需要指出的是这里所说的数学修养并不是指数学知识,不是指你各种解题能力,这里所指的数学修养更多的是平时对数学知识的积累。比如适当做数学题来训练自己的思维、看有关数学书来丰富自己的知识体系,当你需要在工作中具体用到一些数学知识时,你可以很快地学习。数学修养的培养更多的是培养自己的逻辑思维能力,这对于一个优秀程序员是非常重要的能力,数学修养不等于数学知识,并不是看几本高深的数学书就能有好的数学修养,真正的数学修养的培养并不需要我们一定要掌握多少高深的数学知识,而是在平常的学习和工作中能够将数学知识和正在解决的问题联系起来。例如当你在设计一个电子商务系统时,除了传统的CRUD,你还应该考虑一下顾客行为分析、商品推荐、网站链接结构优化、广告投入策略、信息检索模型构建等,这里面也许就需要用到贝叶斯网络、粒子群优化、图论、 聚类和分类等与数学相关的知识,如果你具备很好的数学修养,平时也注意数学知识的积累,那么即使从头开始学这里的某些知识也不是难事。由此可见,对于一名优秀程序员而言,数学修养是必备的。
具体来说,数学修养的培养可以从算法分析和设计开始,深入理解一些经典算法的设计原理和实现机制,我认为算法是数学的一部分,是数学在计算机领域的应用,就像数学应用在材料、力学、经济学一样。另外,有空的话可以多做数学题和逻辑题,把这些习题当做一种逻辑思维练习,让自己思维更加活跃一点,Bob大叔(Robert C. Martin)称这种练习为卡塔(Kata),我建议大家有时间每天也做一两个卡塔,有些数学题可以不在纸上写,直接用程序实现也可以。另外,前面提到的那三本书也挺不错,建议大家有时间可以看看,权当一个入门,总之一定要认识到数学修养的重要性。对于那些正在或有志于数据挖掘、信号处理、图像处理和搜索引擎等工作的朋友,那数学的重要性就不多言了,大家都懂的。
IT人才培养
CSDN:在大学计算机专业课中哪些课程最难?你又是通过什么方式简单地讲解难点?
刘伟:大学计算机专业课中比较难的课包括离散数学、数据结构、编译原理、算法分析与设计等(来自同学反映),当然有的学校还开设了信息论与编码、数字图像处理、计算机图形学、计算机密码学、数据挖掘等,这些课跟数学以及逻辑思维能力或多或少有点关系,当然也因人而异。上述这些课程对于有些同学而言也并不难,但是跟软件工程、操作系统、计算机网络、计算机组成原理等课程相比,很多同学在学习这些课程时相对更加吃力。
这些课有些我也没有教过,在以前讲授数据结构、算法分析与设计等课时,如果遇到比较难的地方,我会首先利用一些图形和动画来分析其原理,先形成一个感性的认识,然后引入一些比较容易理解和通俗的实例来讲解,通过对具体问题的分析来逐步深入。特别是算法,不能为讲算法而讲算法,最好能够结合一些具体问题来分析,对于算法的本质需要讲透彻一点,但通常数学基础较好的学生可以快速消化这些知识,而数学基础相对较差的在学习过程中遇到的困难更大。因此,我有时候也会要求学生在课后做逻辑思维题,例如数字找规律、图形找规律、逻辑推理、简单的数学证明题等来训练一下思维能力,这其实也是在无形中培养自己的数学修养,通过一段时间的训练,有些同学确实有所进步,在思考问题时思路更开阔、更严谨,对算法的理解也更深入。
CSDN:你曾做过几年开发,后来为什么从技术人转为IT教育工作者?之前的工作对你现在有何帮助?在给高校学生上课之外,你还喜欢与企业交流,为什么?
刘伟:我个人对教育事业可以说是情有独钟,我出生于一个教师家庭,祖父、父亲、母亲都是教师,祖父和父亲是一所中学教师(祖父是老校长,父亲是现任校长),母亲是小学教师。从小就在学校长大,一直很喜欢把自己学到的东西传授给别人,这很快乐。在大三(19岁)时我就在IT培训机构担任网页制作、SQL Server数据库等课程的讲师,那时学生基本上比我大,但学习完之后,大家反应都还挺好,说我讲课思路清晰、内容很丰富、信息量大,能够学到很多东西,我想这方面还有点遗传基因吧。研究生阶段也在职业培训机构担任兼职讲师,硕士毕业(2006年)后在湖南移动、创智软件园上班,主要从事软件研发工作,还在NIIT(印度国家信息技术学院)、创智新程教育技术有限公司(原创智集团教育事业部)担任高级讲师,同时也担任几所高校的企业兼职教师,之后读博并在中南大学软件学院任教。从2001年开始都从事与IT教育相关的工作,之前是兼职,现在是全职。对于软件研发、软件职业教育、软件高校教育我都有涉足,正是这种特殊的工作经历,让我对IT人才的培养有更深刻的理解和认识。
在有过几年一线开发经验后,我发现自己最大的长处还是在于将一些知识用较为通俗的语言和实例传递给他人,这也是一名好教师,特别是IT相关教师应该具备的能力,因此,我陆续拒绝了很多国内外知名企业的Offer和多家猎头公司的邀约,在经过慎重思考后我已逐步将工作重心转移到软件教育上。另外我觉得中国的软件教育需要一批有过企业背景,也具有较好表达能力和感染力的老师,我自认为还是具备这些条件的。看到我的学生们能够进入一些一流的软件公司、做出一些优秀的软件,所带给我的成就和愉悦感,远比自己收获这些要大。
企业工作背景对我的教学工作非常有帮助,在教学过程中,我会结合一些企业真实项目实例来进行知识讲解,会结合我之前的一些工作经历讲授一些书本之外的知识,例如在讲解软件需求工程时,我会告诉学生我曾参与开发的一些项目是如何来获取需求的、对于不同的需求源我们做了哪些分析和考虑、采用了哪些需求获取手段、如何记录需求以及如何确认需求,跟学生讲我们当时遇到了哪些问题以及最后怎么解决的,还会穿插一些真实的小故事,让大家的学习过程不那么枯燥无味,而是充满好奇感和趣味性。正因为之前参与过那么多实际的项目,亲身经历过很多软件的成功与失败,也充分体会到过程的快乐与艰辛,才让我现在能够自信满满地站在讲台上,与学生们分享我的知识与经验。
为了不脱离企业,我现在仍然会经常与企业进行交流,我一直认为,一旦脱离企业实际需求,IT教育不可能培养出真正优秀实用的人才。一方面,我会在工作之余参与一些企业项目的开发工作,主要以顾问的形式参与需求分析、系统架构设计、技术评审等,尽自己的能力给一些企业提供指导,例如教企业如何实施Scrum、如何使用UML构建软件模型、如何对源代码进行优化和重构等。在提供指导的同时,我又可以将这些知识和经验传递给在校学生,让学生知道现在企业正在做什么、他们是怎么做的、遇到了什么困难、应该具备哪些知识才能胜任这些工作,我觉得这是一个良性循环,学生们学习了这些知识和技能之后在实际开发中就能够用上,而且学习过程本身也很好地切合了企业的需求,在一定程度上解决高校人才培养和企业实际需求脱节的问题。当然,我现在所做的还是一个探索性的工作,也希望这项工作对于我国高校软件人才的培养有一定的参考价值。另一方面,我也在分析企业的一些需求,例如,有些企业员工因为工作压力大、项目进度紧等原因,无法静下心来学习一些新知识,于是我会将这些知识整理好,用较短的时间和较为通俗生动的方式传授给他们,我觉得这也是IT教育很重要的一个组成部分,教育是贯穿一生的,活到老,学到老。
与企业交流让我了解到企业对人才的需求,能够为我的教学工作提供更多真实案例,同时我也能够为企业开发人员提供一些指导和培训,此外,我个人的知识和经验也在不断累积,有助于我更好地从事软件教育工作。
CSDN:现行的软件人才培养体制有哪些缺陷?你认为该如何改进?
刘伟:关于现行软件人才培养体制,我个人也有一些自己的意见和建议,下面我谈几点自己的看法吧。
当然,还包括不同层次的学校人才培养的差异性问题、软件工程硕士培养问题、不同方向(开发、测试、互联网营销等)的软件人才培养问题等。每一个问题都可以作为一个专题讨论,恕本人才疏学浅,也不妄加评论了,以后有机会再跟大家进一步交流。以上很多观点都来自我2012年12月份写的一篇博文《如何培养软件工程人才——参加“第一届高等学校软件工程人才培养高峰论坛”有感》,欢迎大家一起交流和讨论。
CSDN:设计模式适用于哪些领域?它体现了什么?能给软件开发带来哪些帮助?
刘伟:设计模式主要应用于面向对象软件设计领域,对于面向对象编程也有很好的指导意义。很多人都是通过对设计模式的学习和掌握才真正理解面向对象的。我在给一些软件企业做内训时,接触过很多具有多年开发经验的Java或C#程序员,他们一直采用面向对象语言在从事软件开发,但是基本上还是按照传统的结构化编程方式,不理解抽象类和接口有什么作用,不明白什么时候该用类继承什么时候该用对象关联,通过对设计模式的学习,他们才真正领悟到面向对象的魅力,更好地从事面向对象设计与编码工作。
设计模式来源于众多专家的经验和智慧,是从许多优秀的软件系统中总结出的成功的、目的是为了更好地实现可维护性复用的设计方案。设计模式是在特定环境下为解决某一通用软件设计问题提供的一套定制的解决方案,该方案描述了对象和类之间的相互作用,它是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。我们知道,随着软件寿命的延长和软件规模的扩大,如何更好地维护软件和实现软件的复用是现在软件界面临的一个很重要的问题,越来越多的企业将越来越多的时间、精力和金钱花费在软件维护上,从某种意义上来说,设计模式的使用可以避免我们做一些重复性的设计工作,有助于提高设计和开发效率。此外设计模式提供了一套标准的设计词汇,方便开发人员之间交流,例如学过设计模式的人都知道适配器是怎么回事,都知道桥接模式应用于什么样的环境,都知道单例类如何实现,也都知道迭代器是干啥的。除此之外,设计模式对于提高系统的可重用性、可扩展性以及设计方案的文档化都具有重要的意义,对于面向对象的初学者而言,提高学习和掌握一些设计模式的知识有助于更好地理解面向对象的三大特性:封装、继承和多态,同时还能够帮助大家更好地阅读和理解现有类库和框架的源码,降低学习成本。
CSDN:可以说设计模式是程序员必备技能之一,你认为如何才能更好地学习设计模式(比如如何才能更好地抓住设计思想和本质)?
刘伟:“如果想体验一下运用模式的感觉,那么最好的方法就是运用它们”。设计模式的学习关键是深入理解和多加实践,简单说就是多思考、多实践。每一个设计模式都有自己的适用场景,也都有自己的优缺点,因此在使用设计模式的时候要做一些权衡,例如有的设计模式可以提高系统的可扩展性,但是可能会增加系统中类的个数或者影响性能;滥用模式不如不用模式,需要合理使用设计模式。
最好的学习方法是首先系统学习一下设计模式,掌握这些模式的一些典型应用,例如在现有类库或者框架中的应用情况,关键还是要多加实践,要尝试在项目开发中多使用设计模式,有些设计模式还是很容易用上的,例如工厂方法模式、适配器模式、策略模式等。我建议大家的一种模式学习流程如下:先通过一些生活实例引入某种设计模式,然后学习该模式的动机、定义和结构,再学习一两个使用该模式的典型实例,接下来学习该模式的一些扩展知识以及模式的优缺点和适用场景,最后再学会在项目开发中应用所学模式。我相信,通过这样一个学习流程,应该还是可以较为系统地掌握一个设计模式的。在我最新出版的《设计模式的艺术——软件开发人员内功修炼之道》一书的第一章中有一个专门的小节介绍了我个人对于设计模式及其学习的一些观点,大家感兴趣的话可以看看。
关于这本书我在这里多讲两句,《设计模式的艺术——软件开发人员内功修炼之道》一书是我多年设计模式使用和推广经验的一个结晶。这本书结合30多个应用实例分析和讲解每一个设计模式,力求让大家通过最通俗易懂的方式来学习设计模式,让大家在项目实例的引导下学会选择和合理运用设计模式,快速提升开发功力,真正理解和掌握每一个设计模式,在软件开发的内功修炼之道上迈出坚实的一步。在书中内嵌了适量的基于项目实例的思考题和练习题,内容全面,语言通俗,深入浅出,难度适中,可满足不同层次读者的需求。我相信这本书将会帮助大家更好地理解和掌握设计模式,我在CSDN技术博客(http://blog.csdn.net/LoveLion)中开辟了专门的讨论区,学习之路,与你同行,希望大家能够多沟通,多交流。
CSDN:设计模式确实是个好东西,但很多人为了设计模式而设计模式,因此有人提议达到一定高度后请忘记设计模式,对此你是怎么看的?
刘伟:我很赞成这个看法,就像我经常和学生说的,真正的模式高手就像一些武林高手一样:手中无剑,心中有剑。设计模式的“上乘”境界就是:手中无模式,心中有模式。模式使用的最高境界是你已经不知道某个具体设计模式的定义和结构,但你会灵活自如地选择一种设计方案(也许就是某个设计模式)来解决某个问题,设计模式已经成为你开发技能的一部分,能够手到擒来,“内功”与“招式”已浑然一体,要达到这个境界并不是看完某本书或者开发一两个项目就能够实现的,它需要不断沉淀与积累,因此对模式的学习不要急于求成。
在学习过程中我得重复那句话,千万不要滥用模式。每个模式都有自己的适用场景,不能为了使用模式而使用模式,滥用模式不如不用模式,因为滥用的结果不仅得不到“艺术品”一样的软件,还很有可能是一堆垃圾代码。
当你真正系统理解和掌握了每一个模式之后,设计模式已不复存在,它已经完完全全与你的开发技能融为一体,你可以将它遗忘。
CSDN:设计模式和语言之间存在必然关系吗?有人说设计模式用C#和Java语言最好,对此你有什么观点?
刘伟:设计模式和语言之间还是存在一定的关系,现在通常我们所指的设计模式都是一种狭义的设计模式,大部分都源于GoF 23种经典模式,这些模式都是基于面向对象编程语言的,对于目前比较热门的另一类函数式编程(FP)语言并不适用,例如Haskell和Miranda等。但是对于所有的面向对象编程语言以及支持面向对象编程的语言来说设计模式都是通用的,不同的语言只是提供不同语法风格的实现,同一种模式的涵义和实现思路都是一致的。
由于在.net Framework和JDK类库中使用了大量的设计模式,而且C#和Java都是纯面向对象语言,它们都提供了较为方便的反射机制,同时也拥有大量的开源框架,在C#和Java相关社区讨论设计模式也会更多一些,相关的书和资料也很多,但这些都只能说明使用这两种语言来实现设计模式相对更为方便,并不代表只能用它们来实现。近年来,越来越多的基于其他语言的设计模式书籍问世,足以说明在其他各种面向对象语言中都可以很好地运用设计模式来设计软件。
总之,如果你正在从事面向对象开发或正准备从事面向对象开发,无论你是使用Java、C#、Object-C、VB.net、Smalltalk等纯面向对象编程语言,还是使用C++、PHP、Delphi、JavaScript等可支持面向对象编程的语言,如果你一点设计模式也不懂,可以毫不夸张地说:你out了。
CSDN:万物都有个度,设计模式并非万能,你能谈谈设计模式的一些局限吗?另外设计模式能改变软件质量吗?
刘伟:没有完美的模式,每一种设计模式都存在优缺点,就像我前面所说,有些设计模式可以提高系统的可扩展性,但是可能会增加系统中类的个数或者影响性能,例如工厂模式、策略模式、观察者模式等;有些设计模式可能连最基本的开闭原则都不满足,但是它们在特定情况下为某一软件设计问题提供了解决方案,例如单例模式、外观模式等。严格来说,每一种设计模式都存在自己的局限,因此在使用的时候需要我们做出一些权衡和折中,合理选择设计模式,慎重考虑是否需要使用设计模式。软件工程大师John Vlissides说过:模式从不保证任何东西,它不能保证你一定能够做出可复用的软件,提高你的生产率,更不能保证世界和平。模式并不能替代人来完成软件系统的创造,它们只不过会给那些缺乏经验但却具备才能和创造力的人带来希望。
对于设计模式是否能够改变软件质量,我只能说从某些角度或者一定程度上还是可以的。但是它不能确保,如果滥用模式,不仅不会改善软件质量,还会严重降低软件质量,导致设计方案和代码发生混乱。国外(加拿大蒙特利尔大学)有学者从程序员的主观角度做了一些研究,我把他们的研究成果翻译成中文也发布在CSDN博客中了,结果引起了大家“激烈”的讨论,因为不同的设计模式的出发点不一样,因此对于软件质量的影响也不一样。
软件质量是一个比较宽泛的概念,具体来说包括很多质量属性,例如正确性、健壮性、扩展性、可复用性、可维护性、安全性和可靠性等。有些设计模式可以改善某一个或一些质量属性,但是又会导致另一些质量属性受影响。例如单例模式,它可以节省系统资源,但是它的可维护性和可扩展性并不好;再如工厂模式,虽然它避免了创建代码的蔓延,扩展性也很好,但是它增加了系统的复杂度,一定程度上也影响了程序的性能。因此,对于设计模式是否能够改变软件质量,这句话没有明确的答案,选择设计模式的重点在于我们更加关注哪个或哪些质量属性,是可扩展性、可复用性还是性能,这需要我们做一些权衡和折中,大部分基于面向对象的设计模式重点考虑的还是可复用性和可维护性。因此,大部分设计模式可以改善系统的可复用性和可维护性,这句话是没有问题的,但是对于其他质量属性的改善,我们就只能逐个模式进行分析了。
目前,我带领一个研究小组正在从事有关设计模式对软件质量影响的定量研究,简单来说就是通过一些实实在在的数字(度量因子),而不是主观的评价来说明设计模式对软件质量的影响,我们在研究过程中选取了一些经典的软件度量因子,包括CK、LK、MOOD等,这项工作目前已经取得了一定的进展,我们发现有些模式确实能够很显著地改变一些软件度量因子,今后我会在博客中发布一些我们的研究成果。关于这项工作,我们最终还是希望能够融入到一套自动重构系统中,能够为用户选择是否重构提供一些理论依据。
CSDN:有人表示,设计模式并不难学,难的是如何成功应用,在这方面你有心得分享吗?
刘伟:首先这句话我很赞同。我也经常跟学生或者学员们说,设计模式一旦找到学习的感觉和有效的方式,学习起来并不难,而且学习的过程会很有趣,也很有成就感。但是很多人学完了并不知道怎么在项目中运用设计模式,对于学习,我想强调的是,每一个模式我们至少应该掌握如下几点:这个设计模式的意图是什么,它要解决一个什么问题,什么时候可以使用它;它是如何解决的,掌握它的结构图,记住它的关键代码;能够想到至少两个它的应用实例,一个生活中的,一个软件中的;这个模式的优缺点是什么,在使用时要注意什么。当你能够回答上述所有问题时,恭喜你,你了解一个设计模式了。
注意,我用的是“了解”,并不代表你掌握这个模式了,如果不懂如何使用一个设计模式,而只是学过,能够说出它的用途,绘制它的结构,充其量也只能说你了解这个模式,严格一点说:不会在开发中灵活运用一个模式基本上等于没学。设计模式是“内功心法”,它还是要与“实战招式”相结合才能够相得益彰。学习设计模式的最终目的还是在于应用,如果要做到熟练运用每一个设计模式,我的建议如下:
软件架构、重构与设计模式
CSDN:软件架构设计需要考虑的因素有哪些?如何才能做好架构设计?
刘伟:软件架构是软件工程一个很重要的分支,随着软件规模的扩大和软件寿命的延长,软件架构也越发重要。就像建筑领域,盖一个狗窝不需要进行分析与设计,但是如果是要盖一座万人体育场或者摩天大楼,那一定会离不开设计师。软件工程与之同理,好的架构能够决定软件的成败。软件架构不只是简单的分层或者划分模块,它包括更多的内容,例如需求确认、系统分解、架构风格的选择(B/S还是C/S)、技术选型(Java还是.net,Oracle还是MySQL等)、物理架构设计、数据架构设计、逻辑架构设计等等,通常架构师还要参与包设计、核心模块设计以及类设计等概要设计和详细设计工作。正因为软件架构设计涉及的内容相当多,因此需要考虑的因素也很多。
软件架构设计需要考虑的问题包括需求、成本、进度、团队人员的素质等等,我觉得首先应该考虑的是需求。俗话说:需求进、架构出。如果没有深入分析需求,往往难以得到好的架构,在分析需求时除了功能需求外,还要考虑一些非功能需求,包括是否要与第三方系统兼容、是否要考虑到数据迁移、是否要考虑到平台的多样性等等,非功能需要中很多因素也会影响到架构,例如安全性、性能等等,因此好的架构师应该尽量多参与需求分析,听听客户的想法,需求是影响架构最大的因素,架构风格的选择、技术选型等都与需求息息相关。除此之外,成本、进度以及人员素质等对架构的影响也很大,因此在架构设计的时候也需要充分考虑。没有完美的设计方案,无论是SAAM还是ATAM等架构评估方法,其实都是一种折中的方法,无法使每一个因素都达到最优,所以我们要全盘考虑,具体问题具体分析,找出当前应用最合适的一种设计方案。
对于如何做好架构设计,我个人建议如下:
CSDN:设计模式在架构设计中作用大吗?如何在架构设计中使用设计模式?
刘伟:设计模式在架构设计中还是挺重要,几乎每一本关于架构设计的书都会提到设计模式,甚至还会精讲几个常用的设计模式。就像前面我所说设计模式可以在一定程度上提高架构设计的稳定性和可扩展性,不会因为一点点小的改动就导致架构方案发生大的改变。合理使用设计模式,可以在提高代码质量的同时提升软件架构设计的质量。
在架构设计中使用设计模式时,也需要充分理解需求,才能正确选择和使用设计模式。大部分设计模式都提供了抽象层,目的是让系统更易于扩展。通常的做法是要学会分析出系统的扩展点,对于一些可变的扩展点,需要提供一个稳定的抽象层,然后通过具体层来实现具体的业务功能。比如:如果在需求分析和架构设计时发现某个业务功能将来可能会进行改进,例如加密算法,此时可以提供一个抽象的加密类,而将具体的加密类作为其子类,所有的依赖和关联都基于抽象加密类,引入配置文件,将具体加密类类名存储在配置文件中,然后利用反射和注入的方式将具体加密类对象提供给其他业务类使用。当需要更换加密算法时,只需增加一个新的具体加密类并修改配置文件即可,原有设计方案和代码都无须进行修改,系统符合开闭原则,具有良好的可扩展性,这就是策略模式的一个应用。
对于需求分析和架构设计中的一些具体问题,有些设计模式已经提供了很好的解决方案,例如当你需要经常调用一些第三方接口时可以考虑使用适配器模式,当你需要为多个外部子接口提供一个一致的入口时可以使用外观模式,等等。每一个设计模式都相当于“三十六计”中的一计,一不小心就在你的项目开发中用上了,当你遇到此类问题时就可以游刃有余地解决,这就是设计模式的魅力所在吧。
如果你的项目涉及到更多底层的东西,例如事件处理、缓存服务、类工厂、消息队列等等,特别是你要开发的是一个API或者框架,那么所涉及到的设计模式就更多了,大家有兴趣可以看看《应用框架的设计与实现-.net平台》和《软件框架设计的艺术》这两本书,里面就提到了不少设计模式在框架设计中的应用。虽然框架不等于架构,但是框架的架构设计需要更加灵活,想想谁会去用那些僵硬固化、不易于扩展的框架呢?
总的来说,当你对需求足够了解,已深入学习和理解各种设计模式,并能够准确寻找出扩展点或一些设计模式的适用场景时,你就可以合理使用相应的设计模式了。我相信,有效地使用设计模式一定会提高你架构设计的质量,解决你在架构设计中遇到的一些困难。
CSDN:能不能谈下重构有哪些意义?另外重构与设计模式间有什么关系?
刘伟:说得专业一点,重构就是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。这是重构的定义,简单来说就是不改变软件的功能,优化软件设计和代码,让软件更易于扩展和维护,当然也包括易于复用。软件工程大师Martin Fowler等人总结出了一些常用的重构技术,将其写成了一本面向对象领域的经典著作——《重构:改善既有代码的设计》。
软件开发大师Robert C. Martin在《程序员的职业素养》(The Clean Coder)一书中提到要勇于整理代码,通过整理代码让当它们更易于理解,更易于修改,也更易于扩展。这样代码的bug也会随之减少,不应该让代码劣化而视若不见。我觉得Bob大叔说的很好,这就是重构的意义。因此我常常跟学生们说,如果想成为一名合格的面向对象程序员,设计模式和重构是你必须要学的两项基本技能。
重构和设计模式之间的关系也很紧密,在Martin Fowler的《重构》一书中也提到了好几种使用设计模式来进行重构的手段。另外,还有一本书,名为《重构与模式》(Refactoring to Patterns,个人感觉翻译为“面向模式的重构”或者“重构到模式”更合适),作者是Joshua Kerievsky,这本书获得过第15届Jolt生产效率大奖。在这本书中提到了27种以模式为导向的重构,包括在设计中实现模式、趋向模式和去除模式。很客观地对一些设计模式进行了评价,既告诉我们如何通过设计模式来提高代码质量,又告诉我们如何在代码中去除一些不合理的模式应用。该书大部分重构方案还是实现和趋向模式的,例如将创建知识搬移到Factory、将聚集操作搬移到Visitor、用Strategy替换条件逻辑、用State替换状态改变条件语句等。每一种重构方案都提供了相应的实例,让你做一次重构的操练。当然,在读这本书之前,我建议大家还是先把设计模式好好学一下,否则里面有一些重构方案就没有办法理解了,毕竟这本书不是专门讲设计模式的。建议大家在学完设计模式之后再看这本书,既能够学到如何在实际项目中运用设计模式,又能学到如何在不同情况下选择设计模式,这本书也是我研究团队成员必读书籍之一。
CSDN:那在什么情况下才需要考虑重构?衡量是否需要重构的标准是什么?重构的难题有哪些?
刘伟:在Robert C. Martin新近出版的《程序员的职业素养》(The Clean Coder)一书中提到:当你发现修改软件不像你预想的那样简单时,你便应该改进设计,使后续修改变简单。让软件保持固定不变是危险的,如果一直不重构代码,等到最后不得不重构时,将会发现代码已经很僵化。因此,要将重构变成一种习惯,每一次在阅读代码或者检入代码时都要考虑对代码进行改善与优化。如果你希望自己的代码灵活可变,那就应该时常修改它!我觉得这就是对重构时机最好的回答。如果你发现代码太僵硬,不易于扩展(你可以扩展一下试试),特别是那些在需求文档或者客户嘴里多次提到的需要改变的地方,一定要尽量灵活,当缺少这种灵活性时,你应该马上重构。我个人觉得,衡量是否需要重构的标准就是现有设计方案或者代码是否不易扩展,复用性是否存在问题,将来是否会增加维护成本。为了将来,应该重构。
很多人明知设计方案或者代码有问题,却不愿意去重构,这里面也存在很多原因,我觉得很多人之所有害怕重构,最大的问题在于担心重构之后会引入新的问题,难于测试。关于这一点,Robert C. Martin和我的想法不谋而合,尽量实现测试的自动化。由于重构主要还是代码级的,对应的测试也主要是单元测试,单元测试的自动化程度在所有的测试中应该是最高的,因此只要我们有一套完整的测试用例,重构之后可以对应修改少许的测试代码就可以马上实施回归测试了。我个人觉得这个问题还是可以解决的,但是对于测试代码不完善或者根本没有测试代码的项目,实现起来恐怕会比较麻烦。因此,培养良好的开发习惯很重要,建议大家有空看看测试驱动开发(TDD)方面的书,我相信对大家,特别是一线开发人员还是挺有帮助的。
当然也有人觉得重构麻烦,不愿意重构,觉得功能都没有问题了,没有必要再进行重构,指不定重构之后功能还会出问题。有这种想法的人缺乏一种专业精神,我个人觉得要想成为一名专业的程序员,应该掌握一些常用的重构技巧并经常在项目开发中使用它们,可能开始会比较麻烦一点,但是当重构成为你开发技能一部分,就像写for、if语句一样很平常,你就不会觉得这是一种麻烦。在现在主流的IDE,例如Eclipse、Visual Studio中,重构都已成为菜单的一部分,可见业界对于重构已达成共识,很多人把重构当做写注释一样,是一个很平常的提高代码质量的操作而已。
还有一个影响重构的因素是项目进度、成本等受到制约。明明知道要重构,但是项目工期很短,没有时间和精力来重构,各种赶工很常见,后果有时候也很严重,代码质量很差,在维护和二次开发时大量代码可能需要推倒重写。对于这个问题,只能尽量去跟客户或者领导们交涉了,建议适当延长时间或者缩减功能。如果交涉失败确实很麻烦,只能想办法记录一下哪些地方需要重构,存在哪些问题,寄希望于有时间能够把这些地方重构一下或者在维护阶段再进行重构。如果不懂如何与客户和领导沟通与交流,建议读一读《软件架构师的12项修炼》(12 Essential Skills for Software Architects)一书,看看一名优秀的软件架构师(普通开发人员也一样)应该具备的一些非技术性的软技能,例如如何沟通、如何协商等等,说不定对你会有所帮助。
我个人的建议,将重构当做一种习惯,发现有问题或不利于扩展就应该立即重构。
我与CSDN
CSDN:你博客内容大部分都是12年所发,而第一篇文章却是06年,中断了很久为什么又拾起博客?你意识到了什么?此外你博客第一篇文章写于2006年的九一八,有什么寓意吗?
刘伟:中间几年因为工作太忙,一直没有坚持把博客写下去,更准确说应该是在不断积累和沉淀吧,厚积薄发。我觉得2012年也积累的差不多了,而且2012年也是我的而立之年,理应成为人生的一个小转折,因此我决定好好利用博客,把积累的一些东西发布出去,也算为软件教育事业尽自己的一份力,希望能够有人从我的博客中学到一些知识并将其应用于实际工作,这样我也就很欣慰了。我2012年的重点是设计模式,2013年的重点会是UML和软件工程的研究,我正在编写一些UML方面的图书,里面一些核心内容和我积累的一些资料也将陆续通过博客发布,希望大家能够喜欢。2014年可能对方向还会有所调整,不过还是会与软件工程和数据挖掘有关。
关于第一篇博客之所以选择2006年的九一八,其实也算是个巧合吧,我个人也有点“狭隘民族主义”,不喜欢日本,也是个日货坚决抵制者,但我不会去影响别人的选择,也不会去损害咱同胞的财物。
CSDN:在刚发售的新书《设计模式的艺术——软件开发人员内功修炼之道》里你加上了CSDN技术博客地址,为什么会想到加地址?你和CSDN有什么特别的故事分享吗?另外你对CSDN有什么建议?对未来有什么期待?
刘伟:我觉得CSDN是一个很好的交流和学习平台,大家在阅读完这本书之后,有一些意见、建议、想法,包括学习心得都可以通过这个平台进行交流,我也可以通过这个平台发布一些图书勘误、习题解答等,并及时收集和整理大家的意见和建议,以便再版时能够修复其中的一些问题。此外,大家在学习过程难免会遇到一些问题,通过博客大家可以相互讨论,也可以分享自己的一些体会和经验,这会让大家的学习之路更加轻松、收获更大,真正让博客成为一个学习、交流和分享的平台。因此,我决定把博客地址加到这本书中,而且我计划在以后每一本技术书籍中都加上博客地址。
我是CSDN和《程序员》的老用户,从2001年开始我就一直在购买《程序员》杂志,也经常访问CSDN的网站,每次我看到书房里那满满一箱的《程序员》杂志时(还有10多本《CSDN开发高手》),感觉那些年、那些事都还近在眼前,还记得大学时端着饭盆在学校书报亭问老板这个月《程序员》到了没有,然后拿着新一期的杂志如饥似渴地阅读的场景,那段年轻时期的学习和奋斗历程还历历在目。在这里我知道了设计模式、敏捷开发、Web服务、UML、CMM、XP、Scrum、TDD、SOA、MDA、RUP……,在这里我认识了(虽然他们不认识我)蔡学镛、李维、侯捷、李开复、Grady Booch、James Rumbaugh、Erich Gamma、John Vissides、Bertrand Meyer、Martin Fowler、Kent Beck……,很多知识从不懂到似懂非懂,很多技术从陌生到熟悉,我收获了太多太多,每次抚摸10多年前那些已经有点泛黄的《程序员》时,满是感触、感动和感激。在学习和成长的道路上,有一份属于程序员的杂志,有一个属于程序员的网站,真好!
最后,我希望CSDN能够进一步加强与高校的合作,进一步扩大自己的品牌影响力,能够走入更多企业,走入更多高校。同时,CSDN也可以充分利用已有的专家资源,在高校合作、企业培训、图书出版和在线教育等方面为软件技术的推广和软件行业的发展作出更大的贡献!
我坚信CSDN一定会越办越好!
写在最后:
在和刘伟的沟通中,记者发现他的确是一个对教育事业非常热爱的人,这从他在微博上写下“软件兴邦,教育利民!致力于中国软件教育”座右铭,立志成为一流的IT教育工作者中可以看到,从他拒绝了很多国内外知名企业的offer和多家猎头公司的邀约,毅然只当一名普通的高校教师中也可以看到。他私下和记者表示,他所追求的是尽自己最大的努力培养更多的优秀软件人才,为中国软件事业的发展和腾飞做出贡献,他随即又补充到,帽子有点大,但他确实是这么想的。
除此之外他还是名学者,他承担的科研项目已得到包括华为在内的多家企业关注并愿意参与其中,这样的科研成果对于一名80后而言是非常丰硕的。这么年轻就取得如此高的成就,那成功秘诀在哪?当记者了解到他在大学时就已开始实践,当晓得他藏书几千册可以办小型图书馆,当他告诉我每天无论如何都会抽出两小时来学习,当看到他在七年前文章中写下这样一句话“所有的证书和荣誉都只代表过去,而我只憧憬未来”时,这一切都已了然。
若想获悉刘伟更多动态,请关注:
CSDN博客:点此进入 个人微博:点此进入