http://www.xio.name/XiorkFlow/
http://www.xio.name/XiorkFlow/
MFC有几个未公开的函数很有用,AfxExtractSubString()就是其中之一。你在MSDN文档里是找不到关于这个函数的说明的,但是你如果研究过MSDN里的例子程序的话,就会发现很多代码中都使用了这个函数。它的功能简单说来就是从某个用NULL或者换行符"n"分割的字符串中吸取子串。
CString str = "123,456,789";
CString output = "";
for (int i=0; i<3>
一、朝令夕改的老板。这样的老板可能会不断地给你新指示,你花费许多时间策划的方案,老板可能在实行3天后取消,或者花费数月酝酿的一个计划,可能因为他一句话而宣布作废。这样的公司上上下下天天都会很忙,但大家忙的都是收拾残局、挖东墙补西墙。
二、鱼与熊掌都想兼得的老板。这类老板既要马儿跑,又要马儿不吃草,到头来二者都得不到。他们常常会因小而失大,既不知何所取,也不知何所舍。
三、多疑的老板。这样的老板所持的观念是人治胜过规章制度,这类公司通常没有上轨道的制度。如果你是一个部门主管,经常会在非工作时间接到老板的电话;如果你是基层员工,他也经常会对你表示不痛不痒的“关切”。跟着这样的老板工作,心理负担之重可想而知。
四、言行不一的老板。这类老板最常说的一句话就是:“赚这么多钱对我并没有什么意义。”实际上,利润是公司生存的惟一命脉,又何必加以否认呢?
五、爱听甜言蜜语的老板。一般说来,老板不可能听到批评还会心花怒放,但如果连善意的批评和宝贵的建议也听不进去,并因此影响了员工在公司的发展,则人人都会噤若寒蝉。
六、心胸狭窄的老板。这样的老板看不得员工的成长和发展,更不会创造条件让你事业有成。
1.UI层,FLASH件:
var param1:String;
var URLpreFix:String;
//设置服务器URL文件,根据实际自定义
URLpreFix = "http://localhost:5689/flashtext/WebForm1.aspx";
bt.onRelease = function() {
//LoadVars 类是 loadVariables() 函数的替代方法,用于在 Flash 应用程序和服务器之间传输变量。
var myLoadVars = new LoadVars();
_root.onEnterFrame = function() {
if (_root.yuan.hitTest(_root.juxing)) {
txt = "<workflow></workflow>";
}
else
{
txt = "";
}
}
//txt是场景里面的一个文本变量
//把txt变量的值传给LoadVars类对象
myLoadVars.txt = txt;
//发送给服务器,可使用HTTP 协议的 GET 或 POST 方法。
myLoadVars.sendAndLoad(URLpreFix, myLoadVars, "post");
_root.lb.text="正在加载数据...";
//得到服务器是否成功返回数据,success是成功标志,成功时返回true
myLoadVars.onLoad = function(success) {
//如果成功把lb的文本换成服务器返回的变量值
if (success) {
_root.lb.text = this.txt;
} else {
_root.lb.textt = "异常错误!";
}
};
};
2.DLL层,ASPX文件:新建一“asp.net web 应用程序”,位置为http://localhost/flashtext/,然后把转到HTML设计介面,把HTML代码删除掉,只保存以下这行代码(ASP.NET是采用codebehind设计,默认VS会自动产生一些HTML代码),
3.DLL层,ASPX.cs文件:点开WebForm1.aspx.cs设计类文件,输入代码,用于Request FLASH送过来的数据而提交商业逻辑层处理,完整如下:
@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="flashtext.WebForm1" %>
这个很重要,因为如果没有删除,等一下运行,服务器会返回这些HTML代码给UI层,使之产生错误。
{
{
{
{
{
4.DLL层,运行商业逻辑:新建一个新类,名为testClass.cs,用于整个demo简单的商业逻辑处理(在此你可以完全去处理与数据库相关处理等等),只返回一行数据,代码如下:
{
{
{
{为了让更多的朋友能了解天人合一在生命中的意义.本文简介一下如何论命的.当然,如果已经是行内人的话,就不必费心了.
自古有句话,医易同源.就是说中医和易经是同出一源的,都是根据天文学而来的.人在大自然的环境中,要受到自然的影响,春夏秋冬,寒暑燥湿,风雨雷电,都会对人的生理和心理产生影响,进而成为群体性的行为,更进而变成社会行为.古人用天干地支来研究这种现象.天干就是:甲乙丙丁戊已庚辛壬癸;地支是:子丑寅卯辰巳午未申酉戌亥.古代,天干是用来给帝王当名字的,原因是什么则已无法考证了.天干代表天象,地支代表地象,地支中有人象,即地支是天干的根,有天干的气在,如子是癸水,丑是已癸辛,寅是甲戊丙,卯是乙,辰是戊癸乙,巳是丙戊庚,午是丁已,未是已乙丁,申是庚戊壬,酉是辛,戌是戊丁辛,亥是壬甲.这叫地支藏的人元.中国文化中,万物皆有阴阳,如白天是阳,晚上是阴,男人是阳,女人是阴.天干地支也分阴阳.甲丙戊庚壬为阳,乙丁已辛癸为阴,子寅辰午申戌是阳,丑卯巳未酉亥是阴.中国古人认为世间蛭锒加晌逯制?鄱??因为气是流动的,所以叫五行,即木火土金水.天干地支分为五行,甲乙为木丙丁为火戊已为土,庚辛为金,壬癸为水;寅卯辰为木,巳午未为火,申酉戌为金,亥子丑为水;在时空方面.春为木为东方,夏为火为南主,秋为金为西方,冬为水为北方.
古人总结出世间的各种关系,无非是五大种,即五行的相生相克关系.以我为中心,即生我者为印,我生者为食神伤官,克我者为官,我克者为财,与我一样的为比肩劫财.因为一种关系有阴阳,所以有十种,命理专用名称为"十神"如金克木,木克土,土克水,水克火,火克金;这是相克关系,金生水,水生木,木生火,火生土,土生金,这是相生.知道了这个道理,就可以学习中国传统文化中的很多方法,来研究生命和各种现象了.
如何算命呢?先要学会排一个人的四柱,即八字,就是将一个人的年,月,日,时,的天干和地支排出来.先排年,如今年零五年是乙酉年出生的,年柱为乙酉,本月是已卯月,月就是已卯,今天是丙午日,如果是中午生的人就是甲午时,这就是这个人的八字.乙酉/已卯/丙午/甲午.年从每年的立春算起,如今年二月四日丑时立春,在此时以前出生的,年柱为甲申年,算去年的,此时以后出生的,才算乙酉年;月是按节气算,如三月五日戌时是惊蛰,在此以前,二月四日丑时以后出生的,算上个月的,戊寅月,在此以后出生的,四月五日清明以前出生的算已卯月,即月是以每月的节气为界限的.日可查万年历,或用推算的.时则是按十二时辰来,晚上十一点开始算子时,以后每二个小时按地支顺序分别为丑,寅卯等.知道年推月有口诀:甲已之年丙年首,乙庚之年戊为头,丙辛必定寻庚上,丁壬壬寅顺水流,若问戊癸何方发,甲寅之上好追求.就是说,逢甲年或已年开关的,如去年甲申年或九九年已卯年,其正月,寅月的天干必是丙,为丙寅月,二月卯则为丁卯月,以此类推.知道日推时辰也是同样有口诀:甲已还生甲,乙庚丙作初,丙辛从戊起,丁壬庚子居,戊癸何方发,壬子是真途.就是说,甲日或已日生人,或是子时,其时柱必为甲子时,丑时为乙丑时,以此类推.
学会排八字后,要会起大运.大运每十年一周期,以月柱为起点,阳男阴女顺推,反之逆谁.如前例乙酉年已卯月丙午日甲午日生人,若是男命,是阴男,则其大运为逆推,分别是戊寅/丁丑/丙子/乙亥/甲戌/癸酉/壬申,一般排八步,如是女的则是阴女,顺推,则为庚辰/辛巳/壬午-------;如何计算几岁起运呢?也是从节气算起.中国的律法中,阴阳合历有二十四节气.口诀为:春雨惊春清谷天,夏满芒夏暑相连,秋处露秋寒霜降,冬雪雪冬小大寒,每月两节日期定,最多相差一两天.如一月两节是立春和谷雨,前面的立春是节,后面的谷雨是中气,论命以前面的节气为界,入了节,才算进入了该月.以一个人的出生日算,同样的年命阳男阴女顺行,阴男阳女逆行到最近的一个节气.看有几天几个时辰,一个时辰为十天,三月为一岁.如今天上例出生的男命,是阴命,所以起运的时间要逆行到三月五日戌时,共十八天差三个时辰,所以,此人是六岁差三十天上大运,如是女命,则顺行至四月五日子时清明,共十二天又六个时辰,则此女是四岁又二个月起运.大运为一个人在十年中的大趋势,前五年以天干为主,后五年以地支为主,兼顾为佳.
会排大运后,每年的运气就叫流年,每月就叫流月,每天就叫流日,象流水一般.
然后开始论命.以日柱的天干为自己,称为日元或命主.然后看这个天干和其他的各个字的关系.如上例,日主为丙.也就是说,不论男女,这个人的命是丙火.再分析一下命主的大概情况.首先看他生在什么样的时节.生在春天卯月,卯属乙木,木能生丙火,说明生命力有来源;叫得令;然后看他是什么时夺胜的,是午时,正是太阳高照的进候,所以火更旺,因此叫身得逢时,再看年和时的干都是乙木和甲木,都来生他,所以叫得势,这么多的力量来帮他,这个人就可以做很多事了.做什么呢?看他命中有什么?首先看到的是月干有已土,是他的伤官,是他生的,就是思想行为,所以,这是个喜欢行动的人,爱表现,敢冲;再看年支有酉金,是他的正财,主时此人祖上有正财,但和月支卯木相冲,说明母亲和祖母关系不好,还有和姑姑也不好.再看看,这个人一生大概走什么运,如是男的,大运如上,就是逆行,先是北方水地后东方木地,水能克火,使这个人有压力,也变成了动力,所以六岁到三十六岁,还是能够安份的,也比较努力,但后面木运生火,就不太好了.因为,论命的基本原则是,一个人的命和运要相和谐.命局要中和,阴阳平衡,命中不平衡的就要靠运来补.如果命很平衡就叫好命了,走什么运都可以,如果命不平衡,但在运中得到补充,就叫命运相济,就是可能运来大发,运去大败了.
这就是算命的基本原理.当然,要学会算命,还要努力去学习和实践.最基本的入门书是:宋人徐子升总结的[[渊海子平]],所以算命术也叫子平术;高级阶段要看宋人京图的[[滴天髓]].当然还有其他人的论著.近人复旦毕业的民国年间的才子韦千里的[[千里命稿]
.NET下写程序来实现邮件发送,还真是个不大不小的问题,上网找了一下,好象经常用的有5大方法, (1):调用OUTLOOK组件,调用的是OFFICE里面的OUTLOOK组件.对组件的依赖性比较高. (2):调用.NET自带的System.Web.Mail类,发送的附件比较大时,会有点问题. (3):使用System.Net.Sockets,利用Sockets进行网络编程开发,代码量较大. (4):IIS SMTP自带的基本的发信组件CDONTS,这个用的人比较少. (5):最后说说,调用Jmail组件,现在本人的所做的项目中也是用它来发送的,点击这里看原码!
1.经过分析,工作流的流程定制可以在页面中完成,但是这就不能采用集成在WWF中的Activity控件,但是可以采用其他的形式来向服务器端传输流程定制信息,比如flash,目前flash已经开发出了针对.Net的插件,提供了一些接口。这样就可以在表现层采用flash做流程定制的表象。
2.我尝试采用经典的MVC模式进行asp.Net2的开发,因为它的结构清晰,易于捆绑WWF,但是由于我之前没有接触过经典的MVC模式(尤其是.net),所以研究基于.net的MVC也会花费一些时间.
3.对于采用flash形式来向服务器端传输流程定制信息,我还有一个问题,那就是WWF中的Activity控件对于程序员来说可以理解,但是用户理解起来就比较费劲,所以还要考虑如何将WWF中的Activity控件转化或组合成用户易于理解的Activity。
简介
通过使用WWF,你可以创建基于处理器流的工作流并且把它们部署在任何类型的.NET应用程序中。此外,本文还讨论了ASP.NET开发者面对的一些特有的问题-这些问题可能通过使用工作流得到解决,如维持状态和页面导航等。
在2005年9月,微软在它的一年两次的专业开发者会议上公开了Windows Workflow Foundation(WWF,Windows工作流基础)。作为WinFX API的支柱之一,WWF提供给开发者一个普通框架-在其上开发过程驱动的和以工作流为中心的应用程序。
当前,有些组织力图把整个商业过程自动化;他们的标准答案就是集合一队开发者来开发相应的代码。尽管这种方式对于这些组织带来良好的作用,然而也有一些固有的问题。为了深入理解这一问题,你需要理解一个工作流的基本特征。
一个工作流本质是一种方法-用来归档包含在完成一个单元的工作中的活动。典型地,在处理过程中,工作"流"流过一项或更多活动。这些活动可以通过机器或人工来实现,并且有可能象在一个互联网应用程序定义页面顺序一样得简单,也有可能象管理必须为任何数目的人都要看到、更改并同意的文件或产品一样得复杂。
因为如此多的工作流必须考虑到人工参预,所以可能需要花费很长工期才能完成,时间可能为几小时到数月或更长。例如,参预在该过程中的人可能无法找到,不在本地或忙于另外的任务;因此,工作流必须在所有非活动期间能够把自身持续性存储。而且,通过编码独立实现的过程可能对非技术人员难于理解而对开发者却难于更改。这一点和其它一些因素正是例如WindowsWF等通用工作流框架的目标-其目的就在于使创建、改变和管理工作流更容易-这是通过向它们提供一个可视化接口或通过定义一组普通API来实现的。
你可以把WWF工作流放置在任何类型的.NET应用程序中-包括Windows表单程序,控制台应用程序,Windows服务和ASP.NET Web应用程序。每种类型都需要专门的考虑。尽管一些现有示例已经足够说明如何把工作流宿主到Windows表单程序和控制台应用程序中,但是本文将集中于讨论ASP.NET开发者的问题-他们希望把工作流集成到自己的应用程序中。
作者注:本文所提供的代码是以Windows WF Beta 1和Visual Studio 2005 Beta 2 为工具创建的。你可以在www.windowsworkflow.net找到有关安装Windows WF的信息。尽管本文讨论了Windows WF的一些基础问题,但是还有其它一些这方面的可用资源。我假定读者至少了解一点Windows WF。本文的目的是深度分析Windows WF和ASP.NET,而不是从一个高层次上讨论Windows WF。
一、 Windows WF和MVC模式
在开发一个ASP.NET应用程序时,你可能使用WWF的一个普通的方法是实现一种模型-视图-控制器(MVC)方法。实质上,MVC的目标是把描述层、应用程序逻辑和应用程序流逻辑分离开来。
搞清楚这个将十分有益于一个ASP.NET应用程序的开发,请考虑一个帮助桌面票工作流的场所。假定有一个商业用户通过填写一个ASP.NET Web表单并点击一个提交按钮来启动该工作流。接下来,服务器就会通知一个使用Windows表单应用程序和帮助桌面的雇员--"有新票可用了"。该帮助桌面雇员然后将在这一问题上工作,并在最后关闭该票。如果使用Windows WF来开发这个工作流情形,那么所有的处理逻辑和流程可以被包含在工作流本身,而该ASP.NET应用程序将完全不需要了解这一逻辑。
这种场所提供了一些稳固的证据-把描述与逻辑相分离是一件好事情。因为这个处理帮助桌面请求的过程是非常普通的,如果使用C#或VB.NET代码在若干不同的.NET应用程序中实现这一逻辑,那么你将会冒着重复编码的危险甚至更坏的情形--用完全不同的代码导致同样的商业处理过程的不同实现。但是如果你使用WWF来实现这一过程,那么需要这一过程的应用程序开发者将仅需在一处修改这些步骤-工作流本身-而不必担心这样会改变应用程序逻辑。代码复制和在哪里实现该过程可以通过Windows WF的使用来加以缓和。
当使用Windows WF在ASP.NET中实现MVC架构时,开发者应该尝试构建独立于应用程序的工作流-而该工作流仍然宿主于该应用程序中。这将有助于保持逻辑独立于描述并且保持在该Web应用程序中的工作步骤顺序和页面流之间的高度独立性。
一个WWF开发新手可能试图用一固定数目的活动以某种顺序去开发一个工作流,然后开发一组ASP.NET Web表单--这些表单以与之相同的顺序从一个表单流向另一个表单。很遗憾,尽管这看上去挺符合逻辑,但是实际上这是非常不具有生产效率的,因为你将会再次实现这个工作流逻辑。Web页面X不需要知道是否它需要转到页面Y或页面Z来正确地实现该工作流步骤。代之的是,该工作流(模型)应该告诉ASP.NET(控制器)下一步该干什么;然后ASP.NET应该决定要显示哪个页面。这样,每个页面几乎不需要了解整个过程;它仅需要知道怎样完成一个不同的活动并且让该工作流来关心页面是如何从一处流向另一处的。这种分离在开发者处理页面流时带来了一种极大的灵活性。例如,如果你决定改变该页面显示顺序,那么你可以从工作流中容易地实现这一点,而不需要改变该ASP.NET应用程序中的一行代码。
软件架构(software architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。 软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口_(计算机科学)来实现。
软件体系结构是构建计算机软件实践的基础。与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统设计方案的基础。
软件构架是一个容易理解的概念,多数工程师(尤其是经验不多的工程师)会从直觉上来认识它,但要给出精确的定义很困难。特别是,很难明确地区分设计和构架:构架属于设计的一方面,它集中于某些具体的特征。
在“软件构架简介”中,David GArlan 和 Mary Shaw 认为软件构架是有关如下问题的设计层次:“在计算的算法和数据结构之外,设计并确定系统整体结构成为了新的问题。结构问题包括总体组织结构和全局控制结构;通信、同步和数据访问的协议;设计元素的功能分配;物理分布;设计元素的组成;定标与性能;备选设计的选择。”[GS93]
但构架不仅是结构;IEEE Working Group on Architecture 把其定义为“系统在其环境中的最高层概念”[IEEE98]。构架还包括“符合”系统完整性、经济约束条件、审美需求和样式。它并不仅注重对内部的考虑,而且还在系统的用户环境和开发环境中对系统进行整体考虑,即同时注重对外部的考虑。
在 Rational Unified ProcESs 中,软件系统的构架(在某一给定点)是指系统重要构件的组织或结构,这些重要构件通过接口与不断减小的构件与接口所组成的构件进行交互。
从和目的、主题、材料和结构的联系上来说,软件架构可以和建筑物的架构相比拟。一个软件架构师需要有广泛的软件理论知识和相应的经验来事实和管理软件产品的高级设计。软件架构师定义和设计软件的模块化,模块之间的交互,用户界面风格,对外接口方法,创新的设计特性,以及高层事物的对象操作、逻辑和流程。
是一般而言,软件系统的架构(ArchitECture)有两个要素:
·它是一个软件系统从整体到部分的最高层次的划分。
一个系统通常是由元件组成的,而这些元件如何形成、相互之间如何发生作用,则是关于这个系统本身结构的重要信息。
详细地说,就是要包括架构元件(Architecture Component)、联结器(Connector)、任务流(TASk-flow)。所谓架构元素,也就是组成系统的核心"砖瓦",而联结器则描述这些元件之间通讯的路径、通讯的机制、通讯的预期结果,任务流则描述系统如何使用这些元件和联结器完成某一项需求。
·建造一个系统所作出的最高层次的、以后难以更改的,商业的和技术的决定。
在建造一个系统之前会有很多的重要决定需要事先作出,而一旦系统开始进行详细设计甚至建造,这些决定就很难更改甚至无法更改。显然,这样的决定必定是有关系统设计成败的最重要决定,必须经过非常慎重的研究和考察。
历史
早在1960年代,诸如E·W·戴克斯特拉就已经涉及软件架构这个概念了。自1990年代以来,部分由于在 Rational Software Corporation 和MiCROSoft内部的相关活动,软件架构这个概念开始越来越流行起来。
卡内基梅隆大学和加州大学埃尔文分校在这个领域作了很多研究。卡内基·梅隆大学的Mary Shaw和David Garlan于1996年写了一本叫做 Software Architecture perspective on an emerging DIscipline的书,提出了软件架构中的很多概念,例如软件组件、连接器、风格等等。 加州大学埃尔文分校的软件研究院所做的工作则主要集中于架构风格、架构描述语言以及动态架构。
计算机软件的历史开始于五十年代,历史非常短暂,而相比之下建筑工程则从石器时代就开始了,人类在几千年的建筑设计实践中积累了大量的经验和教训。建筑设计基本上包含两点,一是建筑风格,二是建筑模式。独特的建筑风格和恰当选择的建筑模式,可以使一个独一无二。
软件与人类的关系是架构师必须面对的核心问题,也是自从软件进入历史舞台之后就出现的问题。与此类似地,自从有了建筑以来,建筑与人类的关系就一直是建筑设计师必须面对的核心问题。英国首相丘吉尔说,我们构造建筑物,然后建筑物构造我们(We shape our buildings, and afterwaRDS our buildings shape us)。英国下议院的会议厅较狭窄,无法使所有的下议院议员面向同一个方向入座,而必须分成两侧入座。丘吉尔认为,议员们入座的时候自然会选择与自己政见相同的人同时入座,而这就是英国政党制的起源。Party这个词的原意就是"方"、"面"。政党起源的关键就是建筑物对人的影响。
在软件设计界曾经有很多人认为功能是最为重要的,形式必须服从功能。与此类似地,在建筑学界,现代主义建筑流派的开创人之一Louis Sullivan也认为形式应当服从于功能(FORMs follows function)。
几乎所有的软件设计理念都可以在浩如烟海的建筑学历史中找到更为遥远的历史回响。最为著名的,当然就是模式理论和XP理论。
架构的目标是什么
正如同软件本身有其要达到的目标一样,架构设计要达到的目标是什么呢?一般而言,软件架构设计要达到如下的目标:
·可靠性(Reliable)。软件系统对于用户的商业经营和管理来说极为重要,因此软件系统必须非常可靠。
·安全行(Secure)。软件系统所承担的交易的商业价值极高,系统的安全性非常重要。
·可扩展性(SCAlable)。软件必须能够在用户的使用率、用户的数目增加很快的情况下,保持合理的性能。只有这样,才能适应用户的市场扩展得可能性。
·可定制化(CuSTomizable)。同样的一套软件,可以根据客户群的不同和市场需求的变化进行调整。
·可扩展性(Extensible)。在新技术出现的时候,一个软件系统应当允许导入新技术,从而对现有系统进行功能和性能的扩展
·可维护性(MAIntainable)。软件系统的维护包括两方面,一是排除现有的错误,二是将新的软件需求反映到现有系统中去。一个易于维护的系统可以有效地降低技术支持的花费
·客户体验(Customer Experience)。软件系统必须易于使用。
·市场时机(Time to Market)。软件用户要面临同业竞争,软件提供商也要面临同业竞争。以最快的速度争夺市场先机非常重要。
架构的种类
根据我们关注的角度不同,可以将架构分成三种:
·逻辑架构、软件系统中元件之间的关系,比如用户界面,数据库,外部系统接口,商业逻辑元件,等等。
比如下面就是笔者亲身经历过的一个软件系统的逻辑架构图
图2、一个逻辑架构的例子
从上面这张图中可以看出,此系统被划分成三个逻辑层次,即表象层次,商业层次和数据持久层次。每一个层次都含有多个逻辑元件。比如WEB服务器层次中有HTML服务元件、Session服务元件、安全服务元件、系统管理元件等。
·物理架构、软件元件是怎样放到硬件上的。
比如下面这张物理架构图描述了一个分布于北京和上海的分布式系统的物理架构,图中所有的元件都是物理设备,包括网络分流器、代理服务器、WEB服务器、应用服务器、报表服务器、整合服务器、存储服务器、主机等等。
图3、一个物理架构的例子
·系统架构、系统的非功能性特征,如可扩展性、可靠性、强壮性、灵活性、性能等。
系统架构的设计要求架构师具备软件和硬件的功能和性能的过硬知识,这一工作无疑是架构设计工作中最为困难的工作。
此外,从每一个角度上看,都可以看到架构的两要素:元件划分和设计决定。
首先,一个软件系统中的元件首先是逻辑元件。这些逻辑元件如何放到硬件上,以及这些元件如何为整个系统的可扩展性、可靠性、强壮性、灵活性、性能等做出贡献,是非常重要的信息。
其次,进行软件设计需要做出的决定中,必然会包括逻辑结构、物理结构,以及它们如何影响到系统的所有非功能性特征。这些决定中会有很多是一旦作出,就很难更改的。
根据作者的经验,一个基于数据库的系统架构,有多少个数据表,就会有多少页的架构设计文档。比如一个中等的数据库应用系统通常含有一百个左右的数据表,这样的一个系统设计通常需要有一百页左右的架构设计文档。
构架描述
为了讨论和分析软件构架,必须首先定义构架表示方式,即描述构架重要方面的方式。在 Rational Unified Process 中,软件构架文档记录有这种描述。
构架视图
我们决定以多种构架视图来表示软件构架。每种构架视图针对于开发流程中的涉众(例如最终用户、设计人员、管理人员、系统工程师、维护人员等)所关注的特定方面。
构架视图显示了软件构架如何分解为构件,以及构件如何由连接器连接来产生有用的形式 [PW92],由此记录主要的结构设计决策。这些设计决策必须基于需求以及功能、补充和其他方面的约束。而这些决策又会在较低层次上为需求和将来的设计决策施加进一步的约束。
典型的构架视图集
构架由许多不同的构架视图来表示,这些视图本质上是以图形方式来摘要说明“在构架方面具有重要意义”的模型元素。在 Rational Unified Process 中,您将从一个典型的视图集开始,该视图集称为“4+1 视图模型”[KRU95]。它包括:
用例视图:包括用例和场景,这些用例和场景包括在构架方面具有重要意义的行为、类或技术风险。它是用例模型的子集。
逻辑视图:包括最重要的设计类、从这些设计类到包和子系统的组织形式,以及从这些包和子系统到层的组织形式。它还包括一些用例实现。它是设计模型的子集。
实施视图:包括实施模型及其从模块到包和层的组织形式的概览。 同时还描述了将逻辑视图中的包和类向实施视图中的包和模块分配的情况。它是实施模型的子集。
进程视图:包括所涉及任务(进程和线程)的描述,它们的交互和配置,以及将设计对象和类向任务的分配情况。只有在系统具有很高程度的并行时,才需要该视图。在 Rational Unified Process 中,它是设计模型的子集。
配置视图:包括对最典型的平台配置的各种物理节点的描述以及将任务(来自进程视图)向物理节点分配的情况。只有在分布式系统中才需要该视图。它是部署模型的一个子集。
构架视图记录在软件构架文档中。您可以构建其他视图来表达需要特别关注的不同方面:用户界面视图、安全视图、数据视图等等。对于简单系统,可以省略 4+1 视图模型中的一些视图。
构架重点
虽然以上视图可以表示系统的整体设计,但构架只同以下几个具体方面相关:
模型的结构,即组织模式,例如分层。
基本元素,即关键用例、主类、常用机制等,它们与模型中的各元素相对。
几个关键场景,它们表示了整个系统的主要控制流程。
记录模块度、可选特征、产品线状况的服务。
构架视图在本质上是整体设计的抽象或简化,它们通过舍弃具体细节来突出重要的特征。在考虑以下方面时,这些特征非常重要:
系统演进,即进入下一个开发周期。
在产品线环境下复用构架或构架的一部分。
评估补充质量,例如性能、可用性、可移植性和安全性。
向团队或分包商分配开发工作。
决定是否包括市售构件。
插入范围更广的系统。
构架模式
构架模式是解决复发构架问题的现成形式。构架框架或构架基础设施(中间件)是可以在其上构建某种构架的构件集。许多主要的构架困难应在框架或基础设施中进行解决,而且通常针对于特定的领域:命令和控制、MIS、控制系统等等。
构架模式示例
[BUS96] 根据构架模式最适用的系统的特征将其分类,其中一个类别处理更普遍的结构问题。下表显示了 [BUS96] 中所提供的类别和这些类别所包含的模式。
类别 模式
结构 层
管道和过滤器
黑板
分布式系统 代理
交互系统 模型-视图-控制器
表示-抽象-控制
自适应系统 反射
微核
软件构架是一个容易理解的概念,多数工程师(尤其是经验不多的工程师)会从直觉上来认识它,但要给出精确的定义很困难。特别是,很难明确地区分设计和构架:构架属于设计的一方面,它集中于某些具体的特征。
在“软件构架简介”中,David Garlan 和 Mary Shaw 认为软件构架是有关如下问题的设计层次:“在计算的算法和数据结构之外,设计并确定系统整体结构成为了新的问题。结构问题包括总体组织结构和全局控制结构;通信、同步和数据访问的协议;设计元素的功能分配;物理分布;设计元素的组成;定标与性能;备选设计的选择。”[GS93]
但构架不仅是结构;IEEE Working Group on Architecture 把其定义为“系统在其环境中的最高层概念”[IEEE98]。构架还包括“符合”系统完整性、经济约束条件、审美需求和样式。它并不仅注重对内部的考虑,而且还在系统的用户环境和开发环境中对系统进行整体考虑,即同时注重对外部的考虑。
在 Rational Unified Process 中,软件系统的构架(在某一给定点)是指系统重要构件的组织或结构,这些重要构件通过接口与不断减小的构件与接口所组成的构件进行交互。
为阐明其含义,下面将详述其中的两个;完整说明请参见 [BUS96]。模式以下列广泛使用的形式来表示:
模式名
环境
问题
影响,描述应考虑的不同问题方面
解决方案
基本原理
结果环境
示例
模式名
层
环境
需要进行结构分解的大系统。
问题
必须处理不同抽象层次的问题的系统。例如:硬件控制问题、常见服务问题和针对于不同领域的问题。最好不要编写垂直构件来处理所有抽象层次的问题。否则要在不同的构件中多次处理相同的问题(可能会不一致)。
影响
系统的某些部分应当是可替换的
构件中的变化不应波动
相似的责任应归为一组
构件大小 -- 复杂构件可能要进行分解
解决办法
将系统分成构件组,并使构件组形成层叠结构。使上层只使用下层(决不使用上层)提供的服务。尽量不使用非紧邻下层提供的服务(不跳层使用服务,除非中间层只添加通过构件)。
示例:
1. 通用层
严格的分层构架规定设计元素(类、构件、包、子系统)只能使用下层提供的服务, 服务可以包括事件处理、错误处理、数据库访问等等。 相对于记录在底层的原始操作系统级调用,它包括更明显的机制。
2. 业务系统层
上图显示了另一个分层示例,其中有垂直特定应用层、水平层和基础设施层。注意:此处的目标是采用非常短的业务“烟囱”并实现各种应用程序间的通用性。 否则,就可能有多个人解决同一问题,从而导致潜在的分歧。
有关该模式的深入讨论,请参见指南:分层。
模式名
黑板
环境
没有解决问题的确定方法(算法)或方法不可行的领域。例如 AI 系统、语音识别和监视系统。
问题
多个问题解决顾问(知识顾问)必须通过协作来解决他们无法单独解决的问题。各顾问的工作结果必须可以供所有其他顾问访问,使他们可以评估自己是否可以参与解决方案的查找并发布其工作结果。
影响
知识顾问参与解决问题的顺序不是确定的,这可能取决于问题解决策略
不同顾问的输入(结果或部分解决方案)可能有不同的表示方式
各顾问并不直接知道对方的存在,但可以评估对方发布的工作
解决办法
多名知识顾问都可访问一个称为“黑板”的共享数据库。黑板提供监测和更新其内容的接口。控制模块/对象激活遵循某种策略的顾问。激活后,顾问查看黑板,以确定它是否能参与解决问题。如果顾问决定它可以参与,控制对象就可以允许顾问将其部分(或最终)解决方案放置于黑板上。
示例:
以上显示了使用 UML 建模的结构或静态视图。 它将成为参数化协作的一部分,然后会绑定到实参上对模式进行实例化。
构架风格
软件构架(或仅是构架视图)可以具有名为构架风格的属性,该属性减少了可选的形式,并使构架具有一定程度的一致性。样式可以通过一组模式或通过选择特定构件或连接器作为基本构件来定义。对给定系统,某些样式可作为构架描述的一部分记录在构架风格指南(Rational Unified Process 中设计指南文档的一部分)中。样式在构架的可理解性与完整性方面起着主要的作用。
构架设计图
构架视图的图形描述称为构架设计图。对于以上描述的各种视图,设计图由以下统一建模语言图组成 [UML99]:
逻辑视图:类图、状态机和对象图。
进程视图:类图与对象图(包括任务 - 进程与线程)。
实施视图:构件图。
部署视图:配置图。
用例视图:用例图描述用例、主角和普通设计类;顺序图描述设计对象及其协作关系。
构架设计流程
在 Rational Unified Process 中,构架主要是分析设计工作流程的结果。当项目再次进行此工作流程时,构架将在一次又一次迭代中不断演化、改进、精炼。由于每次迭代都包括集成和测试,所以在交付产品时,构架就相当强壮了。构架是精化阶段各次迭代的重点,构架的基线通常会在此阶段结束时确定。
架构师
软体设计师中有一些技术水平较高、经验较为丰富的人,他们需要承担软件系统的架构设计,也就是需要设计系统的元件如何划分、元件之间如何发生相互作用,以及系统中逻辑的、物理的、系统的重要决定的作出。
这样的人就是所谓的架构师(Architect)。在很多公司中,架构师不是一个专门的和正式的职务。通常在一个开发小组中,最有经验的程序员会负责一些架构方面的工作。在一个部门中,最有经验的项目经理会负责一些架构方面的工作。
但是,越来越多的公司体认到架构工作的重要性,并且在不同的组织层次上设置专门的架构师位置,由他们负责不同层次上的逻辑架构、物理架构、系统架构的设计、配置、维护等工作。
卡内基梅隆大学软件研究所关于软件架构的定义
软件架构师是软件行业中一种新兴职业,工作职责是在一个软件项目开发过程中,将客户的需求转换为规范的开发计划及文本,并制定这个项目的总体架构,指导整个开发团队完成这个计划。架构师的主要任务不是从事具体的软件程序的编写,而是从事更高层次的开发构架工作。他必须对开发技术非常了解,并且需要有良好的组织管理能力。可以这样说,一个架构师工作的好坏决定了整个软件开发项目的成败。
软件架构师实际上就是软件的总体设计师。首席设计师就是总设计师,打个通俗的比方:邓小平是中国改革开放的总设计师,我们用现在的说法可以讲,邓小平是中国改革开放的首席架构师。架构师的形成一定是在实践中积累起来的,而并非上了几次培训班,读了几本书就可以成功的,架构师是在工程实践中培养出来的!
架构师也并非是万能的。架构师是客户需求和开发者之间的桥梁。在软件行业中,一般提到的架构师是技术架构师,而忽略了领域架构师或者讲是领域工程师的概念。一个好的领域专家一定是业务领域的架构师,他能够给出某一个业务领域的架构,我们可以称为业务架构,只有技术架构和业务架构紧密结合才有可能真正创造出一个好的系统!
架构师,首先让我想起的是高楼大厦的设计人员,通常一座大厦在建之前,都先由设计师将蓝图描绘出来,包括其形状、结构、尺寸、材料等等,然后建筑工程师带领工人们按照蓝图将大厦一层一层地建起来。
近年来,软件领域也渐渐地流行起架构师的角色,特别是对一些大型软件产品或项目的开发,这一角色显得很关键,因为缺乏好的软件架构师而导致项目失败的例子不胜枚举,一个没有经验和能力的架构师也会使项目失败的速度加快。
软件架构师的重要作用
软件架构师在整个软件开发过程中都起着重要的作用,并随着开发进程的推进而其职责或关注点不断地变化,在需求阶段,软件架构师主要负责理解和管理非功能性系统需求,比如软件的可维护性、性能、复用性、可靠性、有效性和可测试性等等,此外,架构师还要经常审查和客户及市场人员所提出的需求,确认开发团队所提出的设计;在需求越来越明确后,架构师的关注点开始转移到组织开发团队成员和开发过程定义上;在软件设计阶段,架构师负责对整个软件体系结构、关键构件、接口和开发政策的设计;在编码阶段,架构师则成为详细设计者和代码编写者的顾问,并且经常性地要举行一些技术研讨会、技术培训班等;随着软件开始测试、集成和交付,集成和测试支持将成为软件架构师的工作重点;在软件维护开始时,软件架构师就开始为下一版本的产品是否应该增加新的功能模块进行决策。
如何成为优秀的软件架构师
显而易见,在软件开发过程中,一个优秀软件架构师的重要性是不应低估的。那么如何成为优秀的软件架构师呢?
首先必须具有丰富的软件设计与开发经验,这有助于理解并解释所进行的设计是如何映射到实现中去。
其次要具有领导能力与团队协作技能,软件架构师必须是一个得到承认的技术领导,能在关键时候对技术的选择作出及时、有效的决定。
第三是具有很强的沟通能力,呵呵,其时这一点好象什么鬼角色都最好具备,软件架构师需要与各路人马经常打交道,客户、市场人员、开发人员、测试人员、项目经理、网络管理员、数据库工程师等等,而且在很多角色之间还要起沟通者的作用。在技术能力方面,软件架构师最重要也是最需求掌握的知识是构件通信机制方面的知识,比如远程过程调用、JAVARMI、CORBA、COM/DCOM、各种标准的通信协议、网络服务、面对对象数据库、关系数据库等等,另外,架构师应时刻注意新软件设计和开发方面的发展情况,并不断探索更有效的新方法。开发语言、设计模式和开发平台不断很快地升级,软件架构师需要吸收这些新技术新知识,并将它们用于软件系统开发工作中。当然,行业的业务知识对软件架构师也是很重要的,有助于设计
出一个满足客户需求的体系结构,优秀的软件架构师常常因为要尽快获得对行业业务的理解而必须快速学习并且进行敏锐的观察。
上面的描述是枯燥乏味的,但作为一个软件架构师,在整个软件系统的开发过程中是乐趣无穷的,因为这个角色很具有挑战性,有时需要左右逢源八面玲珑,有时又需要果断坚定不留情面。在国内,较少软件企业拥有独立的架构师,通常一个软件高手身兼数职,既是项目经理,又是软件架构师,还是软件开发者,有时还要客串一个测试人员,这对软件的开发周期和产品质量是不利的,有时一个人的观点立场是很片面的,而且繁重的工作、沉重的压力会影响一个人的情绪,情绪会影响决策,决策影响结果,所以值得我们三思而后行。
构架师自我培养过程
构架师不是通过理论学习可以搞出来的,不过不学习相关知识那肯定是不行的。总结构架师自我培养过程大致如下,仅供参考。
1、构架师胚胎(程序员)
学习的知识是语言基础、设计基础、通信基础等,应该在大学完成,内容包括java、c、c++、UML、RUP、XML、socket通信(通信协议)——学习搭建应用系统所必须的原材料。
2、构架师萌芽(高级程序员)
学习分布式系统、组建等内容,可以在大学或第一年工作时间接触,包括分布式系统原理、EJB、corba、com/com+、webservice(研究生可以研究网络计算机、高性能并发处理等内容)
3、构架师幼苗(设计师)
应该在掌握上述基础之上,结合实际项目经验,透彻领会应用设计模式,内容包括设计模式(c++版本、java版本)、ejb设计模式、J2EE构架、UDDI、软件设计模式等。在此期间,最好能够了解软件工程在实际项目中的应用以及小组开发、团队管理。
4、软件构架师的正是成型在于机遇、个人努力和天赋软件构架师其实是一种职位,但一个程序员在充分掌握软构架师所需的基本技能后,如何得到这样的机会、如何利用所掌握的技能进行应用的合理构架、如何不断的抽象和归纳自己的构架模式、如何深入行业成为能够胜任分析、构架为一体的精英人才这可不是每个人都能够遇上的馅饼……
软件构架师职场概况
如果您今天有幸同全球首富比尔·盖茨交换名片,您会注意到他的头衔是微软公司首席软件架构师。同样假如您得到中国首富丁磊的名片,您也会看到他的头衔是网易公司首席架构师。悄然间,架构师已经成为职场上最让人羡慕的职位。
在我国,随着软件业规模的不断扩大,软件人才结构性矛盾将更加突出。国家人事部门预计到2005年我国软件产业的规模将达到2500亿元,全国计算机应用专业人才的需求每年将增加百万人左右。其中,架构师这样的专业高级人才每年培养人数全国不过数百名,缺口非常之大,而其中尤其以Java架构师缺口最为明显。
众所周知,Java是当前最热门的软件开发语言,它具有跨平台、面向对象、强大的网络功能等特性。你不仅能在电脑上使用Java程序,还能在手机、PDA、家用电器上使用Java程序,甚至举世瞩目的火星车也全部采用Java技术。Java在不到10年时间内已经变成最流行的软件开发平台,最新的企业级Java 2.0版本(简称:J2EE)也成为企业应用系统上最受欢迎的开发标准。
事实上,全世界范围内的J2EE架构师都是紧缺的人才,只是中国更加明显而已。在英国,有经验的J2EE架构师,目前平均年薪已经飙涨到七万至十万英镑。全球著名的电子商务平台提供商SilverSTreAM软件公司的技术服务总监Mark AShton对J2EE人才的短缺深有感受,他表示许多求职者的履历表上都有把J2EE列进去,但是仔细查看或是面试之后就会发现大多数人只是听过J2EE,并没有真正用过这些技术。信息产业部电子信息产品管理司副司长丁文武近期也表示,目前我国Java人才还远远不够,至少短缺20万。特别是随着大量软件外包业务进入中国,许多外资或中资软件企业也开始面临着高级Java人才奇缺的问题,尤其是熟悉J2EE又能掌握一门相应外语的人才成为了众多大公司争抢的对象。
作为Java的发明者和Java开发标准的主要制定者——美国Sun公司对从事Java开发的技术人员提供了三级认证体系,即初级的程序员认证(SCJP)、中级的开发员认证(SCJD和SCWD)和高级的架构师认证(SCEA)。这也是软件行业中最权威的国际认证之一。目前国内已经有针对美国Sun公司认证体系的培训,但绝大多数主要针对初级的程序员认证,只有极少数专业培训机构能够提供三层完整培训。国家信息化教育示范基地——上海文华学院(www.wenhua.org)是上海仅有的一家拥有Java自上而下、由浅入深的完善的培训及认证体系的学院。作为Sun华东区最佳培训中心,上海文华学院的“对外J2EE国际软件工程师就业班”课程除了由浅入深,完整地教授整个J2EE体系外,还详尽地教授开发企业级应用软件所必须掌握的知识体系,如:操作系统、UML、数据库、项目管理、软件测试等。因此,即使你没有任何软件开发知识,也能完成这门课程的学习。课程采用项目教学,并培训计算机英语和第二外语。学员考试通过后,可以获得美国Sun公司的最高级别国际认证:Sun认证企业级Java 2架构师(SCEA),还推荐就业。学员入学前还可参加免费的“软件开发潜质测试”,评估自己是否适合开发软件。
升职与加薪是双胞胎,升职随之而来的就是加薪。升职,人人盼望,人人向往,但并不是人人能具备,人人有机会。要想升职,甚至升到重要位置,那要经过很多磨练,练就领导者的素质和品质才可以胜任,不然,你就是升了职也会让人心中不服。
职场案例:王伟就职于一家中型私企的部门主管,4年来,与老板和公司里老板的两个弟弟相处的很好,应该算是铁哥们。最近,公司一名副总跳槽走掉了。王伟隐约觉得,自己可能是老板提拔的首选,两个弟弟也想竞争,但又知道没有可能,也觉得论各种条件,应该非王伟莫属。他曾经是这个公司销售部门里销售业绩最好的员工,后来提拔到销售部做主管,对公司也算上忠心耿耿。谁知,老板并无此意,而是从同行企业中,高薪请了位副总,让王伟他们不能理解。老板说:你们哥几个看问题还不行,有点嫩。副总别看前面有个"副"字,平时是总经理的得力助手,协调各部门的关系,当总经理外出时要当成正职使用,也就是要主持全面工作,必须具备很高的素质才能胜任。你们都是将才,不是帅才。离总经理的位置还需要磨砺几年。
宏威职业顾问分析:白领升职,不是想升就升,需要多年磨一箭,要磨砺出应有的良好素质。此外还要有机会:
一、 领导者(leadership)的"领导力"
领导者是影响他人行为与思想的过程,领导的目的是影响被领导者做出努力和贡献去实现组织目标。"领导力"则是激发他人跟随你一起工作,以获取共同目标的能力,其本质就是影响力。"领导力"的核心要素包括:"情感智力"(emotional intelligence)、"技术技能"、"人格素质"、"认知能力"、"领导风格"。
其中集体领导就是让团队中的每个成员都担起领导之责,管理方法有四个特征,称为"4 c":允许多名领导同时存在于团队(concurrent);所有重大决策都由集体做出(collective);成员相互协作(collaborative);领导者关怀他人(compassionate)。借助这四个C,组织能够在更大的范围内完成其领导力培养进程,并且与传统的方法相比,成效更为显著。
"5e"领导力,即所有主管都应该有充沛的个人精力(energy)来迎接和应对变革,有能力创造激励(energizes)别人的环境,有作出艰难决定的决断力和锋芒(edge),有不断执行(execute)的能力,有职业道德(ethical tahavior)。
那些高效的公司层面领导者可以同时熟练地管理五个流程,对组织做出全面整合。对于公司层面的领导者在整合组织的过程当中所发挥的作用,我们可以系统地把它总结为管理五个M:意义(meaning)、理念(mindset)、动员(mobilization)、评估(measurement)、持续改进机制(mechanisms for renewal)。
二、 胜任力(Competence)的10 a、5c、3p、3v
10 a:有雄心壮志的 (ambitious)有志气的,有抱负的(aspiring)、有才干的,能干的(able)、有进取心的(aggressive)、适应性强的 (adaptable)、主动的,活跃的 (active)、善于分析的(analytical)、有理解力的(apprehensive)、大胆的,有冒险精神的(audacious)、和蔼可亲的(amiable)。
5c:富创造力的(creative)、能胜任的(competent)、建设性的(constructive)、正直的(candid)、有合作精神的 (cooperative)。
3p:职业经历(professional history)、实际业绩 (performance)、个人能力(people )
3v:有战略眼光(strategy vision)、有价值(value)、能够创造成功(create victory);
三、 现代化思维(deliberate thinking)的10个C
现代化管理中,一个优秀管理者总是尝试着从新的角度看问题,这些新角度可归纳为五个C:同事的角度(Colleague perspective)、顾客的角度(Customer perspective)、竞争者的角度(Competitor perspective)、公司的角度(Company perspective)、创造性的角度(Creative perspective)。
在激烈竞争的职场中,必备5个C 才能立于不败之地:信心(Confidence)、能力Competence、创造(Creation)、沟通(Communication)、合作(Cooperation),在这5个C中,首当其重的是信心,信心代表着一个人在事业中的精神状态和把握工作的热忱以及对自己能力的正确认知。沟通包含事 ( contant ) 与情 (feeling),即沟通的内容和感受。
四、 升职必备的素质和品质的10个心评价
一个职员能否升职所具备的能力,除了技术之外,也就是"硬指标"之外,还有所谓的"软指标",不同级别的职员有不同的"软指标",如普通职员最可贵的是学习能力、理解能力、团队合作精神等;管理职员最可贵的是领导能力,也就是计划、组织、控制、监督、反馈能力等。因此不同发展时期的职员,需要提高不同的能力、素质和品质,从而促进企业业绩改善。
10个心即有:爱心、热心、责任心、上进心、耐心、关心、恒心、奉献心、包容心和平常心。
五、 升职的成功白领需要"十个Q"
IQ(Intelligence Quotient)、EQ(Emotional Quotient)、挫折商AQ(Adversity Quotient)
1. 德商(MQ):指一个人的道德人格品质。德商的内容包括体贴、尊重、容忍、宽容、诚实、负责、平和、忠心、礼貌、幽默等各种美德。
2. 智商(IQ):是一种表示人智力高低的数量指标。也可以表现为一个人对知识的掌握程度,反映人的观察力、记忆力、思维力、想象力、创造力以及分析问题和解决问题的能力。
3. 情商(EQ):指管理自己的情绪和处理人际关系的能力。
4. 逆商(AQ):指面对逆境承受压力的能力,或承受失败和挫折的能力。
5. 胆商(DQ):是一个人胆量、胆识、胆略的度量,体现了一种冒险精神。胆商高的人能够把握机会,凡是成功的商人、政客,都具有非凡胆略和魄力。
6. 财商(FQ):指理财能力,特别是投资收益能力。财商是一个人最需要的能力,但往往会被人们忽略。
7. 心商(MQ):就是维持心理健康、缓解心理压力、保持良好心理状况和活力的能力。心商的高低,直接决定了人生过程的苦乐,主宰人生命运的成功。
8. 志商(WQ):指一个人的意志品质水平,包括坚韧性、目的性、果断性、自制力等方面。
9. 灵商(SQ):就是对事物本质的顿悟能力和直觉思维能力。
10. 健商(HQ):是指个人所具有的健康意识、健康知识和健康能力的反映。
六、 用良好的心态面对升职成就你人生的十大积极心态(PAM):
执著:对个人、企业和团队目标、价值观坚定不移的信念。
挑战:勇敢地挺身而出,积极地迎接变化和新的任务。
热情:对自己的工作以及公司的产品、服务、品牌和形象具有强烈的感情和浓厚的兴趣。
奉献:全心全意完成工作或处理事务。
激情:始终对未来充满憧憬和希望,对现在全力以赴地投入。
愉快:乐于接受微笑、乐趣,并分享成功。
爱心:助人为乐,感恩心态。
自豪:因为自身价值或团队成绩而深感荣耀。
渴望:强烈的成功欲望。
信赖:相信他人和集体的素质、价值和可靠性。
1. 毁坏你人生的十大消极心态(NMA)
畏惧:面对困难缩头缩脚,没有目标或对自己、公司的目标缺乏信心,不敢接受任务和挑战。
愤怒:因假想的对立或莫名的原因而产生极大的痛苦与敌意。
冷漠:事不关己,高高挂起,脸色整天阴云密布。
紧张:头脑、身体和情绪处于焦虑和不安的状态。
忧虑:对可能出现的困难、任务或问题感到寝食难安。
敌意:对立或反抗的行为,过于强烈的厌恶感。
嫉妒:对团队、他人的成就或优秀素质心生不满甚至感到气愤。
贪婪:无休止、无节制地追求享受、金钱、地位、名誉或权力。
自私:从自身利益出发,全然不顾他人的感受。
麻木:得过且过,没有兴趣和热情。
七、 磨练(Crucible)非凡的"意志力"
必须是一个意志坚强的(purposeful)的人,对于每一个要克服的障碍,都离不开意志力。面对着所执行的每一个艰难的决定,我们所依靠的是内心的力量。事实上,意志力并非是生来就有或者不可能改变的特性,它是一种能够培养和发展的技能。
词典上将"意志力"解释成"控制人的冲动和行动的力量",其中最关键的是"控制"和"力量"两个词。"力量"是客观存在的,问题在于如何"控制"它。
美国罗得艾兰大学心理学教授詹姆斯*普罗斯把实现意志力分为四步:11. 抵制--不愿意转变;12. 考虑--权衡转变的得失;13. 行动--培养意志力来实现转变;14. 坚持--用意志力来保持转变。
八、 谦虚(Humility )的美德
不自大,不自见,不自是,不自伐,不自矜。因为自大反而不能成其大;自我显扬的反而不能彰明;自以为是反而不能昭彰;自我夸耀的反而不能见其功;自高自傲的反而不能成为众人之长。足见自谦之益。
九、 人类特有的四种天赋。
除自我意识外,我们还拥有"想象力"(imagination),能超出现实之外;有"良知"(conscience),能明辨是非善恶;更有"独立意志"(independent will),能够不受外力影响,自行其是。


程序员和系统分析员,大家应该对这两个词很熟悉了,但是对词里包含的意义可能并不是特别清楚。首先必须说明的是,程序员和系统分析员不存在谁高级谁低级的分别,他们是两种职业,对职业技能的要求完全不同。所以厉害的程序员就是系统分析员的说法是不对的。当然,系统分析员的技能要求他必须要懂得如何写程序,但是他的重心在于如何把一个很大的项目切割成适合个人的小块,然后将这些小块组织起来。程序员的职责就是如何更好更快的实现这些小块。
在正式开始之前,我们还是来看在Thinking In Java中作者对分析和设计的一段精辟见解:
分析和设计
面向对象的范式是思考程序设计时一种新的、而且全然不同的方式,许多人最开始都会在如何构造一个项目上皱起了眉头。事实上,我们可以作出一个“好”的设计,它能充分利用OOP提供的所有优点。
请原谅在这里突然出现了OOP这个词,他的意思是面相对象,虽然在之前没有提到,但是在现在OO概念满天飞的软件世界里,大家应该对他不会太陌生。这里我简要的说明一下。在之前我介绍的实际上都是在很早以前程序写作流传下来的经验(什么,教我们老古董,打他!),但是以前的非OO(就是基于过程)的软件设计方法目前在国际上已经很少采用,所以我这里讲软件设计的时候所有的概念都是基于OO的。即使OO的概念很简单的啦,大家思考一下,我们再学习C++的时候一开始使用的类不都是一些动物啦、正方形啦之类的,都是生活中的例子,对吧。其实OO就是我们看世界的一种方式。可是最早由于计算机技术的不发达,我们不得不用一些很奇怪的描述来表达我们的意思,只有这样计算机才能理解,很笨不是吗。比如我们必须使用参数、过程、函数。所以当时的软件设计方法都是基于过程的。举一个简单的例子来显示OO设计方法和基于过程的设计方法之间的差别:一句简单的日常短语--“我吃饭”,用OO的方法来表述还是“我吃饭”,可是如果用基于过程的方法来描述的话就变成“我吃饭(饭)”,是不是很别扭呢。
有关OOP分析与设计的书籍大多数都不尽如人意。其中的大多数书都充斥着莫名其妙的话语、笨拙的笔调以及许多听起来似乎很重要的声明。我认为这种书最好压缩到一章左右的空间,至多写成一本非常薄的书。具有讽剌意味的是,那些特别专注于复杂事物管理的人往往在写一些浅显、明白的书上面大费周章!如果不能说得简单和直接,一定没多少人喜欢看这方面的内容。毕竟,OOP的全部宗旨就是让软件开发的过程变得更加容易。尽管这可能影响了那些喜欢解决复杂问题的人的生计,但为什么不从一开始就把事情弄得简单些呢?因此,希望我能从开始就为大家打下一个良好的基础,尽可能用几个段落来说清楚分析与设计的问题。
不要迷失
在整个开发过程中,最重要的事情就是:不要将自己迷失!但事实上这种事情很容易发生。大多数方法都设计用来解决最大范围内的问题。当然,也存在一些特别困难的项目,需要作者付出更为艰辛的努力,或者付出更大的代价。但是,大多数项目都是比较“常规”的,所以一般都能作出成功的分析与设计,而且只需用到推荐的一小部分方法。但无论多么有限,某些形式的处理总是有益的,这可使整个项目的开发更加容易,总比直接了当开始编码好! 也就是说,假如你正在考察一种特殊的方法,其中包含了大量细节,并推荐了许多步骤和文档,那么仍然很难正确判断自己该在何时停止。时刻提醒自己注意以下几个问题:
(1) 对象是什么?(怎样将自己的项目分割成一系列单独的组件?)
(2) 它们的接口是什么?(需要将什么消息发给每一个对象?)
在确定了对象和它们的接口后,便可着手编写一个程序。出于对多方面原因的考虑,可能还需要比这更多的说明及文档,但要求掌握的资料绝对不能比这还少。
整个过程可划分为四个阶段,阶段0刚刚开始采用某些形式的结构。
阶段0:拟出一个计划
第一步是决定在后面的过程中采取哪些步骤。这听起来似乎很简单(事实上,我们这儿说的一切都似乎很简单),但很常见的一种情况是:有些人甚至没有进入阶段1,便忙忙慌慌地开始编写代码。如果你的计划本来就是“直接开始开始编码”,那样做当然也无可非议(若对自己要解决的问题已有很透彻的理解,便可考虑那样做)。但最低程度也应同意自己该有个计划。
在这个阶段,可能要决定一些必要的附加处理结构。但非常不幸,有些程序员写程序时喜欢随心所欲,他们认为“该完成的时候自然会完成”。这样做刚开始可能不会有什么问题,但我觉得假如能在整个过程中设置几个标志,或者“路标”,将更有益于你集中注意力。这恐怕比单纯地为了“完成工作”而工作好得多。至少,在达到了一个又一个的目标,经过了一个接一个的路标以后,可对自己的进度有清晰的把握,干劲也会相应地提高,不会产生“路遥漫漫无期”的感觉。
从我刚开始学习故事结构起(我想有一天能写本小说出来),就一直坚持这种做法,感觉就象简单地让文字“流”到纸上。在我写与计算机有关的东西时,发现结构要比小说简单得多,所以不需要考虑太多这方面的问题。但我仍然制订了整个写作的结构,使自己对要写什么做到心中有数。因此,即使你的计划就是直接开始写程序,仍然需要经历以下的阶段,同时向自己提出一些特定的问题。
阶段1:要制作什么?
在上一代程序设计中(即“过程化或程序化设计”),这个阶段称为“建立需求分析和系统规格”。当然,那些操作今天已经不再需要了,或者至少改换了形式。大量令人头痛的文档资料已成为历史。但当时的初衷是好的。需求分析的意思是“建立一系列规则,根据它判断任务什么时候完成,以及客户怎样才能满意”。系统规格则表示“这里是一些具体的说明,让你知道程序需要做什么(而不是怎样做)才能满足要求”。
需求分析实际就是你和客户之间的一份合约(即使客户就在本公司内部工作,或者是其他对象及系统)。系统规格是对所面临问题的最高级别的一种揭示,我们依据它判断任务是否完成,以及需要花多长的时间。由于这些都需要取得参与者的一致同意,所以我建议尽可能地简化它们——最好采用列表和基本图表的形式——以节省时间。可能还会面临另一些限制,需要把它们扩充成为更大的文档。 我们特别要注意将重点放在这一阶段的核心问题上,不要纠缠于细枝末节。这个核心问题就是:决定采用什么系统。对这个问题,最有价值的工具就是一个名为“使用条件”的集合。对那些采用“假如……,系统该怎样做?”形式的问题,这便是最有说服力的回答。例如,“假如客户需要提取一张现金支票,但当时又没有这么多的现金储备,那么自动取款机该怎样反应?”对这个问题,“使用条件”可以指示自动取款机在那种“条件”下的正确操作。
应尽可能总结出自己系统的一套完整的“使用条件”或者“应用场合”。一旦完成这个工作,就相当于摸清了想让系统完成的核心任务。由于将重点放在“使用条件”上,一个很好的效果就是它们总能让你放精力放在最关键的东西上,并防止自己分心于对完成任务关系不大的其他事情上面。也就是说,只要掌握了一套完整的“使用条件”,就可以对自己的系统作出清晰的描述,并转移到下一个阶段。在这一阶段,也有可能无法完全掌握系统日后的各种应用场合,但这也没有关系。只要肯花时间,所有问题都会自然而然暴露出来。不要过份在意系统规格的“完美”,否则也容易产生挫败感和焦燥情绪。 在这一阶段,最好用几个简单的段落对自己的系统作出描述,然后围绕它们再进行扩充,添加一些“名词”和“动词”。“名词”自然成为对象,而“动词”自然成为要整合到对象接口中的“方法”。只要亲自试着做一做,就会发现这是多么有用的一个工具;有些时候,它能帮助你完成绝大多数的工作。
尽管仍处在初级阶段,但这时的一些日程安排也可能会非常管用。我们现在对自己要构建的东西应该有了一个较全面的认识,所以可能已经感觉到了它大概会花多长的时间来完成。此时要考虑多方面的因素:如果估计出一个较长的日程,那么公司也许决定不再继续下去;或者一名主管已经估算出了这个项目要花多长的时间,并会试着影响你的估计。但无论如何,最好从一开始就草拟出一份“诚实”的时间表,以后再进行一些暂时难以作出的决策。目前有许多技术可帮助我们计算出准确的日程安排(就象那些预测股票市场起落的技术),但通常最好的方法还是依赖自己的经验和直觉(不要忘记,直觉也要建立在经验上)。感觉一下大概需要花多长的时间,然后将这个时间加倍,再加上10%。你的感觉可能是正确的;“也许”能在那个时间里完成。但“加倍”使那个时间更加充裕,“10%”的时间则用于进行最后的推敲和深化。但同时也要对此向上级主管作出适当的解释,无论对方有什么抱怨和修改,只要明确地告诉他们:这样的一个日程安排,只是我的一个估计!
阶段2:如何构建?
在这一阶段,必须拿出一套设计方案,并解释其中包含的各类对象在外观上是什么样子,以及相互间是如何沟通的。此时可考虑采用一种特殊的图表工具:“统一建模语言”(UML)。请到http://www.rational.com/去下载一份UML规格书。作为第1阶段中的描述工具,UML也是很有帮助的。此外,还可用它在第2阶段中处理一些图表(如流程图)。当然并非一定要使用UML,但它对你会很有帮助,特别是在希望描绘一张详尽的图表,让许多人在一起研究的时候。除UML外,还可选择对对象以及它们的接口进行文字化描述(《Thinking in C++》里说的那样,但这种方法非常原始,发挥的作用亦较有限。
我曾有一次非常成功的咨询经历,那时涉及到一小组人的初始设计。他们以前还没有构建过OOP(面向对象程序设计)项目,将对象画在白板上面。我们谈到各对象相互间该如何沟通(通信),并删除了其中的一部分,以及替换了另一部分对象。这个小组(他们知道这个项目的目的是什么)实际上已经制订出了设计方案;他们自己“拥有”了设计,而不是让设计自然而然地显露出来。我在那里做的事情就是对设计进行指导,提出一些适当的问题,尝试作出一些假设,并从小组中得到反馈,以便修改那些假设。这个过程中最美妙的事情就是整个小组并不是通过学习一些抽象的例子来进行面向对象的设计,而是通过实践一个真正的设计来掌握OOP的窍门,而那个设计正是他们当时手上的工作!
作出了对对象以及它们的接口的说明后,就完成了第2阶段的工作。当然,这些工作可能并不完全。有些工作可能要等到进入阶段3才能得知。但这已经足够了。我们真正需要关心的是最终找出所有的对象。能早些发现当然好,但OOP提供了足够完美的结构,以后再找出它们也不迟。
阶段3:开始创建
读这本书的可能是程序员,现在进入的正是你可能最感兴趣的阶段。由于手头上有一个计划——无论它有多么简要,而且在正式编码前掌握了正确的设计结构,所以会发现接下去的工作比一开始就埋头写程序要简单得多。而这正是我们想达到的目的。让代码做到我们想做的事情,这是所有程序项目最终的目标。但切不要急功冒进,否则只有得不偿失。根据我的经验,最后先拿出一套较为全面的方案,使其尽可能设想周全,能满足尽可能多的要求。给我的感觉,编程更象一门艺术,不能只是作为技术活来看待。所有付出最终都会得到回报。作为真正的程序员,这并非可有可无的一种素质。全面的思考、周密的准备、良好的构造不仅使程序更易构建与调试,也使其更易理解和维护,而那正是一套软件赢利的必要条件。
构建好系统,并令其运行起来后,必须进行实际检验,以前做的那些需求分析和系统规格便可派上用场了。全面地考察自己的程序,确定提出的所有要求均已满足。现在一切似乎都该结束了?是吗?
阶段4:校订
事实上,整个开发周期还没有结束,现在进入的是传统意义上称为“维护”的一个阶段。“维护”是一个比较暧昧的称呼,可用它表示从“保持它按设想的轨道运行”、“加入客户从前忘了声明的功能”或者更传统的“除掉暴露出来的一切臭虫”等等意思。所以大家对“维护”这个词产生了许多误解,有的人认为:凡是需要“维护”的东西,必定不是好的,或者是有缺陷的!因为这个词说明你实际构建的是一个非常“原始”的程序,以后需要频繁地作出改动、添加新的代码或者防止它的落后、退化等。因此,我们需要用一个更合理的词语来称呼以后需要继续的工作。 这个词便是“校订”。换言之,“你第一次做的东西并不完善,所以需为自己留下一个深入学习、认知的空间,再回过头去作一些改变”。对于要解决的问题,随着对它的学习和了解愈加深入,可能需要作出大量改动。进行这些工作的一个动力是随着不断的改革优化,终于能够从自己的努力中得到回报,无论这需要经历一个较短还是较长的时期。
什么时候才叫“达到理想的状态”呢?这并不仅仅意味着程序必须按要求的那样工作,并能适应各种指定的“使用条件”,它也意味着代码的内部结构应当尽善尽美。至少,我们应能感觉出整个结构都能良好地协调运作。没有笨拙的语法,没有臃肿的对象,也没有一些华而不实的东西。除此以外,必须保证程序结构有很强的生命力。由于多方面的原因,以后对程序的改动是必不可少。但必须确定改动能够方便和清楚地进行。这里没有花巧可言。不仅需要理解自己构建的是什么,也要理解程序如何不断地进化。幸运的是,面向对象的程序设计语言特别适合进行这类连续作出的修改——由对象建立起来的边界可有效保证结构的整体性,并能防范对无关对象进行的无谓干扰、破坏。也可以对自己的程序作一些看似激烈的大变动,同时不会破坏程序的整体性,不会波及到其他代码。事实上,对“校订”的支持是OOP非常重要的一个特点。
通过校订,可创建出至少接近自己设想的东西。然后从整体上观察自己的作品,把它与自己的要求比较,看看还短缺什么。然后就可以从容地回过头去,对程序中不恰当的部分进行重新设计和重新实现(注释⑩)。在最终得到一套恰当的方案之前,可能需要解决一些不能回避的问题,或者至少解决问题的一个方面。而且一般要多“校订”几次才行。
构建一套系统时,“校订”几乎是不可避免的。我们需要不断地对比自己的需求,了解系统是否自己实际所需要的。有时只有实际看到系统,才能意识到自己需要解决一个不同的问题。若认为这种形式的校订必然会发生,那么最好尽快拿出自己的第一个版本,检查它是否自己希望的,使自己的思想不断趋向成熟。
反复的“校订”同“递增开发”有关密不可分的关系。递增开发意味着先从系统的核心入手,将其作为一个框架实现,以后要在这个框架的基础上逐渐建立起系统剩余的部分。随后,将准备提供的各种功能(特性)一个接一个地加入其中。这里最考验技巧的是架设起一个能方便扩充所有目标特性的一个框架(对这个问题,大家可参考第16章的论述)。这样做的好处在于一旦令核心框架运作起来,要加入的每一项特性就象它自身内的一个小项目,而非大项目的一部分。此外,开发或维护阶段合成的新特性可以更方便地加入。OOP之所以提供了对递增开发的支持,是由于假如程序设计得好,每一次递增都可以成为完善的对象或者对象组。
这有点类似“快速造型”。此时应着眼于建立一个简单、明了的版本,使自己能对系统有个清楚的把握。再把这个原型扔掉,并正式地构建一个。快速造型最麻烦的一种情况就是人们不将原型扔掉,而是直接在它的基础上建造。如果再加上程序化设计中“结构”的缺乏,就会导致一个混乱的系统,致使维护成本增加。
计划的回报
如果没有仔细拟定的设计图,当然不可能建起一所房子。如建立的是一所狗舍,尽管设计图可以不必那么详尽,但仍然需要一些草图,以做到心中有数。软件开发则完全不同,它的“设计图”(计划)必须详尽而完备。在很长的一段时间里,人们在他们的开发过程中并没有太多的结构,但那些大型项目很容易就会遭致失败。通过不断的摸索,人们掌握了数量众多的结构和详细资料。但它们的使用却使人提心吊胆在意——似乎需要把自己的大多数时间花在编写文档上,而没有多少时间来编程(经常如此)。我希望这里为大家讲述的一切能提供一条折衷的道路。需要采取一种最适合自己需要(以及习惯)的方法。不管制订出的计划有多么小,但与完全没有计划相比,一些形式的计划会极大改善你的项目。请记住:根据估计,没有计划的50%以上的项目都会失败!
非常佩服作者对软件构建过程的精辟见解,软件工程是一门内容非常繁杂的学科,但是作者能够用浅显易懂的句子把它描述出来,真的是非常不简单。软件工程最早的提出者并不是计算机的专业人士,而是一位建筑设计师,所以软件工程的很多思想来自于建筑学。经过了几十年的发展,软件工程经历了很多次的蜕变。形成了今天的世界上以一些大公司提出的架构为主的形式:比如微软提出的COM及COM+以及基于其上的DNA体系,SUN提出的EJB,CORBA,还有BEA、WebLogic、IBM等公司的架构。虽然架构有不同,但是他们的思想都是相通的,架构的作用都是起到辅助开发者实现规范的、科学的软件开发过程。至于谈软件项目的管理和开发,那么Rational公司就是这方面的鼻祖。综合来说,目前世界范围内的软件工程提倡的就是以渐进的、螺旋式的开发方法构建基于组件的软件产品。现在说这些东西可能有些画饼的嫌疑,随着我们专题讨论的继续深入,这些概念就会很清晰的展现在面前。
虽然很希望能够继续的讨论软件工程方面的东东,但是我们的这个专题毕竟是讨论如何编写优美的程序的,离题还是不要太过分的好,至于软件工程的详细讨论,我会在接下去的专题中继续。在接下去的篇幅中,我们会继续讨论程序员和系统分析员之间的差别。
四个阶段
这里我不想举一大堆的数字和实例来描述软件危机和论证软件工程的重要性,这方面的资料有很多,如果一一列举的话,会被怀疑别有用心。事实上,建造狗舍和写一个小的软件没有很大的区别。虽然你认为你的能力可以很轻松的完成小型的软件系统,根本不需要任何的计划。好!我来问问你,你在写程序代码的时候,有没有过漏这漏那,程序快接近完成的时候却发现少了一个很重要的模块;有没有过在书写了大量的代码之后觉得自己写出来的东西不堪入目,恨不得重头开始;有没有过写程序花了两天的时间,但是Debug却花了一个星期的时间;有没有过听到软件的使用者说要改需求,你就恨不得狠狠揍他一顿。如果都没有,那么只有两种可能:你是个超级天才,所有人类能够想到的美好品质你都具有,另一种可能:你根本没有开发过软件。
即便是个人开发的软件,软件工程科学中也有相应的方法来指导软件的开发过程,这种方法叫做PSP(个人软件开发过程),与此相对的,还有TSP(小组软件开发过程)。这些被事实证明行之有效的方法包括了一整套的规范,帮助你开发你的软件,不让你的程序变得无法控制。可以说,对于任何一个软件系统来说,只要你花一些时间去设计,即便你的设计仅仅只是在草稿纸上随便的涂抹,在软件开发完成后,你就会惊喜的发现,你在软件开发早期的小小投入,已经为你带来了额外的好处。
路标和RUP
在阶段0中,我想最重要的思想就是就是“路标”的概念了,和这个概念相类似的概念还有“周期”和“里程碑”的概念,这些概念在Rational公司的RUP(Rational Unified Process 软件统一过程)中有详细的论述。不论这些概念叫做什么,他们体现出来的是一种迭代开发的思想。面对当今的复杂的软件系统,使用连续的开发方法:如首先定义整个问题,设计完整的解决方案,编制软件并最终测试产品,是不可能的。需要一种能够通过一系列细化,若干个渐进的反复过程而生成有效解决方案的迭代方法。
Rational Unified Process支持专注于处理生命周期中每个阶段中最高风险的迭代开发方法,极大地减少了项目的风险性。迭代方法通过可验证的方法来帮助减少风险--经常性的,可执行版本使最终用户不断的介入和反馈。因为每个迭代过程以可执行版本告终,开发队伍停留在产生结果上,频繁的状态检查帮助确保项目能按时进行。迭代化方法同样使得需求、特色、日程上战略性的变化更为容易。(出自《Rational Unified Process白皮书》)
上面这段好像很复杂,但是他所要说明的思想却是很简单的,就拿搭建狗舍来说,你的第一个“路标”可能是要搭一个框架,这个框架是由几根结实的木头组成,等到框架完成之后,你会把你的小白叫来,让他试一下,糟糕的是,这个框架对于小白来说小了一些,这时候你嘘了一口气,因为你原来是打算把整个狗舍搭好以后再叫小白来试一下的,如果你那样做的话,你剩下的木头可能就不够再盖一间狗舍了。好吧,既然有了些问题,我们就把框架调整一下,可能这个过程也花了你一些木头,不过所幸木头还够。在修整完毕后,你觉得第一步的计划虽然有些挫折,不过仍可以算是成功的,接下来你就要建立第二个“路标”了:第二个的“路标”是为狗舍钉上墙板和做出一个底座,你可能花了一些时间来思考以及和你的小白商量是否要在墙壁上开一个窗户和给底座加上轮子,在决定之后,你很快的达成了第二个“路标”。而且在经过了小白的测试后,你发现完全没有问题,你自己都觉得有些佩服自己了,很快的,你又完成刷油漆等“路标”。整个过程进展的非常顺利,而你在做狗舍方面很有天赋的名声也在你的街坊四邻间不胫而走。
很简单是吧,其实本来就是简单的,软件工程的目的就是要把复杂的软件开发过程条理化,简单化。记住,在你使用迭代开发方法的时候,它在每个周期后的产品是一份可执行代码,是一份可以让你的用户品头论足的东西。而这份可执行代码不仅包括了程序本身,可能还有其他的产成品,例如:文档等。
问题和场景
在阶段1中,非常重要的一点是问题描述,在多数情况下,问题描述来自于你的软件的使用者,就是用户。用户的需求决定了问题描述,糟糕的是,用户多半不懂计算机,对他们来说,他们只能够用日常的语言来表达自己的需要。而你的任务就是要把他们的语言翻译成计算机语言,不过并不是指象C那样的高级语言,而是便于你构造系统的需求描述语言。这同样很简单:你只需要问自己几个问题就可以:在什么场合?有什么条件?做些什么事?回答好这三个问题,你就完成了一个完整的问题描述了。
举一个简单的例子:一个银行的信贷系统有这样的问题描述:
“若顾客采取信用贷款方式,销售员就请求信用部门的审核人员查核顾客的信用,此时审核人员会向销售员取得顾客信用编号和销货总金额。”
在某种条件下应该做什么事情,这就是这个问题描述的表现形式,很简单是吧。
实际上,这里可以引申出两个概念:场景(context)和问题(problem),场景指的是一种特定的情况,会导致某种问题的发生;而问题是在某个场景之中,但它也有可能产生出新的场景。
过程和对象
有必要说明一下以前基于过程的软件开发和目前基于对象的软件开发的不同。在没有OO的年代里,DFD(Data Flow Diagram 数据流程图)是一份软件设计中的非常重要的文档,注意力的关键也是集中在数据如何在各个系统之间传递。可是在现在的OO概念中,数据大有为消息(message)所替代的趋势。比如你到麦当劳快餐店,要花10块钱买一份汉堡。在DFD的时代,就是这样表示的:
如果你用消息表示法来表示话,就是另一种方式:
怎么样,你觉得那一种方式更自然呢。(如果你敢回答第一种的话我就...)。再比如上一段话中关于问题描述的例子,如果用传统的数据描述的方法的话,就会是这样子的:
“若采取信用贷款方式,销售员就将顾客信用编号及总金额交给信用部门的信用审核人员。”
请比较其中的两句话:
“若采取信用贷款方式,销售员就将顾客信用编号及总金额交给信用部门的信用审核人员。”
“若顾客采取信用贷款方式,销售员就请求信用部门的审核人员查核顾客的信用,此时审核人员会向销售员取得顾客信用编号和销货总金额。”
了解其中的不同之处了吗,用自然的语言去描述你的问题,这是写出好的软件的第一步。
系统分析员的语言
场景描述是一个很不错的方法,可是随着你对系统的分析的深入,参与开发的人员的增加,你渐渐的感觉这种方法不够用了。原因有很多:文字的描述不够直观,不可能到达一种很细致的程度。这时候就需要一种能够描述问题、描述解决方案、起沟通作用的语言。这就是UML。
UML(Unified Modeling Language 统一建模语言)是由Rational公司发明,目前由OMG(标准化对象管理机构)维护。作为一种建模语言,UML的定义包括UML语义和UML表示法两个部分:
UML语义
描述基于UML的精确元模型定义。元模型为UML的所有元素在语法和语义上提供了简单、一致、通用的定义性说明,使开发者能在语义上取得一致,消除了因人而异的最佳表达方法所造成的影响。此外UML还支持对元模型的扩展定义。
UML表示法
定义UML符号的表示法,为开发者或开发工具使用这些图形符号和文本语法为系统建模提供了标准。这些图形符号和文字所表达的是应用级的模型,在语义上它是UML元模型的实例。标准建模语言UML的重要内容可以由下列五类图(共9种图形)来定义:用例图、静态图、行为图、交互图、实现图。
从应用的角度看,当采用面向对象技术设计系统时,首先是描述需求;其次根据需求建立系统的静态模型,以构造系统的结构;第三步是描述系统的行为。其中在第一步与第二步中所建立的模型都是静态的,包括用例图、类图(包含包)、对象图、组件图和配置图等五个图形,是标准建模语言UML的静态建模机制。其中第三步中所建立的模型或者可以执行,或者表示执行时的时序状态或交互关系。它包括状态图、活动图、顺序图和合作图等四个图形,是标准建模语言UML的动态建模机制。因此,标准建模语言UML的主要内容也可以归纳为静态建模机制和动态建模机制两大类。
这样说,你可能还是不了解UML到底是什么,不过UML并不是我们讨论的重点,你只需要知道UML是一种建模语言,他的目的就是在开发团队之间提供一种通用的、简单的沟通机制,并且UML是面相对象的。
上面所说的这些就是阶段2的重点所在。使用UML语言对阶段1中提出的问题描述进行深化,从各方各面看待问题:顺序、流程、数据、状态、接口等。最终你得到的是一套完整的文档,做为详细的程序设计的参考和标准。
不要累坏自己
上面说了这么多在编程之前要做的工作,但是要注意的是,不是所有的开发工作都必须做这么多的工作的。对于你来说,抓住最重要的内容,不要涉及到太多的细节。对你写出来问题描述,必须要仔细的分析,而这里的分析呢,并不是要你用程序来实现你的问题描述,而是你必须从问题描述中分析出对象(object)、事件(event)和消息(message)。例如上面所提到的例子:
“若采取信用贷款方式,销售员就将顾客信用编号及总金额交给信用部门的信用审核人员。”
你可能看到这句话以后就会在想做一个审核信用的函数,参数部分有信用编号和总金额,然后开始设计程序的细节。如果你是这样干的话,这说明你还没有真正了解OO的思想,你的开发方式仍然停留在以前基于过程的开发方式中。那么面相对象的分析是怎样进行的呢。我们还是来看这段话,撇开你的程序,你的语言,你从这句话中获得了什么信息?是的,你知道说这个企业中有销售员、有信用审核人员;要求审核顾客信用是他们的工作之一;顾客的信用编号和总金额是审核顾客信用的时候的重要信息。这是任何一个普通的人看到这段话后的感觉,这就是OO的分析(在OO中这种的分析方法称为OOAD)。其实是很简单的,和你采用什么样的程序一点关系都没有。
软件重用(Reuse)是软件工程中最重要的思想之一,只有软件重用,才能降低软件成本,提高软件的质量。你在对一个软件进行分析的时候,找出可以重用的对象,有助于你开发高效的软件系统。正如前面所说的,你不必把软件分析的过分细致,你只需从中找出关键性的、能够重用的对象就足够了。剩下的事情,就是对这些对象分配属性和方法,并充分的使用这些对象就好了。
还是那个例子:我们已经从中看到了一些对象:销售员、信用审核人员。但是他们在系统中不具备重用性,至少是重用性不强。信用部门这个对象也存在这个问题。所以不能够把他们作为底层的对象,我们用一个术语Entity Objects 来称呼底层对象。那什么是软件系统中的Entity Objects呢?毛主席教导我们要透过现象看本质。上面的描述中有很多隐含的信息:
顾客请求信用贷款:这里就包括两个Entity Objects:顾客、信用贷款。
销售员、信用审核人员都是员工,所以员工也是一个Entity Objects。
观察一个Entity Objects,你会发现,Entity Objects已经是最小的单位,是使用软件的用户(这里是银行)最小的单位。当然不但是这个软件有Entity Objects,比如我们最常用的Word,我们可以想象一下它的Entity Objects有什么,可能是一种叫做图元的Entity Objects,一个图元包括了文字、图象以及其他的对象。
用OO的方法分析你的软件,从设计到实现都是非常的自然,可能你学习面向对象时是从C++开始的,被其中的虚函数、多态性、多基类继承搞得一头雾水。但是实际上OO的方法要比以前的方法简单的多,不相信?试一试,你就知道了。
校订、校订再校订
第3个阶段称为校订,这个称呼真是太贴切了,既不是测试,也不是返工。任何事物从诞生起都必须经历不断的改进才有可能成熟。(呵呵,说出这么有哲理的话,我都很佩服自己啊。)软件同样不例外。事实上,在阶段0中,我们就讨论了“路标”的概念,当你的第一个路标达成之后,剩下的应该都是属于校订的事了。通过和用户的交互,确定新的“路标”,不断的改进系统功能,优化系统结构,修正系统Bug。
正如作者所说的那样,真正OO的软件是经得起修改的,由于采用了多层的结构以及面向对象的思想,以前软件的致命伤(修改)在新的开发方法面前不会是个大问题。(注意,这并不是说你可以无规划构建你的软件)
由于以前的系统大多会将GUI、事务处理、数据存储都做在一起,当你需要修改一个地方的时候,你就会发现问题的严重性:一个小小的需求变动都意味着你的系统将面临伤筋动骨般的修改。在OO的时代里,所有的对象的访问都是通过接口(Interface)进行的,对象中方法的改变并不会接口产生影响,也就是说,调用该接口的模块不用做任何的修改。另外,如果你打算把你的系统的界面从C/S方式向B/S方式改变,同样不会有问题,你可以很容易的把GUI部分从原有的系统中剥离出来。软件的修改对你来说不再是一个恶梦。
成功的软件产品是建立在成功的需求基础之上的,而高质量的需求来源于用户与开发人员之间有效的沟通与合作。当用户有一个问题可以用计算机系统来解决,而开发人员开始帮助用户解决这个问题,沟通就开始了。
需求获取可能是软件开发中最困难、最关键、最易出错及最需要沟通交流的活动。对需求的获取往往有错误的认识:用户知道需求是什么,我们所要做的就是和他们交谈从他们那里得到需求,只要问用户系统的目标特征,什么是要完成的,什么样的系统能适合商业需要就可以了,但是实际上需求获取并不是想象的这样简单,这条沟通之路布满了荆棘。
首先需求获取要定义问题范围,系统的边界往往是很难明确的,用户不了解技术实现的细节,这样造成了系统目标的混淆。
其次是对问题的理解,用户对计算机系统的能力和限制缺乏了解,任何一个系统都会有很多的用户或者不同类型的用户,每个用户只知道自己需要的系统,而不知道系统的整体情况,他们不知道系统作为一个整体怎么样工作效率
更高,也不太清楚哪些工作可以交给软件完成,他们不清楚需求是什么,或者说如何以一种精确的方式来描述需求,他们需要开发人员的协助和指导,但是用户与开发人员之间的交流很容易出现障碍,忽略了那些被认为是“很明
确”的信息。
最后是需求的确认,因为需求的不稳定性往往随着时间的推移产生变动,使之难以确认。为了克服以上的问题,必须有组织的执行需求的获取活动。
需求获取活动建议要完成的11个任务或者说步骤分别是确定需求过程、编写项目视图和范围文档、用户群分类、选择用户代表、选择用户代表、建立核心队伍、确定使用实例、召开联合会议、分析用户工作流程、确定质量属性
、检查问题报告和需求重用。当然应该根据组织和项目的具体情况进行适当的裁减,比如根据项目和用户情况把需求获取会议改成问卷调查或者座谈等等。
1. 编写项目视图和范围文档
系统的需求包括四个不同的层次:业务需求、用户需求和功能需求、非功能性需求。业务需求说明了提供给用户新系统的最初利益,反映了组织机构或用户对系统、产品高层次的目标要求,它们在项目视图与范围文档中予以说明
。用户需求文档描述了用户使用产品必须要完成的任务,这在使用实例文档或方案脚本说明中予以说明。功能需求定义了开发人员必须实现的软件功能,使得用户能完成他们的任务,从而满足了业务需求。非功能性需求是用户对
系统良好运作提出的期望,包括了易用性、反应速度、容错性、健壮性等等质量属性。
需求获取就是根据系统业务需求去获得系统用户需求,然后通过需求分析得到系统的功能需求和非功能需求。项目视图和范围文档就是从高层次上描述系统的业务需求,应该包括高层的产品业务目标,评估问题解决方案的商业和
技术可行性,所有的使用实例和功能需求都必须遵从的标准。而范围文档定义了项目产品所包括的所有工作及产生产品所用的过程。项目相关人员对项目的目标和范围能达成共识。
2. 用户群分类
系统用户在很多方面存在着差异,例如:使用系统的频度和程度、应用领域和计算机系统知识、所使用的系统特性、所进行的业务过程、访问权限、地理上的布局以及个人的素质和喜好等等。根据这些差异,你可以把这些不同的
用户分成不同的用户类。与UML中Usecase的Actor概念一样,用户类不一定都指人,也可以包括其他应用系统、接口或者硬件,这样做使得与系统边界外的接口也成为系统需求。将用户群分类并归纳各自特点,并
详细描述出它们的个性特点及任务状况,将有助于需求的获取和系统设计。
3. 选择用户代表
不可能对所有的用户都进行需求获取,这样做时间不允许效果也不一定好,所以要识别出能够确定需求和了解业务流程的用户作为每类用户的代表。每类用户至少选择一位能真正代表他们需求的人作为代表并且能够作出决策,用
户代表往往是本类用户中三类人:对项目有决定权的领导、熟悉业务流程的专家、系统最终用户。每一个用户代表者代表了一个特定的用户类,并在那个用户类和开发者之间充当主要的接口,用户代表从他们所代表的用户类中收
集需求信息,同时每个用户代表又负责协调他们所代表的用户在需求表达上的不一致性和不兼容性。
4. 建立核心队伍
通常用户和开发人员不自觉的都有一种“我们和他们”的想法,产生一种对立关系,把彼此放在对立面,每一方都定义自己的“边界”,只想自己的利益而忽略对方的想法。他们通过文档、记录和对话来沟通,而不是作为一个合
作的整体去识别和确定需求完成任务。实践证明这样的方法是不正确的,不会给双方带来一点益处,良好的沟通关系没有建立导致了误解和忽略重要的信息。只有当双方参与者都明白要成功自己需要什么,同时也知道要成功对方
需要什么时,才能建立起一种合作关系。
为了建立合作关系通常采取一种组队的方式来获取需求,建立一个由用户代表和开发人员组成的联合小组作为需求获取的核心队伍。联合小组将负责识别需求、分析解决方案和协商分歧,小组成员可以采用会议、电子邮件、综合
办公系统等方式进行交流,但交流时应注意以下原则:小组会议应该由中立方来组织和主持,用户和开发人员都要参加;交流预先要确定准备和参与的规则;议题要明确并覆盖所有关键点,但信息来源应该自由;交流目标要明确
,并告知所有的成员。
5. 确定使用实例
从用户代表处收集他们将使用系统完成所需任务的描述,讨论用户与系统间的交互方式和对话要求,这就是使用实例,一个单一的使用实例可能包括完成某项任务的许多逻辑相关任务和交互顺序。使用实例方法给需求获取带来的
好处来自于该方法是用以任务为中心和以用户为中心的观点,比起使用以功能为中心和以开发者为中心的方法,使用实例方法可以使用户更清楚地理解和认识到新系统允许他们做什么和怎么做。描写使用实例的时候要注意使用简
洁直白的表述,尽量使用主动语态,以“系统”或者“用户”作为主语,比如“用户提交用户密码,系统验证用户密码是否正确”,还有一点在描述中不要设计界面细节,比如“用户从下拉框中选择产品类型”。使用实例为以后
写用例场景描述中的基本路径和扩展路径提供了素材。
6. 召开联合会议
最常见的需求获取方法是召开会议或者面谈,联合会议是范围广的、简便的讨论会,也是核心队伍成员之间一种很好的沟通方法,该会议通过紧密而集中的讨论得以将用户代表与开发人员间的合作伙伴关系付诸于实践并能由此拟
出需求文档的底稿。联合会议的第一个议题就是系统的必要性和合理性,必须所有成员都同意系统是必要的而且合理的。接下来就可以讨论使用实例清单,清单可以打印成大纸挂在墙上、写在黑板上或做成演示材料。对每个清单
合并去掉重复项,加上补充内容就可以得到一份总的清单,注意避免采用负面的“太差”“不可行”去否定用户的想法,这些想法都应该保留下来作为被评议的清单项,这样保护了小组成员开放的思维。最后对清单进行讨论,会
议成员必须检查每一个使用实例,在把它们纳入需求之前决定其是否在项目所定义的范围内,形成最终的需求报告。
在进行讨论时,也应该避免受不成熟的细节的影响,在对系统需求取得共识之前,用户能很容易地在一个报表或对话框中列出某些精确设计,如果这些细节都作为需求记录下来,他们会给随后的设计过程带来不必要的限制,应确
保用户参与者将注意力集中在与所讨论的话题适合的抽象层上,重点就是讨论做什么而不是怎么做。这里有一点很重要就是要让用户理解对于某些功能的讨论并不意味着即将在系统中实现它,更不要做暗示或者承诺什么时候完成
需求。在讨论之后,记下所讨论的条目,并请参与讨论的用户评论并更正,因为只有提供需求的人才能确定是否真正获取需求。
7. 分析用户工作流程
分析用户工作流程观察用户执行业务任务的过程,通过分析使用实例得到系统的用例图。编制用例图文档将有助于明确系统的使用实例和功能需求,统一建模语言的使用有助于与用户进一步交流。每个用例的描述应包括:
编号,为每个用例分配一个唯一的编号,为需求的追溯提供了方便;
参与者,与这个用例交互的actor;
前置条件,开始用例前所必须具备的系统状态;
后置条件,用例完成后系统达到的状态;
基本路径,用例完成的关键路径,也是用户期望的路径;
扩展点,基本路径的分枝,表示意外情况;
字段说明,路径中名称的进一步分解说明,对以后类属性的定义和数据库字段设计起作用;
设计约束,实现用例的非功能约束。
写基本路径时应该使用主动语句;句子以actor或者系统作为主语;一句表示一个actor动作,一句表示系统动作,交叉表现交互;不要涉及界面细节,比如“用户在文本框输入名称,下拉框选择类型”。
8. 确定质量属性
在功能需求之外再考虑一下非功能的质量特点,以及确定由于特殊的商业应用环境对系统提出的功能或性能上的约束,这会使你的产品达到并超过客户的期望。对系统如何能很好地执行某些行为或让用户采取某一措施的陈述就是
质量属性,这是一种非功能需求。听取那些描述合理特性的意见:快捷、简易、直觉性、用户友好、健壮性、可靠性、安全性和高效性。你将要和用户一起商讨精确定义他们模糊的和主观言辞的真正含义,并且要将质量属性分配
到每个用例的设计约束中去。
9. 检查问题报告
通过检查当前已经运行系统的问题报告来进一步完善需求客户的问题报告及补充需求为新系统或新版本提供了大量丰富的改进及增加特性的想法,负责提供用户支持及帮助的人能为收集需求过程提供极有价值的信息。
10. 需求重用
如果客户要求的功能与已有的系统很相似,则可查看需求是否有足够的灵活性以允许重用一些已有的软件组件。业务建模和领域建模式需求重用的最好方法,像分析模式和设计模式一样,需求也有自己的模式