精华内容
下载资源
问答
  • 对于人力资源的同事来说,画组织结构图是一键非常头疼的事情,尤其是对于一些大公司和人员变动较大的公司来说,需要经常更换组织结构图,每次变动都要耗费大量的时间和精力去重新绘图。其实绘制织结构图很简单,之...

    还在用PPT、Word和Excel画企业组织结构图吗?对于人力资源的同事来说,画组织结构图是一键非常头疼的事情,尤其是对于一些大公司和人员变动较大的公司来说,需要经常更换组织结构图,每次变动都要耗费大量的时间和精力去重新绘图。其实绘制织结构图很简单,之所以难是因为没有找对工具和方法!今天小编就教你如何用亿图图示轻松绘制一个既美观又专业的组织结构图!

    下图是一个简单的组织结构图例子,小编就以此为例,详细讲解一下好看清晰、实用的公司组织结构图是怎么画出来的。

    1、新建组织结构图

    2、创建组织结构

    从左侧符号库中,双击或者拖拽一个“职位”图形到绘图页面。

    3、增加下属

    将鼠标移动到图形上,就会出现一个按钮,点击,即可快速创建一个下属。

    点击多次按钮,可添加多个同级下属,如下图所示:

    同理,按照此操作一级一级的添加下属,就可以得到一个大概的组织结构框架:

    4、自定义显示域

    选中组织结构图,此时软件上方菜单栏就会出现“组织结构图”菜单,选择“定义域”,即可给形状添加可显示的属性。

    温馨提示:点击“定义属性:可自定义新的属性。

    5、修改显示选项

    点击显示选项,会弹出一个窗口,在定义域中添加的形状属性会全部显示出来,在这个界面可以选择需要显示的属性,也可以对各属性显示的字体样式、颜色、排列顺序进行调整。

    温馨提示:此操作可以适用于全部形状,也可以适用于选中的形状。

    6、替换文字

    单击选中需要修改文字的形状,直接输入文字就可以了。双击该形状也可以输入文字。

    温馨提示:如果绘图页面显示比例小于100%,在输入文字时,页面会自动还原到100%的状态。

    7、调整布局

    点击“市场营销部门”,在组织结构菜单的布局设置中,选择需要的布局类型。同理,按照此方法,将其他需要调整的形状进行设置就可以了。

    温馨提示:Ctrl+A键,全选整个组织结构图,可以一键进行调整整个布局,按住鼠标左键,选中需要调整的形状,可以对选中区域的形状进行修改。

    8、修改主题风格

    使用模板绘制的组织结构图的颜色,是软件默认主题的风格,可以在“页面布局”的主题设置中进行修改。

    9、修连接线样式

    选中需要修改的连接线,打开软件右侧工具栏,选择线条工具。

    在这里,可以对连接线、线条的颜色、宽度、透明度、线头样式、箭头样式等属性进行修改。

    温馨提示:通过“页面布局”菜单下的“连接线”工具,修改的样式会对整个绘图页面的连接线起作用,如果只需要对特定的连接线进行修改的,不建议从这里修改。

    10、为组织结构图添加标题

    从符号库中,选择一个标题条类型,将其拖拽至绘图页,标题条的颜色会根据已经设置好的主题颜色自动修改。双击标题的文字可对文字进行修改。

    11、添加其他符号

    在符号库旁边的搜索框中,输入需要插入的符号名字,将需要的图形拖到绘图页。

    温馨提示:两个图形若重叠显示,如上图所示的情况,可以通过“开始”–“置于顶层/底层”的方法决定图片显示的先后顺序。

    12、调整页面布局

    所有图形都画好之后,难免会发现,有些地方会多出很多空白的地方,图形显示位置不在居中位置,怎么办呢?

    很简单,鼠标右键,选择页面适应到绘图,或者在“页面布局中”选择页面适应到绘图。

    然后,再全选所有的图形,点击“开始”菜单的”居中“设置”,就可以将整个图形居中显示了。

    以上方法,只是亿图图示的一种基本操作方法,除了组织结构图模板、例子,后续教你通过一键导入数据快速创建组织架构图。

    展开全文
  • 此篇源出自我在公司内部写的一个PPT,它是用于在公司内部向广大技术人员做普及的一个资料,而CSDN这边的编辑不支持图文混排的效果,因此一些章节我就直接截取自我的PPT里的内容了,这样可能对大家在阅读上会显得...

    正文

    来点轻松的话题。我们调剂一下后再继续讲CAS SSO单点登录吧因为后面的内容全部和代码有关,大家会觉得枯燥。所以今天我们先来点”番外篇“,讲讲什么是架构师,什么是架构这个永恒的话题吧。此篇源出自我在公司内部写的一个PPT,它是用于在公司内部向广大技术人员做普及用的一个资料,而CSDN这边的编辑不支持图文混排的效果,因此一些章节我就直接截取自我的PPT里的内容了,这样可能对大家在阅读上会显得更加生动和活泼一些吧。

    架构的定义

    先来看看软件架构的普遍定义吧。

    一个程序和计算系统软件体系结构是指系统的一个或多个结构。结构中包括软件的构建,构建的外部可见属性以及它们之间的相互关系。

    体系结构并非可运行软件。确切的说,它是一种表达,使软件工程师能够:

    分析设计在满足规定需求方面的有效性。

    在设计变更相对容易的阶段,考虑体系结构可能的选择方案。

    降低与软件构造相关联的风险。

    软件架构的生命周期

    软件开发有其生命周期,它应该是:
    在这里插入图片描述

    而软件架构也有着其生命周期,它又是怎么样的呢?

    在这里插入图片描述

    软件架构的重要性

    为什么说一个软件架构是很重要的呢?直接编程直接开发,多EASY?请看下面几点:

    软件架构能够满足系统的品质

    架构设计使受益人达成一致的目标

    架构设计能够支持计划编制过程

    架构设计对系统开发的指导性

    架构设计能够有效地管理复杂性

    架构设计为复用奠定了基础

    架构设计能够降低维护费用

    架构设计能够支持冲突分析

    什么是好的软件架构

    这个问题,可能大家一直都在问,包括一些IT企业也在问,对于这个问题的回答,可能不仅仅是一个简单的语句或者是定义就可以回答的出的,我们来看下面的几个形象的例子:

    在这里插入图片描述

    这个是什么东东呢?乐高玩具,乐高玩具大家肯定都玩过吧?

    它即可以以一个完整的模型卖给你,你也可以把它全部打碎了重新从一个模型自由的再去组装成另一个模型,因为每一个乐高的模块在横向、坚向里都有标准的接口,这就是我们常说的高内聚、低耦合。

    什么又是糟糕的架构
    在这里插入图片描述

    大家看看上面这幅图是什么?

    一个是清代的八股文,一个是孔乙己。还记得回字的四种写法吗?那么你专门就研究回字的四种写法 ,但你有没有想过我把回字折开来又可以变成几个字?是否好折?

    要知道最时髦的并不一定是最好的
    在这里插入图片描述

    为什么M1A2和阿帕奇直升机里不用A8处理器,或者是最新的奔腾处理器啊?实用、经过检验的才是最好的!

    成功的软件又是怎么样的呢

    我们谈的是软件架构,架构的最终体现是一个软件,那么什么是成功的架构什么是成功的软件呢?
    在这里插入图片描述

    大家看左边的这个图,是美国的“阿利伯克级”宙斯盾驱逐舰,右边的是印度模仿美国的宙斯盾自己设计和建造的”德里级”的“咖喱盾”驱逐舰。

    两艘战舰一对比,怎么样?

    一个是模块化的设计,整体线条流畅,战损时模块可以任意替换。

    一个却是拼拼凑凑,线路外露,甲板上布满了各种电子设备和天线,一旦战损,极难维护

    架构之美

    架构,架构,到底什么是架构?我以前上大学时有一个70多岁的老教授,他上课每讲20分钟左右,需要2个同学”架“着去上一次WC,我们的架构师当然不是指这种”架构师“。那么我们一直说的架构,到底它是一个什么样的东西呢?怎么样又可以做出一个完美的架构呢?

    架构就像是迷踪拳

    动作轻灵敏捷,灵活多变,它其实违背一切传统拳法,因此可以克敌制胜。

    在这里插入图片描述

    架构就像是独孤九剑,破剑式、破枪式、无招胜有招,它发源于传统武术,又扩展了传统的武术

    干货 | 一个架构师谈什么是架构,以及怎么成为架构师

    架构就像是一件艺术珍品,有时一个看似简单的架构往往却是一件艺术珍品。

    干货 | 一个架构师谈什么是架构,以及怎么成为架构师

    大家知道这幅画吗?他是挪威画家蒙克的一幅作品叫”呐喊“,蒙克这个人是一个疯子,这幅画很简单,就是随手涂鸦一般,但是大家可知道这幅画值多少钱吗?2012年该画在纽约苏富比拍卖上以1.19亿美元被拍卖。

    架构的意境

    一个好的架构不应该受限于框架,受限于语言,受限于技术,受限于各种条条框框,它是一种意境。

    干货 | 一个架构师谈什么是架构,以及怎么成为架构师

    架构时需要考虑的几个基本因素

    干货 | 一个架构师谈什么是架构,以及怎么成为架构师

    JAVA通用领域的相关技术

    当然,我们这边主要说的是JAVA,那么作为一名学习JAVA、J2EE的架构师来说,要具备一些什么样的技能才能达到架构师的水平呢?

    干货 | 一个架构师谈什么是架构,以及怎么成为架构师

    上面这张图,我们这样来看,它分为3个部分:

    顶部,是我们需要掌握的一些技术领域的知识,它可以使我们应对通用领域如电商、企业OA、银行保险金融等领域的一些解决方案和设计

    中部,为了达到顶部这些技术我们需要了解的一些中间件、数据库、开发框架这些知识,它是一根支柱

    底部,底部呢?它是我们的基础,为铺设我们通向中间或者更上层的一个基石,这也是为什么大家有时发觉我的博客和其它博客有不一样的地方,不仅仅有编程还有”中间“的这一层即数据库、性能、安全、框架搭建这些东西混合在里面的原因,因为我不希望大家通过阅读完了我的博客还只是停留在一个码农、码工、螺丝钉的这种水平上。

    架构师的职能

    说了这么多架构,我们来说说架构师吧。

    干货 | 一个架构师谈什么是架构,以及怎么成为架构师

    大家看到了没有,架构师的第一职责就是关注:non-functional requirements,即非功能性需求。很多人对功能性需求和非功能性需求的界线划分还是不清楚,我这边举2个例子说明一下吧:

    功能性需求

    页面查询,这个查询是关联哪些哪些数据库表,因为我的业务是有这样这样的需求,在界面A里点了一个按钮,然后弹出窗口B,在窗口B里要显示什么样的数据,最后界面A里点完后,当我打开界面B时哪块数据已经随之发生了更改。

    非功能性需求

    我们的系统查询速度小于2S,是否考虑使用异步查询、使用队队列机制,系统要求可以容纳1000个并发,这个系统要可以做成插件式的,要可以横向扩展,要符合XXX协议,这个Webservice要做成SOAP HEAD内带有BASIC认证,还是做成符合NTLM的认证的,还是使用令牌环认证的?这个下拉框要做成即可输入又可以下拉的,这块认证要访问LDAP?

    很多以业务为主的项目型公司认为架构师就是trouble shooting(即排错、查错的意思,就是有错误、出问题了再找架构师),把架构师当成了fireman(救火员),可是你不自己想想为什么出了问题架构师过来2秒、2分钟或者1天半可以解决你们1个月几十人天天到零晨也解决不了的问题呢?嗯?

    解决了说这是人家应该的,解决不了,说人家架构师不合格呢?是不是我们应该从这个软件最早的框架上、架构上去发现一下问题呢?

    架构师啊,这不是一个trouble shooting的问题啊。

    在节前我也进行了一些面试,出于纯技术角度来说,即走架构师,TECH LEADER这样的路线的侯选人。我还是发觉了不少的问题这也是中国的一个通病:即我们的程序员,很多时候不是在做程序,而更多时候是在做业务逻辑,成了一个某一领域的业务人员了。

    当然,我们的程序员在其职业生涯的前3年、4年都是做某一块领域的代码的,这个是没有问题的,但是请一定一定记住,我们是编码,是IT,是程序员,不是“业务人员”!!!

    什么是IT?什么是程序员?什么是Tech Leader?什么是架构师?这个问题大家有必要好好的去问一下自己,去好好的想一下,架构师的要求是什么?

    我这边随便说一些东西:相信对一些要走技术道路的同学们是有帮助的:

    TCP/IP协议,加密解密,计算机原理(增补反码),JPG码,MPEG2-3协议,逻辑电子电路,计算机编译器原理(堆、栈、队列),这些东西你平时工作时一直用到吗?这些是你一直关注的底层吗?

    如果你是要走技术路线,一定一定请记得“数据库+ASP/JSP”不是技术,它只比表单制作,报表制作人员稍微强了那么一点点。

    请一定记住,技术路线关注的是非功能性需求,非功能性需求啊,就是一种一通百通的东西,有了这块底蕴,任何需求和你说清了,对你来说是没有任何“难度”的,或者你再去学,是可以举一反三的啊。

    最近一直面试一些侯选人,做架构师的,在此过程中我对此深有感受,找一个程序员开发不难,招一个架构师,难。。。唉,我觉得大家有必要要考虑一下,如果我走技术路线,我缺什么,我怎么补,还要关注些什么?

    科技是第一生产力,管理方法论中的所谓的六SIGMA即六西格玛的第一条就是“技术人才是当下企业的第一生产力”,大家看看能够发财的是哪些公司?阿里,淘宝,支付宝,GOOGLE, 通讯,互联网,高科技等等等一些企业,他们靠的不是业务逻辑,而是真正的技术,这足以说明问题了,所以大家如果要走技术道路,请多关注一下更细节,更底层的东西吧。

    这也是为什么我在之前的博文中所阐述的那些东西的原因,可见企业IT项目开发之七宗罪。

    第一宗罪:重业务不重技术

    第二宗罪:编程开发人员沦为业务开发人员、沦为码农

    第三宗罪:IT市场沦为自由市场、小菜场一样的叫买

    第四重罪:技术无用论的诞生

    第五宗罪:闭门造车,与实际脱节,完全抛弃业务

    第六宗罪:消极怠工

    第七宗罪:不思进取

    架构师的分类

    一般会把架构师分为:

    业务架构师即BA

    系统架构师SA

    其实从严格意义上业说架构师是可以分成三类的:

    一般就是把系统架构师和应用架构师合成一类。这个从本质上来讲倒没有什么太大的区别,不伤大雅。

    架构师会做什么

    一个架构师在一个团队中或者说在一个企业中它具体要做哪些日常工作呢?

    架构师并不是万能的

    架构师很牛B,可是架构师也是人,他不是超人。
    在这里插入图片描述

    架构师需要掌握的软技巧

    技术,是架构师的Hard Skill,那么架构师的Soft Skill有哪些呢?

    在这里插入图片描述

    架构师不是皇冠上的明珠

    大家一定一定要记住,架构师决不是像大家想像中的那样,是所谓的皇冠上的明珠,架构师承担的责任是相当的大的。
    在这里插入图片描述

    如何成为架构师

    人类是如何进化的?学习、使用工具、社会协作性、不断的总结经验。
    在这里插入图片描述

    架构师也会退化到比一般的程序员都不如。如果停止了学习的步伐,那么。。。。。。
    在这里插入图片描述

    谈架构师的自我修养

    学习之道

    在这里插入图片描述

    需要掌握的基本功中的基本功
    在这里插入图片描述

    大家注意,上面这个列表在学习时是有先后顺序的,从上至下分别为第一步,第二步,第三步。。。。。。不要觉得枯燥,你可以去试试,真的,被折腾着和被快乐着。Bad artist copy good artist steal

    在这里插入图片描述

    放正你的心态

    在这里插入图片描述

    不断的需要自我激励

    成功的唯一方法便是,承认现实,超越现实,鼓起勇气并善用它。

    学会平静的对待生活中的不完美之处,适应自己的情绪,了解如何让它们自然宣泄出去

    学习如何把不完美的地方转换成我们的优势,激发我们的创造力

    自我激励,不管外部条件是否有激励性,找到一种激发最佳状态的情绪,学习如何在我们的意识中制造一些波动来激励我们前进

    此文献给众IT技术人员和那些将要或想要走上IT道路的朋友们

    展开全文
  • /在稳定阶段,对功能齐全的解决方案进行最后的测试,使其成为稳定的解决方案,为其后的发布准备。/在部署阶段,将稳定、完善的解决方案完全部署为真正的产品。 37、MSF部署阶段交付成果包括:运营及支持信息系统/...
  • 新生代的开发人员没有使用分布式对象的经验,因此也就没有认识到这个主意多么糟糕,他们正试图重复历史,只是这次使用了新技术,比如HTTP取代了RMI或IIOP。 </li></ul> 微服务和Domain ...
  • XP非常强调简单的设计原则:能够数组实现的功能决不链表。...开发人员花在理解架构本身上的时间甚至超出了实现架构的时间。在前面的文章中,我们提到了一些反对象牙塔式架构的一个原因,而其中的一个原因就...
    XP非常强调简单的设计原则:能够用数组实现的功能决不用链表。在其它Agile方法中,简单的原则也被反复的强调。在这一章,我们就对简单性做一个全面的了解。
    Context
    架构应该设计到什么程度?
    Problem
    软件的架构都是非常的复杂的,带有大量的文档和图表。开发人员花在理解架构本身上的时间甚至超出了实现架构的时间。在前面的文章中,我们提到了一些反对象牙塔式架构的一个原因,而其中的一个原因就是象牙塔式架构的设计者往往在设计时参杂进过多的自身经验,而不是严格的按照需求来进行设计。
    在软件开发领域,最为常见的设计就是"Code and Fix"方式的设计,设计随着软件开发过程而增长。或者,我们可以认为这种方式根本就不能算是设计,它抱着一种船到桥头自然直的态度,可是在设计不断改动之后,代码变得臃肿且难以理解,到处充满着重复的代码。这样的情形下,架构的设计也就无从谈起,软件就像是在风雨中的破屋,濒临倒塌。
    针对于这种情形,新的设计方式又出现了,Martin Fowler称这种方式为"Planned Design"。和建筑的设计类似,它强调在编码之前进行严格的设计。这也就是我们在团队设计中谈到的架构设计师的典型做法。设计师们通常不会去编程,理由是在土木工程中,你不可能看到一位设计师还要砌砖头。
    "Planned Design"较之"Code and Fix"进步了许多,但是还是会存在很多问题。除了在团队设计中我们谈的问题之外,需求变更将会导致更大的麻烦。因此,我们理所当然的想到进行"弹性设计":弹性的设计能够满足需求的变更。而弹性的设计所付出的代价就是复杂的设计。
    题外话:
    这里我们谈论"Planned Design"引出的一些问题,并没有任何排斥这种方式的意思。"Planned Design"还是有很多可取之处的,但也有很多需要改进的地方。事实上,本文中我们讨论的架构设计方式,本质上也是属于"Planned Design"方式。和"Planned Design"相对应的方式是XP所主张的"Evolutionary Design"方式,但是这种方式还有待于实践的检验,并不能简单的说他就一定要比"Planned Design"先进或落后。但可以肯定的一点是:"Evolutionary Design"方式中有很多的思想和技巧是值得"Planned Design"借鉴的。
    Solution
    XP中有两个非常响亮的口号:"Do The Simplest Thing that Could Possibly Work"和"You Aren't Going to Need It"(通常称之为YAGNI)。他们的核心思想就是不要为了考虑将来,把目前并不需要的功能加到软件中来。
    粗看之下,会有很多开发人员认为这是不切实际的口号。我能理解这种想法,其实,在我热衷于模式、可重用组件技术的时候,我对XP提倡的简单的口号嗤之以鼻。但在实际中,我的一些软件因为复杂设计导致开发成本上升的时候,我重新思考这个问题,发现简单的设计是有道理的。
    降低开发的成本
    不论是模式,可重用组件,或是框架技术,目的都是为了降低开发的成本。但是他们的方式是先进行大量的投入,然后再节省后续的开发成本。因此,架构设计方面的很多思路都是围绕着这种想法展开的,这可能也是导致开发人员普遍认为架构设计高不可攀的原因。
    XP的方式恰恰相反,在处理第一个问题的时候,不必要也不可能就设计出具有弹性、近乎完美的架构来。这项工作应该是随着开发的演进,慢慢成熟起来的。我不敢说这种方式肯定正确,但是如果我们把生物的结构视同为架构,这种方式不是很类似于自然界中生物的进化方式吗?
    在一开始就制作出完美的架构的设想并没有错,关键是很难做到这一点。总是会有很多的问题是你在做设计时没有考虑到的。这样,当一开始花费大量精力设计出的"完美无缺"的架构必然会遇到意想不到的问题,这时候,复杂的架构反而会影响到设计的改进,导致开发成本的上升。这就好比如果方向错了,交通工具再快,反而导致错误的快速扩大。Martin Fowler在他的论文中说,"Working on the wrong solution early is even more wasteful than working on the right solution early"(提前做一件错事要比提前做一件对的事更浪费时间),相信也是这个道理。
    更有意思的是,通常我们更有可能做错。在我们进行架构设计的时候,我们不可能完全取得详细的需求。事实上,就算你已经取得了完整的需求,也有可能发生变化。这种情况下做出的架构设计是不可能不出错的。这样,浪费大量的时间在初始阶段设计不可能达到的"完美架构",倒不如把时间花在后续的改进上。
    提升沟通的效率
    我们在团队设计中已经谈过了团队设计的目标之一就是为了降低沟通的成本,以期让所有人都能够理解架构。但是如果架构如果过于复杂,将会重新导致沟通成本的上升,而且,这个成本并不会随着项目进行而降低,反而会因为上面我们提到的遇到新的问题导致沟通成本的持续上升。
    简单的架构设计可以加快开发团队理解架构的速度。我们可以通过两种方式来理解简单的含义。首先,简单意味着问题的解不会非常的复杂,架构是解决需求的关键,无论需求再怎么复杂多变,总是可以找出简单稳定的部分,我们可以把这个简单稳定的部分做为基础,再根据需要进行改进扩展,以解决复杂的问题。在示例中,我们提到了measurement pattern,它就是按照这种想法来进行设计的。
    其次,简单性还体现在表示的简单上。一份5页的文档就能够表达清楚的架构设计为什么要花费50页呢?同样的道理,能够用一副简单的图形就能够表示的架构设计也没有必要使用文档。毕竟,面对面的沟通才是最有效率的沟通,文档不论如何的复杂,都不能被完全理解,而且,复杂的文档,维护起来也需要花费大量的时间。只有在两种情况下,我们提倡使用复杂的文档:一是开发团队没有办法做到面对面沟通;二是开发成果要作为团队的知识积累起来,为下一次开发所用。
    考虑未来
    我们之所以考虑未来,主要的原因就是需求的不稳定。因此,我们如果考虑未来可能发生的需求变化,就会不知觉的在架构设计中增加复杂的成分。这违背的简单的精神。但是,如果你不考虑可能出现的情况,那些和目前设计格格不入的改变,将会导致大量的返工。
    还记得YAGNI吗?原则上,我们仍然坚持不要在现有的系统中为将来可能的情况进行设计。但是,我们必须思考,必须要为将来可能出现的情况做一些准备。其实,软件中了不起的接口的思想,不就是源于此吗?因此,思考未来,但等到需要时再实现。
    变更案例有助于我们思考未来,变更案例就是你在将来可能要(或可能不要)满足的,但现在不需要满足的需求。当我们在做架构设计的时候,变更案例也将会成为设计的考虑因素之一,但它不可能成为进行决策的唯一考虑因素。很多的时候,我们沉迷于设计通用系统给我们带来的挑战之中,其实,我们所做的工作对用户而言是毫无意义的。
    架构的稳定
    架构简单化和架构的稳定性有什么关系吗?我们说,架构越简单,其稳定性就越好。理由很简单,1个拥有4个方法和3个属性的类,和1个拥有20个方法和30属性的类相比,哪一个更稳定?当然是前者。而架构最终都是要映射到代码级别上的,因此架构的简单将会带来架构的稳定。尽可能的让你的类小一些,尽可能的让你的方法短一些,尽可能的让类之间的关系少一些。这并不是我的忠告,很多的设计类的文章都是这么说的。在这个话题上,我们可以进一步的阅读同类的文章(关于 refactoring 的思考)。
    辨正的简单
    因此,对我们来说,简单的意义就是不要把未来的、或不需要实现的功能加入到目前的软件中,相应的架构设计也不需要考虑这些额外的需求,只要刚好能够满足当前的需求就好了。这就是简单的定义。可是在现实之中,总是有这样或者那样的原因,使得设计趋向复杂。一般来说,如果一个设计对团队而言是有价值的,那么,付出一定的成本来研究、验证、发展、文档化这个设计是有意义的。反之,如果一个设计没有很大的价值或是发展它的成本超过了其能够提供的价值,那就不需要去考虑这个设计。
    价值对不同的团队来说具有不同的含义。有时候可能是时间,有时候可能是用户价值,有时候可能是为了团队的设计积累和代码重用,有时候是为了获得经验,有时候是为了研究出可重用的框架(FrameWork)。这些也可以称为目的,因此,你在设计架构时,请注意先确定好你的目的,对实现目的有帮助的事情才考虑。
    Scott W.Ambler在他的文章中提到一个他亲身经历的故事,在软件开发的架构设计过程中,花了很多的时间来设计数据库到业务逻辑的映射架构,虽然这是一件任何开发人员都乐意专研的事情(因为它很酷)。但他不得不承认,对用户来说,这种设计先进的架构是没有太大的意义的,因为用户并不关心具体的技术。当看到这个故事的时候,我的触动很大。一个开发人员总是热衷于新奇的技术,但是如果这个新奇技术的成本由用户来承担,是不是合理呢?虽然新技术的采用能够为用户带来效益,但是没有人计算过效益背后的成本。就我开发过的项目而言,这个成本往往是大于效益的。这个问题可能并没有确定的答案,只能是见仁见智了。

    例1.Java的IO系统
    从Java的IO系统设计中,我们可以感受到简单设计的困难。
    IO系统设计的困难性向来是公认的。Java的IO设计的一个目的就是使IO的使用简单化。在Java的1.0中,Java的IO系统主要是把IO系统分为输入输出两个大部分,并分别定义了抽象类InputStream和OutputStream。从这两个的抽象类出发,实现了一系列不同功能的输入输出类,同时,Java的IO系统还在输入输出中实现了FilterInputStream和FilterOutputStream的抽象类以及相关的一系列实现,从而把不同的功能的输入输出函数连接在一起,实现复杂的功能。这个实现其实是Decorator模式(由于没有看过源码和相关的资料,这里仅仅是根据功能和使用技巧推测,如果大家有不同的意见,欢迎来信讨论)。
    因此,我们可以把多个对象叠加在一起,提供复杂的功能:
    DataInpuStream in =
    new DataInputStream(
    new BufferedInputStream(
    new FileInputStream("test.txt");

    上面的代码使用了两个FilterInputStream:DataInpuStream和BufferedInputStream,以实现读数据和缓冲的功能,同时使用了一个InputStream:FileInputStream,从文件中读取流数据。虽然使用起来不是很方便,但是应该还是非常清晰的设计。
    令设计混乱的是既不属于InputStream,也不属于OutputStream的类,例如RandomAccessFile,这正表明,由于功能的复杂化,使得原先基于输入输出分类的设计变得混乱,根据我们的经验,我们说设计需要Refactoring了。因此,在Java1.1中,IO系统被重新设计,采用了Reader和Writer位基础的设计,并增加了新的特性。但是目前的设计似乎更加混乱了,因为我们需要同时使用1.0和1.1两种不同的IO设计。

    简单并不等于实现简单
    说到这里,如果大家有一个误解,认为一个简单的架构也一定是容易设计的,那就错了。简单的架构并不等于实现起来也简单。简单的架构需要设计者花费大量的心血,也要求设计者对技术有很深的造诣。在我们正在进行的一个项目中,一开始设计的基础架构在实现中被修改了几次,但每修改一次,代码量都减少一分,代码的可读性也就增强一分。从心理的角度上来说,对自己的架构进行不断的修改,确实是需要一定的勇气的。因为不论是设计还是代码,都是开发人员的心血。但跨出这一步是值得的。
    右侧的例子讨论了Java的IO设计,Java类库的设计应该来说是非常优秀的,但是仍然避免不了重新的修改。实际上,在软件开发领域,由于原先的设计失误而导致后来设计过于复杂的情况比比皆是(例如微软的OLE)。同样的,我们在设计软件的时候,也需要对设计进行不断的修改。能够实现复杂功能,同时自身又简单的设计并不是一件容易的事情。
    简单设计需要什么样的设计师
    简单的架构需要全面的设计师。什么才是全面的设计师,我的定义是既能够设计,又能够编码。我们在团队设计模式中就已经谈过象牙塔式架构和象牙塔式架构设计师。他们最容易犯的一个毛病就是设计和代码的脱离。从我们自己的经验来看,即使在设计阶段考虑的非常完美的架构,在编码阶段也会出现这样或那样的问题。从而导致架构实现变得复杂。最明显的特征就是在编码时出现了有大量方法的类,或是方法很长的类。这表明架构和代码脱钩了。在我们的开发过程中,不只一次出现这种现象,或者说,出现了坏味道(Bad Smell)。Refactoring的技巧也同样有助于识别坏味道。
    一次的架构设计完成后,开发人员可以按照设计,快速的编程。可在一段时间之后,新的特色不断的加入,我们发现代码开始混乱,代码量增大,可读性下降,调试变得困难,代码不可控制的征兆开始出现。我们就知道,架构的设计需要调整了。这属于我们在后面所提到的Refactoring模式。而我们在这里要说的是,如果架构的设计师不参与编码,它是无法感受到坏味道的,因此也就不会主动的对设计进行改进。要解决这个问题,最好的办法是让设计师参与代码的编写,尤其是重要架构的现实部分需要设计师的参与。如果设计师没有办法参与编码,那就需要一种机制,能够把代码反馈给设计师,让他在适当的时候,重新考虑改进架构。一个可能的办法是Code Review。让设计师审核代码,以确保编码者真正了解了架构设计的意图。
    例1.Java的IO系统
    从Java的IO系统设计中,我们可以感受到简单设计的困难。
    IO系统设计的困难性向来是公认的。Java的IO设计的一个目的就是使IO的使用简单化。在Java的1.0中,Java的IO系统主要是把IO系统分为输入输出两个大部分,并分别定义了抽象类InputStream和OutputStream。从这两个的抽象类出发,实现了一系列不同功能的输入输出类,同时,Java的IO系统还在输入输出中实现了FilterInputStream和FilterOutputStream的抽象类以及相关的一系列实现,从而把不同的功能的输入输出函数连接在一起,实现复杂的功能。这个实现其实是Decorator模式(由于没有看过源码和相关的资料,这里仅仅是根据功能和使用技巧推测,如果大家有不同的意见,欢迎来信讨论)。
    因此,我们可以把多个对象叠加在一起,提供复杂的功能:
    DataInpuStream in =
    new DataInputStream(
    new BufferedInputStream(
    new FileInputStream("test.txt");
    上面的代码使用了两个FilterInputStream:DataInpuStream和BufferedInputStream,以实现读数据和缓冲的功能,同时使用了一个InputStream:FileInputStream,从文件中读取流数据。虽然使用起来不是很方便,但是应该还是非常清晰的设计。
    令设计混乱的是既不属于InputStream,也不属于OutputStream的类,例如RandomAccessFile,这正表明,由于功能的复杂化,使得原先基于输入输出分类的设计变得混乱,根据我们的经验,我们说设计需要Refactoring了。因此,在Java1.1中,IO系统被重新设计,采用了Reader和Writer位基础的设计,并增加了新的特性。但是目前的设计似乎更加混乱了,因为我们需要同时使用1.0和1.1两种不同的IO设计。
    例2. measurement pattern
    在分析模式一书中有一个measurement pattern(测量模式),原来它是为了要解决现实中各种各样纷繁复杂的可测量的属性。例如,一个医疗系统中,可能会有身高多高,体重多种,血压多少等上千种可测量的属性。如果分别表示它们,必然导致系统复杂性的上升。因此measurement pattern就从这些属性的可测量的共性出发,研究新的解决方法,提出了measurement pattern的想法:
    如图所示,把可测量的属性(Measurement)做为Phenomenon Type的实例,此外,每一个的Person可以拥有多个的Measurement,同时,Measurement还对应处理的属性,例如图中的Quantity,就表示了Measurement的数量和单位。比如,一个人的体重是65公斤,那么,Phenomenon Type就是体重,Quantity的amount是65,units是公斤。

    no061-1.jpg
    图 5.牋 measurement pattern 的类图
    这其实是一个很简单的设计,但它清楚的表示了属性之间的关系,简化了数千种的属性带来的复杂性。此外,我们进一步思考,就会发现,这种架构只是针对目前出现属性众多的问题的基本解决方法,它还可以根据具体的需要进行扩展,例如,实现动态添加单位,或实现不同单位的转化等问题。
    因此,我们这里展示的其实是一种思考的方法,假想一下,当你在面对一个复杂的医疗系统时,大量的属性和不同的处理方式,你是不是可以从这样复杂的需求中找出简单的部分来呢?在我们架构设计的第一篇中,我们谈到架构设计的本质在于抽象,这里例子就是最典型的一个例子,在我们传统的想法中,我们都会把身高、体重等概念做为属性或是类,但是为了满足这里的需求,我们对这些具体的概念做一个抽象,提出可测量类别的概念,并把它设计为类(Phenomenon Type),而把具体的概念做为实例。这种抽象的思想在软件设计中无处不在,例如元类的概念。
    更深入的理解
    下一章中我们将会讨论迭代设计,其中还会涉及到简单设计的相关知识。建议可以将两章的内容结合起来看。

    (待续)
    作者简介:
    林星,辰讯软件工作室项目管理组资深项目经理,有多年项目实施经验。辰讯软件工作室致力于先进软件思想、软件技术的应用,主要的研究方向在于软件过程思想、Linux集群技术、OO技术和软件工厂模式。您可以通过电子邮件 iamlinx@21cn.com 和他联系。

    转载于:https://www.cnblogs.com/nianshi/archive/2007/04/02/697347.html

    展开全文
  • 五、简单设计 XP非常强调简单的设计原则:能够数组实现的功能决不链表。在其它Agile方法中,简单...开发人员花在理解架构本身上的时间甚至超出了实现架构的时间。在前面的文章中,我们提到了一些反对象牙塔式架构
     五、简单设计

      XP非常强调简单的设计原则:能够用数组实现的功能决不用链表。在其它Agile方法中,简单的原则也被反复的强调。在这一章,我们就对简单性做一个全面的了解。

      Context

      架构应该设计到什么程度?

      Problem

      软件的架构都是非常的复杂的,带有大量的文档和图表。开发人员花在理解架构本身上的时间甚至超出了实现架构的时间。在前面的文章中,我们提到了一些反对象牙塔式架构的一个原因,而其中的一个原因就是象牙塔式架构的设计者往往在设计时参杂进过多的自身经验,而不是严格的按照需求来进行设计。

      在软件开发领域,最为常见的设计就是"Code and Fix"方式的设计,设计随着软件开发过程而增长。或者,我们可以认为这种方式根本就不能算是设计,它抱着一种船到桥头自然直的态度,可是在设计不断改动之后,代码变得臃肿且难以理解,到处充满着重复的代码。这样的情形下,架构的设计也就无从谈起,软件就像是在风雨中的破屋,濒临倒塌。

      针对于这种情形,新的设计方式又出现了,Martin Fowler称这种方式为"Planned Design"。和建筑的设计类似,它强调在编码之前进行严格的设计。这也就是我们在团队设计中谈到的架构设计师的典型做法。设计师们通常不会去编程,理由是在土木工程中,你不可能看到一位设计师还要砌砖头。

      "Planned Design"较之"Code and Fix"进步了许多,但是还是会存在很多问题。除了在团队设计中我们谈的问题之外,需求变更将会导致更大的麻烦。因此,我们理所当然的想到进行"弹性设计":弹性的设计能够满足需求的变更。而弹性的设计所付出的代价就是复杂的设计。

      题外话:

      这里我们谈论"Planned Design"引出的一些问题,并没有任何排斥这种方式的意思。"Planned Design"还是有很多可取之处的,但也有很多需要改进的地方。事实上,本文中我们讨论的架构设计方式,本质上也是属于"Planned Design"方式。和"Planned Design"相对应的方式是XP所主张的"Evolutionary Design"方式,但是这种方式还有待于实践的检验,并不能简单的说他就一定要比"Planned Design"先进或落后。但可以肯定的一点是:"Evolutionary Design"方式中有很多的思想和技巧是值得"Planned Design"借鉴的。

      Solution  

      XP中有两个非常响亮的口号:"Do The Simplest Thing that Could Possibly Work"和"You Aren't Going to Need It"(通常称之为YAGNI)。他们的核心思想就是不要为了考虑将来,把目前并不需要的功能加到软件中来。

      粗看之下,会有很多开发人员认为这是不切实际的口号。我能理解这种想法,其实,在我热衷于模式、可重用组件技术的时候,我对XP提倡的简单的口号嗤之以鼻。但在实际中,我的一些软件因为复杂设计导致开发成本上升的时候,我重新思考这个问题,发现简单的设计是有道理的。

      降低开发的成本

      不论是模式,可重用组件,或是框架技术,目的都是为了降低开发的成本。但是他们的方式是先进行大量的投入,然后再节省后续的开发成本。因此,架构设计方面的很多思路都是围绕着这种想法展开的,这可能也是导致开发人员普遍认为架构设计高不可攀的原因。

      XP的方式恰恰相反,在处理第一个问题的时候,不必要也不可能就设计出具有弹性、近乎完美的架构来。这项工作应该是随着开发的演进,慢慢成熟起来的。我不敢说这种方式肯定正确,但是如果我们把生物的结构视同为架构,这种方式不是很类似于自然界中生物的进化方式吗?

      在一开始就制作出完美的架构的设想并没有错,关键是很难做到这一点。总是会有很多的问题是你在做设计时没有考虑到的。这样,当一开始花费大量精力设计出的"完美无缺"的架构必然会遇到意想不到的问题,这时候,复杂的架构反而会影响到设计的改进,导致开发成本的上升。这就好比如果方向错了,交通工具再快,反而导致错误的快速扩大。Martin Fowler在他的论文中说,"Working on the wrong solution early is even more wasteful than working on the right solution early"(提前做一件错事要比提前做一件对的事更浪费时间),相信也是这个道理。

      更有意思的是,通常我们更有可能做错。在我们进行架构设计的时候,我们不可能完全取得详细的需求。事实上,就算你已经取得了完整的需求,也有可能发生变化。这种情况下做出的架构设计是不可能不出错的。这样,浪费大量的时间在初始阶段设计不可能达到的"完美架构",倒不如把时间花在后续的改进上。

      提升沟通的效率

      我们在团队设计中已经谈过了团队设计的目标之一就是为了降低沟通的成本,以期让所有人都能够理解架构。但是如果架构如果过于复杂,将会重新导致沟通成本的上升,而且,这个成本并不会随着项目进行而降低,反而会因为上面我们提到的遇到新的问题导致沟通成本的持续上升。

      简单的架构设计可以加快开发团队理解架构的速度。我们可以通过两种方式来理解简单的含义。首先,简单意味着问题的解不会非常的复杂,架构是解决需求的关键,无论需求再怎么复杂多变,总是可以找出简单稳定的部分,我们可以把这个简单稳定的部分做为基础,再根据需要进行改进扩展,以解决复杂的问题。在示例中,我们提到了measurement pattern,它就是按照这种想法来进行设计的。

      其次,简单性还体现在表示的简单上。一份5页的文档就能够表达清楚的架构设计为什么要花费50页呢?同样的道理,能够用一副简单的图形就能够表示的架构设计也没有必要使用文档。毕竟,面对面的沟通才是最有效率的沟通,文档不论如何的复杂,都不能被完全理解,而且,复杂的文档,维护起来也需要花费大量的时间。只有在两种情况下,我们提倡使用复杂的文档:一是开发团队没有办法做到面对面沟通;二是开发成果要作为团队的知识积累起来,为下一次开发所用。

      考虑未来

      我们之所以考虑未来,主要的原因就是需求的不稳定。因此,我们如果考虑未来可能发生的需求变化,就会不知觉的在架构设计中增加复杂的成分。这违背的简单的精神。但是,如果你不考虑可能出现的情况,那些和目前设计格格不入的改变,将会导致大量的返工。

      还记得YAGNI吗?原则上,我们仍然坚持不要在现有的系统中为将来可能的情况进行设计。但是,我们必须思考,必须要为将来可能出现的情况做一些准备。其实,软件中了不起的接口的思想,不就是源于此吗?因此,思考未来,但等到需要时再实现。

      变更案例有助于我们思考未来,变更案例就是你在将来可能要(或可能不要)满足的,但现在不需要满足的需求。当我们在做架构设计的时候,变更案例也将会成为设计的考虑因素之一,但它不可能成为进行决策的唯一考虑因素。很多的时候,我们沉迷于设计通用系统给我们带来的挑战之中,其实,我们所做的工作对用户而言是毫无意义的。

      架构的稳定

      架构简单化和架构的稳定性有什么关系吗?我们说,架构越简单,其稳定性就越好。理由很简单,1个拥有4个方法和3个属性的类,和1个拥有20个方法和30属性的类相比,哪一个更稳定?当然是前者。而架构最终都是要映射到代码级别上的,因此架构的简单将会带来架构的稳定。尽可能的让你的类小一些,尽可能的让你的方法短一些,尽可能的让类之间的关系少一些。这并不是我的忠告,很多的设计类的文章都是这么说的。在这个话题上,我们可以进一步的阅读同类的文章(关于 refactoring 的思考)。

      辨正的简单

      因此,对我们来说,简单的意义就是不要把未来的、或不需要实现的功能加入到目前的软件中,相应的架构设计也不需要考虑这些额外的需求,只要刚好能够满足当前的需求就好了。这就是简单的定义。可是在现实之中,总是有这样或者那样的原因,使得设计趋向复杂。一般来说,如果一个设计对团队而言是有价值的,那么,付出一定的成本来研究、验证、发展、文档化这个设计是有意义的。反之,如果一个设计没有很大的价值或是发展它的成本超过了其能够提供的价值,那就不需要去考虑这个设计。

      价值对不同的团队来说具有不同的含义。有时候可能是时间,有时候可能是用户价值,有时候可能是为了团队的设计积累和代码重用,有时候是为了获得经验,有时候是为了研究出可重用的框架(FrameWork)。这些也可以称为目的,因此,你在设计架构时,请注意先确定好你的目的,对实现目的有帮助的事情才考虑。

      Scott W.Ambler在他的文章中提到一个他亲身经历的故事,在软件开发的架构设计过程中,花了很多的时间来设计数据库到业务逻辑的映射架构,虽然这是一件任何开发人员都乐意专研的事情(因为它很酷)。但他不得不承认,对用户来说,这种设计先进的架构是没有太大的意义的,因为用户并不关心具体的技术。当看到这个故事的时候,我的触动很大。一个开发人员总是热衷于新奇的技术,但是如果这个新奇技术的成本由用户来承担,是不是合理呢?虽然新技术的采用能够为用户带来效益,但是没有人计算过效益背后的成本。就我开发过的项目而言,这个成本往往是大于效益的。这个问题可能并没有确定的答案,只能是见仁见智了。

      简单并不等于实现简单

      说到这里,如果大家有一个误解,认为一个简单的架构也一定是容易设计的,那就错了。简单的架构并不等于实现起来也简单。简单的架构需要设计者花费大量的心血,也要求设计者对技术有很深的造诣。在我们正在进行的一个项目中,一开始设计的基础架构在实现中被修改了几次,但每修改一次,代码量都减少一分,代码的可读性也就增强一分。从心理的角度上来说,对自己的架构进行不断的修改,确实是需要一定的勇气的。因为不论是设计还是代码,都是开发人员的心血。但跨出这一步是值得的。

      右侧的例子讨论了Java的IO设计,Java类库的设计应该来说是非常优秀的,但是仍然避免不了重新的修改。实际上,在软件开发领域,由于原先的设计失误而导致后来设计过于复杂的情况比比皆是(例如微软的OLE)。同样的,我们在设计软件的时候,也需要对设计进行不断的修改。能够实现复杂功能,同时自身又简单的设计并不是一件容易的事情。

      简单设计需要什么样的设计师

      简单的架构需要全面的设计师。什么才是全面的设计师,我的定义是既能够设计,又能够编码。我们在团队设计模式中就已经谈过象牙塔式架构和象牙塔式架构设计师。他们最容易犯的一个毛病就是设计和代码的脱离。从我们自己的经验来看,即使在设计阶段考虑的非常完美的架构,在编码阶段也会出现这样或那样的问题。从而导致架构实现变得复杂。最明显的特征就是在编码时出现了有大量方法的类,或是方法很长的类。这表明架构和代码脱钩了。在我们的开发过程中,不只一次出现这种现象,或者说,出现了坏味道(Bad Smell)。Refactoring的技巧也同样有助于识别坏味道。

      一次的架构设计完成后,开发人员可以按照设计,快速的编程。可在一段时间之后,新的特色不断的加入,我们发现代码开始混乱,代码量增大,可读性下降,调试变得困难,代码不可控制的征兆开始出现。我们就知道,架构的设计需要调整了。这属于我们在后面所提到的Refactoring模式。而我们在这里要说的是,如果架构的设计师不参与编码,它是无法感受到坏味道的,因此也就不会主动的对设计进行改进。要解决这个问题,最好的办法是让设计师参与代码的编写,尤其是重要架构的现实部分需要设计师的参与。如果设计师没有办法参与编码,那就需要一种机制,能够把代码反馈给设计师,让他在适当的时候,重新考虑改进架构。一个可能的办法是Code Review。让设计师审核代码,以确保编码者真正了解了架构设计的意图。

       例1.Java的IO系统

      从Java的IO系统设计中,我们可以感受到简单设计的困难。

      IO系统设计的困难性向来是公认的。Java的IO设计的一个目的就是使IO的使用简单化。在Java的1.0中,Java的IO系统主要是把IO系统分为输入输出两个大部分,并分别定义了抽象类InputStream和OutputStream。从这两个的抽象类出发,实现了一系列不同功能的输入输出类,同时,Java的IO系统还在输入输出中实现了FilterInputStream和FilterOutputStream的抽象类以及相关的一系列实现,从而把不同的功能的输入输出函数连接在一起,实现复杂的功能。这个实现其实是Decorator模式(由于没有看过源码和相关的资料,这里仅仅是根据功能和使用技巧推测,如果大家有不同的意见,欢迎来信讨论)。

      因此,我们可以把多个对象叠加在一起,提供复杂的功能:

    DataInpuStream in = new DataInputStream( new BufferedInputStream( new FileInputStream("test.txt");



      上面的代码使用了两个FilterInputStream:DataInpuStream和BufferedInputStream,以实现读数据和缓冲的功能,同时使用了一个InputStream:FileInputStream,从文件中读取流数据。虽然使用起来不是很方便,但是应该还是非常清晰的设计。

      令设计混乱的是既不属于InputStream,也不属于OutputStream的类,例如RandomAccessFile,这正表明,由于功能的复杂化,使得原先基于输入输出分类的设计变得混乱,根据我们的经验,我们说设计需要Refactoring了。因此,在Java1.1中,IO系统被重新设计,采用了Reader和Writer位基础的设计,并增加了新的特性。但是目前的设计似乎更加混乱了,因为我们需要同时使用1.0和1.1两种不同的IO设计。

      例2. measurement pattern

      在分析模式一书中有一个measurement pattern(测量模式),原来它是为了要解决现实中各种各样纷繁复杂的可测量的属性。例如,一个医疗系统中,可能会有身高多高,体重多种,血压多少等上千种可测量的属性。如果分别表示它们,必然导致系统复杂性的上升。因此measurement pattern就从这些属性的可测量的共性出发,研究新的解决方法,提出了measurement pattern的想法:

      如图所示,把可测量的属性(Measurement)做为Phenomenon Type的实例,此外,每一个的Person可以拥有多个的Measurement,同时,Measurement还对应处理的属性,例如图中的Quantity,就表示了Measurement的数量和单位。比如,一个人的体重是65公斤,那么,Phenomenon Type就是体重,Quantity的amount是65,units是公斤。
    http://developer.ccidnet.com/pub/attachment/2003/5/185072.jpg

      图 5.牋 measurement pattern 的类图

      这其实是一个很简单的设计,但它清楚的表示了属性之间的关系,简化了数千种的属性带来的复杂性。此外,我们进一步思考,就会发现,这种架构只是针对目前出现属性众多的问题的基本解决方法,它还可以根据具体的需要进行扩展,例如,实现动态添加单位,或实现不同单位的转化等问题。

      因此,我们这里展示的其实是一种思考的方法,假想一下,当你在面对一个复杂的医疗系统时,大量的属性和不同的处理方式,你是不是可以从这样复杂的需求中找出简单的部分来呢?在我们架构设计的第一篇中,我们谈到架构设计的本质在于抽象,这里例子就是最典型的一个例子,在我们传统的想法中,我们都会把身高、体重等概念做为属性或是类,但是为了满足这里的需求,我们对这些具体的概念做一个抽象,提出可测量类别的概念,并把它设计为类(Phenomenon Type),而把具体的概念做为实例。这种抽象的思想在软件设计中无处不在,例如元类的概念。

      更深入的理解

      下一章中我们将会讨论迭代设计,其中还会涉及到简单设计的相关知识。建议可以将两章的内容结合起来看。

       六、迭代设计



      迭代是一种软件开发的生命周期模型,在设计中应用迭代设计,我们可以得到很多的好处。

      Context

      在软件生命周期中,我们如何对待架构设计的发展?

      Problem

      架构设计往往发生在细节需求尚未完成的时候进行的。因此,随着项目的进行,需求还可能细化,可能变更。原先的架构肯定会有不足或错误的地方。那么,我们应该如何对待原先的设计呢?

      我们在简单设计模式中简单提到了"Planned Design"和"Evolutionary Design"的区别。XP社团的人们推崇使用"Evolutionary Design"的方式,在外人看来,似乎拥护者们从来不需要架构的设计,他们采用的方式是一开始就进入代码的编写,然后用Refactoring来改进代码的质量,解决未经设计导致的代码质量低下的功能。

      从一定程度上来说,这个观点并没有错,它强调了代码对软件的重要性,并通过一些技巧(如Refactoring)来解决缺乏设计的问题。但我并不认同"Evolutionary Design"的方式,在我看来,一定程度上的"Planned Design"是必须的,至少在中国的软件行业中,"Planned Design"还没有成为主要的设计方向。借用一句明言,"凡事预则立,不预则废",在软件设计初期,投入精力进行架构的设计是很有必要的,这个架构是你在后续的设计、编码过程中依赖的基础。但是,一开始我们提到的设计改进的问题依然存在,我们如何解决它呢?

      在简单设计模式中,我们提到了设计改进的必要性,但是,如果没有一种方法去控制设计的改进的话,那么设计改进本身就是一场噩梦。因此,何时改进,怎么改进, 如何控制,这都是我们需要面对的问题。

      Solution

      为了实现不断的改进,我们将在开发流程中引入迭代的概念。迭代的概念在我的另一篇文章--《需求的实践》中已经提到,这里我们假设读者已经有了基本的迭代的概念。

      软件编码之前的工作大致可以分为这样一个工作流程:
    http://developer.ccidnet.com/pub/attachment/2003/5/185073.jpg.

    http://developer.ccidnet.com/pub/attachment/2003/5/185073.jpg.

      上图中的流程隐含着一个信息的损失的过程。来自于用户的需求经过整理之后,开发人员就会从中去掉一些信息,同样的事情发生在后面的过程中,信息丢失或变形的情况不断的发生。这里发生了什么问题?应该说,需求信息的失真是非常普遍的,我们缺少的是一种有效的办法来抑止失真,换句话说,就是缺少反馈。

      如果把眼睛蒙上,那我们肯定没有办法走出一条很长的直线。我们走路的时候都是针对目标不断的调整自己的方向的。同样的,漫长的软件开发过程如果没有一种反馈机制来调整方向,那最后的软件真是难以想象。

      所以我们引入了迭代周期。

      初始设计和迭代设计

      在团队设计中,我们一直在强调,设计组最开始得到的设计一定只是一个原始架构,然后把这个原始架构传播到每一位开发者的手中,从而在开发团队中形成共同的愿景。(愿景(Vision):源自于管理学,表示未来的愿望和景象。这里借用来表示软件在开发人员心中的样子。在后面的文章中我们会有一个章节专门的讨论架构愿景。)

      迭代(Iterate)设计,或者我们称之为增量(Incremental)设计的思想和XP提倡的Evolutionary Design有异曲同工之妙。我们可以从XP、Crystal、RUP、ClearRoom等方法学中对比、体会迭代设计的精妙之处:每一次的迭代都是在上一次迭代的基础上进行的,迭代将致力于重用、修改、增强目前的架构,以使架构越来越强壮。在软件生命周期的最后,我们除了得到软件,还得到了一个非常稳定的架构。对于一个软件组织来说,这个架构很有可能就是下一个软件的投入或参考。

      我们可以把早期的原始架构当作第一次迭代前的早期投入,也可以把它做为第一次迭代的重点,这些都是无所谓的。关键在于,原始架构对于后续的架构设计而言是非常重要的,我们讨论过架构是来源于需求的,但是原始架构应该来源于那些比较稳定的需求。

      TIP:现实中迭代设计退化为"Code and Fix"的设计的情况屡见不鲜("Code and Fix"参见简单设计)。从表面上看,两者的做法并没有太大的差别,都是针对原有的设计进行改进。但是,二者效果的差别是明显的:"Code and Fix"是混沌的,毫无方向感可言,每一次的改进只是给原先就已摇摇欲坠的积木上再加一块积木而已。而迭代设计的每一次改进都朝着一个稳定的目标在前进,他给开发人员带来信心,而不是打击。在过程上,我们说迭代设计是在控制之下的。

         从实践的经验中,我们发现,把原该在目前就该解决的问题退后是造成这一问题的主要原因之一。因此,请严格的对待每一次的迭代,确保计划已经完成、确保软件的质量、确保用户的需求得到满足,这样才是正统的迭代之路。

      单次的迭代

      我们说,每一次的迭代其实是一个完整的小过程。也就是说,它同样要经历文章中讨论的这些过程模式。只不过,这些模式的工作量都不大,你甚至可以在很短的时间内做完所有的事情。因此,我们好像又回到了文章的开头,重新讨论架构设计的过程。

      单次迭代最令我们兴奋的就是我们总是可以得到一个在当前迭代中相当稳定的结果,而不像普通的架构设计那样,我们深怕架构会出现问题,但又不得不依赖这个架构。从我们的心理上来分析,我们是在持续的建设架构中,我们不需要回避需求的变更,因为我们相信,在需求相对应的迭代中,我们会继续对架构进行改进。大家不要认为这种心理的改变是无关紧要的,我起初并没有意识到这个问题,但是我很快发现新的架构设计过程仍然笼罩在原先的惧怕改变的阴影之下的时候,迭代设计很容易就退化为"Code and Fix"的情形。开发人员难以接受新方法的主要原因还是在心理上。因此,我不得不花了很多的时间来和开发人员进行沟通,这就是我现实的经验。

      迭代的交错

      基于我们对运筹学的一点经验,迭代设计之间肯定不是线性的关系。这样说的一个原因架构设计和后续的工作间还是时间差的。因此,我们不会傻到把时间浪费在等待其它工作上。一般而言,当下一次迭代的需求开始之后,详细需求开始之前,我们就已经可以开始下一次迭代的架构设计了。

      各次迭代之间的时间距离要视项目的具体情况而定。比如,人员比较紧张的项目中,主要的架构设计人员可能也要担任编码人员的角色,下一次迭代的架构设计就可能要等到编码工作的高峰期过了之后。可是,多次的交错迭代就可能产生版本的问题。比如,本次的迭代的编码中发现了架构的一个问题,反馈给架构设计组,但是架构设计组已经根据伪修改的本次迭代的架构开始了下一次迭代的架构设计,这时候就会出现不同的设计之间的冲突问题。这种情况当然可以通过加强对设计模型的管理和引入版本控制机制来解决,但肯定会随之带来管理成本上升的问题,而这是不符合敏捷的思想的。这时候,团队设计就体现了他的威力了,这也是我们在团队设计中没有提到的一个原因。团队设计通过完全的沟通,可以解决架构设计中存在冲突的问题。

      迭代频率

      XP提倡迭代周期越短越好(XP建议为一到两周),这是个不错的提议。在这么短的一个迭代周期内,我们花在架构设计上的时间可能就只有一两个小时到半天的时间。这时候,会有一个很有意思的现象,你很难去区分架构设计和设计的概念了。因为在这么短的一个周期之内,完成的需求数量是很少的,可能就只有一两个用例或用户素材。因此,这几项需求的设计是不是属于架构设计呢?如果是的话,由于开发过程是由多次的迭代组成的,那么开发过程中的设计不都属于架构设计了吗?我们说,架构是一个相对的概念,是针对范围而言的,在传统的瀑布模型中,我们可以很容易的区分出架构设计和普通设计,如果我们把一次迭代看作是一个单独的生命周期,那么,普通的设计在这样一个范围之内也就是架构设计,他们并没有什么两样。但是,迭代周期中的架构设计是要遵循一定的原则的,这我们在下面还会提到。

      我们希望迭代频率越快越好,但是这还要根据现实的情况而定。比如数据仓库项目,在项目的初期阶段,我们不得不花费大量的时间来进行数据建模的工作,这其实也是一项专门针对数据的架构设计,建立元数据,制定维,整理数据,这样子的过程很难分为多次的迭代周期来实现。

      如何确定软件的迭代周期

      可以说,如果一支开发团队没有相关迭代的概念,那么这支团队要立刻实现时隔两周迭代周期是非常困难的,,同时也是毫无意义的。就像我们在上面讨论的,影响迭代周期的因素很多,以至于我们那无法对迭代周期进行量化的定义。因此我们只能从定性的角度分析迭代周期的发展。

      另一个了解迭代的方法是阅读XP的相关资料,我认为XP中关于迭代周期的使用是很不错的一种方法,只是他强调的如此短的迭代周期对于很多的软件团队而言都是难以实现的。

      迭代周期的引入一定是一个从粗糙到精确的过程。迭代的本质其实是短周期的计划,因此这也是迭代周期越短对我们越有好处的一大原因,因为时间缩短了,计划的可预测性就增强了。我们知道,计划的制定是依赖于已往的经验,如果原先我们没有制定计划或细节计划的经验,那么我们的计划就一定是非常粗糙,最后的误差也一定很大。但是这没有关系,每一次的计划都会对下一次的计划产生正面的影响,等到经验足够的时候,计划将会非常的精确,最后的误差也会很小。

      迭代周期的确定需要依赖于单位工作量。单位工作量指的是一定时间内你可以量化的最小的绩效。最简单的单位工作量是每位程序员一天的编码行数。可惜显示往往比较残酷,团队中不但有程序员的角色,还有设计师、测试人员、文档制作人员等角色的存在,单纯的编码行数是不能够作为唯一的统计依据的。同样,只强调编码行数,也会导致其它的问题,例如代码质量。为了保证统计的合理性,比较好的做法是一个团队实现某个功能所花费的天数作为单位工作量。这里讨论的内容实际是软件测量技术,如果有机会的话,再和大家探讨这个问题。

      迭代周期和软件架构的改进

      我们应用迭代方法的最大的目的就是为了稳步的改进软件架构。因此,我们需要了解架构是如何在软件开发的过程中不断演进的。在后面的文章中,我们会谈到用Refactoring的方法来改进软件架构,但是Refactoring的定义中强调,Refactoring必须在不修改代码的外部功能的情况下进行。对于架构来说,我们可以近乎等价的认为就是在外部接口不变的情况下对架构进行改进。而在实际的开发中,除非非常有经验,否则在软件开发全过程中保持所有的软件接口不变是一件非常困难的事情。因此,我们这里谈的架构的改进虽然和Refactoring有类似之处,但还是有区别的。

      软件架构的改进在软件开发过程会经历一个振荡期,这个振荡期可能横跨了数个迭代周期,其间架构的设计将会经历剧烈的变化,但最后一定会取向于平稳。(如果项目后期没有出现设计平稳化的情况,那么很不幸,你的项目注定要失败了,要么是时间的问题,要么就是需求的问题)。关键的问题在于,我们有没有勇气,在架构需要改变的时候就毅然做出变化,而不是眼睁睁的看着问题变得越来越严重。最后的例子中,我们讨论三个迭代周期,假设我们在第二个周期的时候拒绝对架构进行改变,那么第三个周期一定是有如噩梦一般。变化,才有可能成功。

      我们知道变化的重要性,但没有办法知道变化的确切时间。不过我们可以从开发过程中嗅到架构需要变化的气味:当程序中重复的代码逐渐变多的时候,当某些类变得格外的臃肿的时候,当编码人员的编码速度开始下降的时候,当需求出现大量的变动的时候。

      例子:

      从这一周开始,我和我的小组将要负责对软件项目中的表示层的设计。在这个迭代周期中,我们的任务是要为客户端提供6到10个的视图。由于视图并不很多,表示层的架构设计非常的简单:
    http://developer.ccidnet.com/pub/attachment/2003/5/185074.jpg

      准确的说,这里谈不上设计,只是简单让客户端访问不同的视图而已。当然,在设计的示意图中,我们并没有必要画出所有的视图来,只要能够表达客户端和视图的关联性就可以了。

      (架构设计需要和具体的实现绑定,但是在这个例子中,为了着重体现设计的演进,因此把不必要的信息都删掉。在实际的设计中,视图可能是JSP页面,也可能是一个窗口。)

      第一个迭代周的任务很快的完成了,小组负责的表示层模块也很顺利的和其它小组完成了对接,一个简陋但能够运转的小系统顺利的发布。客户观看了这个系统的演示,对系统提出了修改和补充。

      第二个迭代周中,模块要处理的视图增加到了30个,视图之间存在相同的部分,并且,负责数据层的小组对我们说,由于客户需求的改进,同一个视图中将会出现不同的数据源。由于我们的视图中直接使用了数据层小组提供给我们的数据源的函数,这意味着我们的设计需要进行较大的调整。

      考虑到系统的视图的量大大的增加,我们有必要对视图进行集中的管理。前端控制器(Front Control)模式将会是一个不错的技巧。对于视图之间的普遍的重复部分,可以将视图划分为不同的子视图,再把子视图组合为各种各样的视图。这样我们就可以使用组合(Composite)模式:

    http://developer.ccidnet.com/pub/attachment/2003/5/185075.jpg

      客户的请求集中提交给控制器,控制器接受到客户的请求之后,根据一定的规则,来提供不同的视图来反馈给客户。控制器是一个具有扩展能力的设计,目前的视图数量并不多,因此仍然可以使用控制器来直接分配视图。如果视图的处理规则比较复杂,我们还可以使用创建工厂(Create Factory)模式来专门处理生成视图的问题。对于视图来说,使用组合模式,把多个不同数据源的视图组合为复杂的视图。例如,一个JSP的页面中,可能需要分为头页面和尾页面。

      项目进入第三个迭代周期之后,表示层的需求进一步复杂化。我们需要处理权限信息、需要处理数据的合法性判断、还需要面对更多的视图带来的复杂程度上升的问题。

      表示层的权限处理比较简单,我们可以从前端控制器中增加权限控制的模块。同时,为了解决合法性判断问题,我们又增加了一个数据过滤链模块,来完成数据的合法性判断和转换的工作。为了不使得控制器部分的功能过于复杂,我们把原先属于控制器的视图分发功能转移到新的分发器模块,而控制器专门负责用户请求、视图的控制。


    http://developer.ccidnet.com/pub/attachment/2003/5/185077.jpg

     我们来回顾这个例子,从迭代周期1中的需求最为简单,其实,现实中的项目刚开始的需求虽然未必会像例子中的那么简单,但一定不会过于复杂,因此迭代周期1的设计也非常的简单。到了迭代周期2的时候,需求开始变得复杂,按照原先的架构继续设计的话,必然会导致很多的问题,因此对架构进行改进是必要的。我们看到,新的设计能够满足新的需求。同样的,迭代周期3的需求更加的复杂,因此设计也随之演进。这就是我们在文章的开始提到的"Evolutionary Design"的演进的思想。

     

    - 作者: javant 2005年01月1日, 星期六

    展开全文
  • 软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或成为领域层)、表示层. 二、三层结构的优点 1、开发人员可以只...
  • 五、简单设计 XP非常强调简单的设计原则:能够数组实现的功能决不链表。在其它Agile方法中,...开发人员花在理解架构本身上的时间甚至超出了实现架构的时间。在前面的文章中,我们提到了一些反对象牙塔式架构
  • 软件设计规范

    2015-03-11 11:57:50
    软件编制是专业人员的事情,因此语言问题的本质其实不那么重要。须知,经过培训,莫尔司码的电报发报可以比说话的语速还快!因此,计算机语言的前途迷茫;实际上也确实迷茫,历史上语言的层出不穷本身就说明了问题...
  • 及网站开发人员建立大型网站,使网站能够被管理,充满魅力,并且易于 户浏览。 新版《Web信息架构:设计大型网站》针对新技术了全面更新??搭 配新颖范例、全新场景及最佳实践信息??但是,其焦点依然放在基础原理...
  • 软件工程教程

    热门讨论 2012-07-06 23:10:29
    产生的原因(软件开发人员的错误观点): “有一个对目标的概括描述就足以着手编写程序了,许多细节可以在以后再补充” “所谓软件开发就是编写程序并设法使它运行” “用户对软件的要求不断变化,然而软件是柔软而...
  • 简约之美-软件设计之道

    热门讨论 2012-12-29 09:38:40
    什么软件设计成了一门缺失的科学软件和优秀软件设计的终极目标确定现在以及将来软件设计的价值所在真实案例证明系统如何随时间变化而变化好的设计,能适应外界尽可能多的变化,而软件自身的变化尽可能少代码越...
  • 软件工程知识点

    2012-12-02 21:34:25
    软件定义是软件项目的早期阶段,主要由软件系统分析人员和用户合作,针对有待开发的软件系统进行分析、规划和规格描述,确定软件什么,为今后的软件开发准备。这个时期往往需要分阶段地进行以下几项工作。 1....
  • 创建一种新的软件项目架构,来封装离散服务,对于全新的项目来说,这是非常简单的。但是,对于大多数软件开发者来说,谁又有大把的奢侈时间一直在全新项目上呢? 大多数软件开发人员职责更多是维护或增加现有软件...
  • 最近开始接触需求调研、设计。...我们一位经验丰富的成员说需求调研只要记住三要素:组织架构,业务流程,表单,即搞清楚:什么人、用什么表单、什么业务。这3样搞清楚了,就可以开始需求设计了。醍
  • 控制过度消费通过记账,你会很清楚地知道自己的钱都用来什么,关于每分钱的去处心中都明明白白, 哪些是必要的开销,哪些是非理性的、应该避免的花费,分别占有多大的比例。有专家统计,个人 或者家庭的年节余...
  • 在这一年,全世界的开发人员都开始习惯容器测试自己的软件容器线上发布,开始对容器化的软件构建和交付流程习以为常。全世界的架构师们都在对“云原生”侃侃而谈,描绘多云时代的应用治理方式,...
  • 持续交付-发布可靠软件的系统方法

    热门讨论 2014-03-02 01:32:14
    Jez Humble编著的《持续交付(发布可靠软件的系统方法)》讲述如何实现更快、更可靠、低成本的自动化软件交付,描述了如何通过增加反馈,并改进开发人员、测试人员、运维人员和项目经理之间的协作来达到这个目标。...
  •  第3章对MySQL软件的源代码以及如何获得和构建一个MySQL系统了全面的介绍。主要内容包括MySQL源代码的内部机制以及编码指导原则和如何维护源代码的最佳实践。  第4章介绍了生成高质量MySQL系统扩展的一个关键...
  • 作者以自己在苹果、网景等公司中面临的生死攸关的时刻所的抉择为例,总结了在硅谷摸爬滚打的经验,旨在为软件工程师更好地规划自己的职业生涯提供帮助。  《持续交付--发布可靠软件的系统方法》适合软件工程师...
  • CRM客户销售管理软件B/S

    热门讨论 2012-08-09 15:56:22
    销售人员却感叹公司销售计划无序可循,走向市场如同走向迷宫,只知道该完成多少销售任务,但如何完成,每天该做什么,任务分哪几个部分,每一步该怎么? 团队各自为阵: 公司多个部门与某个客户有工作关系和...
  • 软件研发这个词包含了两个意思,第一是架构设计,即决定一个系统采用什么样的架构,怎么,通常这是系统分析师或者架构师的责任,系统分析师是比较传统的叫法,现代互联网公司往往喜欢用架构师来替代;第二是代码...
  • 需要教导项目成员的内容

    千次阅读 2012-05-15 16:47:16
    什么样的要求才是合格的、适合开发人员使用的?怎么反思会?怎么单元测试?怎么划分组件、模块?怎么提有效的需求?例图,用例文档为什么要OO,OO老了吗?无论时间多紧,分析设计必须要。怎么职业规划?...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 257
精华内容 102
关键字:

做人员架构用什么软件