专访刘伟:软件开发人员的内功修炼之道

转自:http://www.csdn.net/article/2013-01-15/2813690/3


软件架构、重构与设计模式

CSDN:软件架构设计需要考虑的因素有哪些?如何才能做好架构设计?

刘伟:软件架构是软件工程一个很重要的分支,随着软件规模的扩大和软件寿命的延长,软件架构也越发重要。就像建筑领域,盖一个狗窝不需要进行分析与设计,但是如果是要盖一座万人体育场或者摩天大楼,那一定会离不开设计师。软件工程与之同理,好的架构能够决定软件的成败。软件架构不只是简单的分层或者划分模块,它包括更多的内容,例如需求确认、系统分解、架构风格的选择(B/S还是C/S)、技术选型(Java还是.net,Oracle还是MySQL等)、物理架构设计、数据架构设计、逻辑架构设计等等,通常架构师还要参与包设计、核心模块设计以及类设计等概要设计和详细设计工作。正因为软件架构设计涉及的内容相当多,因此需要考虑的因素也很多。

软件架构设计需要考虑的问题包括需求、成本、进度、团队人员的素质等等,我觉得首先应该考虑的是需求。俗话说:需求进、架构出。如果没有深入分析需求,往往难以得到好的架构,在分析需求时除了功能需求外,还要考虑一些非功能需求,包括是否要与第三方系统兼容、是否要考虑到数据迁移、是否要考虑到平台的多样性等等,非功能需要中很多因素也会影响到架构,例如安全性、性能等等,因此好的架构师应该尽量多参与需求分析,听听客户的想法,需求是影响架构最大的因素,架构风格的选择、技术选型等都与需求息息相关。除此之外,成本、进度以及人员素质等对架构的影响也很大,因此在架构设计的时候也需要充分考虑。没有完美的设计方案,无论是SAAM还是ATAM等架构评估方法,其实都是一种折中的方法,无法使每一个因素都达到最优,所以我们要全盘考虑,具体问题具体分析,找出当前应用最合适的一种设计方案。

对于如何做好架构设计,我个人建议如下:

深入理解需求:错误的需求必定导致错误的架构,因此一定要深入理解需求,作为架构师,一个很重要的职责是进一步确认和细化需求,例如了解当前系统是否需要和别的系统交互,通过什么接口来交互,在交互的时候数据如何发送和接收等等,了解得越细致对于架构设计帮助越大,因此,一定要做好需求工作。
全面考虑非功能因素:很多软件项目的失败并不是因为功能的缺失或者错误,而是因为一些非功能因素考虑不周全,例如服务器的性能、最多容许的并发用户数、安全性等等。作为一名好的架构师,应该认识到当前系统最重要、最核心的质量属性是哪些,例如有些项目的核心是安全性,此时可能需要牺牲性能来提高安全性,这就需要和客户进行交流,做一些平衡,通盘考虑。可能还要专门就安全性来做专门的设计,例如在我曾经参与过的项目中,光一个安全性就需要做好几个层次的设计,有代码级的、数据库级的、功能级的、系统级的,但性能是肯定会要下降的。因此,在进行架构设计时要学会取舍,当然取舍的前提是已得到客户的认可。优秀的架构师会引导客户接受合理的架构方案,以确保系统能够真正投入使用。
构造合理的系统模型:建筑设计师都擅长绘图,同样作为一门工程学科,软件工程也需要绘制一些图,越大的项目需要的图越多,要求也越严格。这些图又可以称为模型,好的架构设计一定要有一套完整、合理的模型,包括数据模型(概念数据模型、逻辑数据模型和物理数据模型),结构模型(类图、包图、组件图和部署图等),动态模型(状态图、活动图和顺序图等)等,要熟练使用UML等技术来构造系统模型,这些图形也有助于进一步理解和验证架构的合理性,例如使用类图描述系统的类结构、使用包图描述系统的分层结构、使用组件图描述系统物理文件的联系以及与第三方库之间的交互、使用状态图描述核心业务对象的状态及其转换、使用活动图描述核心业务流程等等。在现代软件开发中,越来越多的软件公司都意识到建模的重要性,我也给一些软件公司做过UML建模技术的培训,发现很多公司在学完UML之后就能够将这些技术很好地用于实际的项目开发,特别是软件架构的设计,这与之前直接根据需求文档写代码,越写越盲目,最后还可能出现项目失败的情况相比,已经有了很大的改善。我目前也正在写一本UML相关的书,预计2013年能够发行,希望能够给广大开发人员提供帮助。
保证架构的稳定性和可扩展性:好的架构应该是稳定而又易于扩展的,因此在进行架构设计时要充分考虑这些因素,使用设计模式的目的实际上就是在一定程度上来保持架构的稳定性和可扩展性。因此,对于一名优秀的架构师而言,软件需求、软件质量属性、UML、设计模式等知识都是必须要具备的。
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后而言是非常丰硕的。这么年轻就取得如此高的成就,那成功秘诀在哪?当记者了解到他在大学时就已开始实践,当晓得他藏书几千册可以办小型图书馆,当他告诉我每天无论如何都会抽出两小时来学习,当看到他在七年前文章中写下这样一句话“所有的证书和荣誉都只代表过去,而我只憧憬未来”时,这一切都已了然。

猜你喜欢

转载自lee-govern.iteye.com/blog/1771789