第二桶 基于对象的编程 第一碗 老C初谈统一建模 小P开练建模语言(之一)

     “……所以,我们希望使得软件也可以像硬件一样——将实现同一功能的电路放在一起,做成集成电路并封装,只留下定义清晰的引脚作为接口——这样在需求相似 的地方,只要使用这个已经制造好的芯片就可以了,而无需再次设计电路。这就是复用的思想,这样可以极大的提高生产效率和技术的积累。正因为有了IC,硬件 发展的水平已经远远的将软件发展的水平甩在了身后,目前软件发展还只是进行到模块化而已,而就我所知系统级规模的复用也还是在发展阶段……还远没有到达软 件IC的地步……总之你要了解自己所处于的技术浪潮中,这样才可以更好的把握自己……”不知道两个人在聊什么,不知不觉就又聊到了编程这个话题。“同时软 件业可以像其它行业学习的东西很多,比如像硬件学习封装和复用,像建筑业学习模式,像心理学和工业设计学学习UI设计……等等等等,总之要心态开放,兼容 并包,虚心学习,不要以为自己有多么了不起——就各行各业的发展时间来看,软件业吃的饭还没有一些传统行业吃的盐多……”老C开始给小P狂喷。两个人下午 上完课也没有什么事情,干脆把椅子拉在一起狂谝起来。
     “嗯,我觉得你说的有些道理,那么我们的编程语言是如何对模块化进行支持的呢?”小P觉得自己的捧场很重要,如果没有自己说“然后呢……其他呢……”等 等,老C不会狂喷这么多有意思的话题,所以他很是恰当的在旁边煽风。“一开始的时候没有直接的模块化的支持,”老C道,“后来人们根据实际需求总结出来一 些使用语言的方法,形成一定的业内规范,将语言形成的代码组织得更容易形成模块。比如我们在使用C语言时,将模块的接口声明到.h文件,内部实现放在.c 文件并且用static声明,这样就提供了某些封装的方法——但不是强制的,如果你违反了这些规定,语言本身是拿你没有办法的——这个时候就需要从行政上 动脑筋……比如扣除一部分你的劳动所得等等,哈哈。”老C笑道,“但是这种约定只是在坊间流传,基本上不会在介绍语言的书籍或者课本上出现——因为这些是 工程经验,而理论虽然在理论上讲与实践没有什么区别,但是从实践的观点看,结论正好相反——因此企业不得不花费一些时间教会新手和菜鸟遵守某些坊间流传的 规矩和约定。”
     “哦?也就是说如果我们毕业就算找到工作,也还是不能马上就给企业带来效益的?”小P问。
     “嗯,是的。所以虽然企业内部急需要人才,但是应届毕业生工作还是挺难找的,因为很多企业不想花费一些培训和引导的成本,所以就在社会上寻找有经验的人。 但是有经验的人哪里这么好找啊……于是就出现了矛盾——一方面好多人找不到工作,另一方面企业又需要人……”老C道。
     “哦?那么没有什么好的解决方法吗?”小P问。
     “我觉得也有办法,学校尤其是一类院校可以从企业吸收一些高级人才,充当一线教师和导师……但是这里面牵扯了方方面面的利益,实现起来比较困难。同时由于 学校的学术界有固步自封的倾向,一味追求理论上的高新,基本上不会考虑实现上的问题,导致大量水文的出现,造成一定程度上毕业生质量的下降。我觉得如果一 个人可以很好的将某种理论以实际的方法实现,应当也颁发学历和学位的——因为这样学术研究才会真正变为生产力——要知道数字信号处理在FFT变换出来之前 也只是理论上的玩具而已,但是随着FFT的被发现,信息技术才有了突飞猛进的发展啊……”老C感概道,“呵呵,一下子说的远了,跑题,跑题……”他咋咋 嘴,叹了一口气,“题外话就不多说了,我们再来看看随着科技的发展,语言又对我们的模块化编程提供了哪些支持吧。”
     “哦,然后呢?”小P问。
     “然后随着人们经验的增加和积累,发现在语言层面对模块这个概念提供支持是很好很强大的想法,至于怎么实现模块化,见仁见智,相互PK,总之我们看到的结 论是经过在市场上的残酷厮杀,面向对象理论发展了起来。”老C道,“其实我们用非面向对象的语言也可以实现面向对象的某些思想,比如可以在C中用结构体+ 对结构体操作的函数的方式构造我们的模块,但——你也看到了——到底没有语言上直接支持来的方便和轻松。”老C挠挠头,“因为人们开始接受面向对象的语 言,如何对设计过程和设计所使用的模型进行描述又有了新的争议……”
     “哦?什么是设计模型?”小P问。
     “……简单的说,我们在盖房子的时候一般都会先简单的画出一个草图吧,也叫蓝图,blue print的东东,然后再进行详细的计算和设计……没有见过没有图纸就直接上的,这样既不安全,出了问题也比较难以修改,这个就是草图和蓝图的作用,而草 图和蓝图描述的就是房子的模型——因为房子只出现在概念中,还没有被实际盖出来。”老C觉的要向这个无知青年解释清楚还是比较累人的,“又比如我们要进行 一个飞机场空中管制和航班管理的软件,你会怎么做?”
     “呵呵,依我现在的水平——不要想,就是我的做法……”小P答道。
     “……也是……哈哈,我觉得你应当先去买一套飞机场的玩具,然后模拟几次飞机的起降过程,并人为的制造一些障碍,比如飞机晚点,天气不好等等,来熟悉你即将碰到的问题并想办法解决之。这就是建模的过程,体现了一些模型的重要性。”老C笑道。
     “哦,我明白了,”小P高兴的说道,“就是说在实际实现前,概念上和理论上的对问题进行仿真和建模,并用某种方式表达出来,这样对开发过程很有益处……”
     “没错没错。”老C同意,“就像流程图这个我们在结构化编程时经常使用的建模工具,在面向对象时代也有类似的,但是更强大的工具来支持我们建模。同时这种 工具不但可以在外部对问题进行描述,对问题域进行记录,而且还可以记录解决问题的方案,程序的结构等解决域的内容。”他想了想,又说道,“在历史上有多种 这样的符号和图形系统——毕竟一图顶千言,哦,不,是正确的清晰的一图才可以顶千言——最后经过努力这些图形和符号都统一为一种符号和表述方式……就像电 路符号是实际电路的建模一样,如果同时存在7、8种电阻符号,那样引起的混乱有可能比没有建模还严重呢。”
     “喔?这么说其实建模的工具就是一些用来描述问题和软件结构的图形和符号?就像我在电路课程中学习的电阻、电感和电容符号那样?”小P问。
     “没错!这种被统一后的符号集和图形集被称为UML,近来还在里面加入了一些在符号间找来找去的脚本语言……”老C接着道,“所谓UML,就是Unified Modeling Language的简称,从Unified这个词,你就可以看出它发展的历史。”
     “哦,原来名字的来历是这样啊。”小P道。
     “是啊,无论怎么样,统一和标准是我们的需求,只有用统一的标准的符号我们才可以更好的交流。一个反面的例子是我们上数字电路里面的与门、非门、与非门和 或门等等的逻辑符号,国家标准与业界流行的标准就不一样,导致学生在毕业的时候可能看不懂行业内的电路图——就事实而论,我们大部分的电路模块产品和芯片 的说明手册还是欧美的居多——这样即加重了企业负担,可能需要再花一部分精力来培训新人,也增加了学生的负担——为了在毕业的时候增加些许竞争力,不得不 学习两套符号系统。总之我觉得这个事情还是比较脑残的,让我想到窄轨铁路……”老C借机发泄了一下从毕业就开始累积的郁闷。
     “呵呵……”小P嘴上打着哈哈,心想,不就是多记几个框框嘛,对自己影响不是很大啊,“消消气,我们还是来说说UML本身吧。”小P道。
     “嗯……我觉得首先我们得先明确几个概念——要知道概念是比技巧更重要的东西——为了明确这些概念,我们最好先来谈论一些哲学问题。”老C道,“首先来UML的阴与阳。”
     “阴与阳?”小P槑。
     “对,呵呵,无极生太极,太极生两仪,两仪生八卦……”老C开始转文。
     “八卦?我觉得隔壁的行司就比较八卦……”小P小声说道。
     “哈哈,这里说的阴与阳,是指UML模型中class与object概念的对偶,静态模型与动态模型的区分。”老C道,“这些都是不同的概念,我们现在来仔细说说。”
     “哦?是吗?那太好了。”小P道。
     “首先我们来区分class与object的概念,什么是class?什么是object?我们先在概念上讨论一下,然后再看看在C语言里是怎么一回事。 首先讲概念,我们来打个简单的比方。”因为要开始长篇大论,老C把自己的茶杯端到手里,“比如你在一村闲逛,看到一只小狗在树下面小便,你会说‘狗撒尿 ’……”
     “哦,这个例子显得……每下愈况……”小P道。
     “呵呵,你总结的很好很强大……”老C突然有了伯牙遇子期的感慨,“话说高山……哦,不,狗撒尿,在这里,狗就是类的概念。”老C道,“因为所有的狗,无 论什么品种,都会撒尿,因此你会建立一个‘狗’的概念,这个‘狗’只是存在于理性世界当中,并不是真实存在的,只是一种模型而已,这就是对类这个概念的简 单理解。如果你知道这条狗叫旺财,你会说‘旺财撒尿’,那么这里‘旺财’就是‘狗’这个类的一个对象,因为‘旺财’是‘狗’这个概念的实体。”
     “喔?这样说来就是概念与实体的区别了?”小P问。
     “嗯,可以先简单的这样理解。”老C说,“而‘撒尿’就是‘狗’这个类所具有的‘操作’,就是说只要是‘狗’,一定会‘撒尿’。”
     “哦,有点需要理解力了。”小P道。
     “呵呵,可以这样理解,‘狗’与‘撒尿’这两个都是概念,生活在理性的世界,而‘旺财’和‘旺财的撒尿动作’是实体,生活在现实世界。”老C解释道,“但是理性世界的概念在实例化之前不会有任何作用……因为它们本身都是概念而已。”
     “太抽象了,来点具体的吧。”小P埋怨。
     “呵呵,形而上者谓之道,形而下者谓之器,先道而后器者,几稀!”老C又转文,“可以可以,我们在C++中举个简单的例子。”他又指挥小P拉过来白板并擦干净,写下如下代码。

class Dog
{
public:
    Dog(const string& name) : name_(name) {}
    piss() {}
private:
    string name_;
};

int main()
{
    Dog wangCai("Wang Cai");
   
    wangCai.piss();

    return 0;
}

     “看,我们的Dog类,在还没有生成wangCai对象前,并没有什么实际的作用,它只是记录了一些类型和函数的信息而已。然而一旦生成了wangCai 对象,那么在实际内存中——无所谓是在栈还是堆——都占有了一席之地,而这个对象的行为都会依照我们class内部的设定而进行。”老C道。
     “唔,这么一说,我倒是理解了很多。”小P道。
     “呵呵,还是要在实际编程中多体会和领悟。”老C说道。“现在我们来说说class和object如何在UML中表示,没有什么难的,就像电阻、电感或者 电容一样,只是一种记号。”老C道,并在白板上画了两个框框,“不同的访问等级分别用+,#,和-表示,你可以google一下class diagram,查找一些具体的信息。”他接着说道,“有了class和object的表示方法,我们需要了解一下如何表示它们之间的关系。”     
     “哦?”小P一副疑惑的样子。
     “因为我们的对象都不可能是孤岛,对象之间需要相互协作才可以完成一些功能。形而下的对象之间如何发生了相互的联系,那么在形而上的类之间就会塑模出各种 关系。”老C说道,“我们先来说说最简单的也是最宽泛的一种关系——对于类来说叫association,对于对象来说叫link……你要习惯这种概念体 系,因为在UML中,形而上和形而下被区分的很明显,你要理解这种概念上的对偶。”
     “那么什么叫做association呢?”小P问道。
     “嗯,只要有物理上或者概念上的关联,都可以建模为类之间的association,或者对象之间的link。”老C回答,“同样我们可以举例说明一下。 比如我们选课,你选择了《数字信号处理》、《数理统计》和《现代控制理论》,那么你就和这些课程之间发生一些link,因为你是对象,而这些课程也是对 象;我选择了《计算机通信原理》,《数理统计》和《现代测控原理》那么我这个对象和这些课程对象之间就发生了一些link——上升到理性世界,就是形而上 的世界,那就是Person这个类与Course这个类之间发生了association。”
     “哦?是这样啊……”小P想了想,“那么怎么样用association表示link的数量呢?因为已经抽象到另一个层次中……”
     “呵呵,没有关系,我们可以用multiplicity来表示,比如这个学期我们每个人可以最多选5门,最少选3门课,可以在class diagram中用multiplicity来这样表示……”老C说着画了一个图,“你先理解到这里就够了,因为UML是一个理论性很强的东东,没有必要 一下子就深入进去,这样反而无法学好。我们先一个一个慢慢来,由浅入深,由此及彼。”
     “嗯,你说的有些道理。”小P道。
     “先在我们只要知道class之间有association就可以了,至于这种association具体到什么地步,那是下一步的事情。所谓建模是见仁 见智的事情,除非重大错误,否则你总可以认为你这样建模是对的,因为你观察问题的角度就是这样……”老C道,“我们现阶段就只要先搞清楚有几个class 存在关系就行了。”
     “呵呵,好的。”小P心想还没有人教他这样不求甚解的学习。

Link



Association
     “下来我们需要掌握sequence diagram,”老C道,“关于UML,有3中模型,分别是class model,state model和interaction model,前一个class model是静态模型,后两个是动态模型,这是UML中除形而上和形而下外又一对阴阳。”他喝了一口茶,“我们先把state model放一边,先学习一下interaction modle中的sequence diagram。而且同样也不要太深入,只要先了解一些够我们用的部分就行了。”说罢他在白板上先写下可见性三个大字。

可见性

     “不是要说sequence diagram吗?”小P不解的问。
     “哦,sequence diagram主要是描述对象间是如何交换信息的,在此之前我们需要简单的说说对象间交换信息的方式。”老C回答,“否则可能你对message这个概念的理解会困难一些。”他接着说,“你能告诉我两个对象之间怎么传递信息吗?”
     “哦,我想想……”小P想了一回,“如果对象a需要对象b的信息,那么对象a可以调用对象b的提取信息的成员函数……”
     “没错,这是一个办法,”老C点头,“如果我们把对象想象为一个一个的小岛,它们之间需要通过交换信息来共同解决问题,那么你可以想象message就是 它们之间往来的小船,这些小船携带了需要交互的信息。比如a岛需要b岛的信息,或者它需要将信息发送到b岛,作为活动发起人,它需要b岛提供船只,然后将 信息从船上取出,或者将信息放入船上。你先这样理解,信息的接受和发送都是被动的,如果a是发起者,那么它就需要b提供交通工具——因为你现在碰到的都是 被动类,等我们遇到了主动类,再来升级我们的认识。这样在C++中,如果对象a需要向对象b发送一个消息,那么对象b需要提供一个接口;具体来说就是a调 用了b的成员函数。”
     “哦,那我就先这样理解着。”小P回答。
     “是啊,因为一步到位的很正确和深刻的认识这个问题也不现实,我们需要在不断的实践中迭代的修正我们的观念。”老C道,“现在我们来看看,如果对象a需要调用对象b的函数,那么对象b必须对对象a来说是可见的,你说说在C++中怎么样才具有这种可见性呢?”
     “唔……好像对象b要是对象a的一个成员变量?”小P不是很确定。
     “嗯,只是一种情况。”老C回答,“如果对象b对于对象a可见,可能存在以下几种情况。”说着他在白板的可见性几个字下面又增加了几行。

可见性

1. b 在 全局范围内。
2. b 是a的成员变量。
3. a有一个指向b的指针(或引用),这个指针(或引用)被正确的初始化。
4. a的成员函数含有b的指针或引用的参数。
5. b的定义在a定义的外层。


     “看,虽然在模型中都由a发送message给b代所塑模,但具体实现上我们可以有至少这么多的方案供选择。”老C说,“不要狭隘的理解message, 无非就是信息交换而已。”他想了想,“为了保持你的好奇心和进取心,我再给你简单说说当两个对象不可见时它们怎么交换信息……”
     “哦?这样它们也可以交换信息?”小P追问。
     “这时C++语言没有提供直接的帮助,我们需要借助外力。如果我们使用类库,可以用boost的signal/slot机制,也可以用Qt的signal /slot机制;如果我们在windows下编程,可以借助windows操作系统的消息并借用MFC的消息映射机制;如果这些都不可用,我们还可以自己 依照command模式和observe模式设计一套机制来自己使用……这些话题我们以后一定可以讨论到,现在就先不要着急啦。”老C吊起了小P的胃口, 但是又不再继续下去。
     “是吗?”小P问道,心想自己需要学习的地方还挺多的。
     “好,现在我们就具体看看sequence diagram。”老C说道。说着他让小P打开电脑,照着AppleGame的代码在白板上画出了如下图形。

AppleGame


sd PlayAppleGame

     “我来解释一下。”老C先指着class diagram AppleGame说道,“在这里我们只要先知道AppleGame类与ChildList类有关联就可以了,至于具体是什么关联,我们以后再说。”然后 他解释道,“由于我已经知道这两个class的成员函数了,为了省事就直接写在里面,其实更合理的做法是先不要在这里写需要的成员函数,而是应当在有了 class diagram后马上去建模sequence diagram,根据解决问题的需要再回头给class 中添加具体的成员函数。”看到小P看得聚精会神,他就停了一会儿,喝了一口水,等小P先消化消化。
     “……嗯,然后呢?”几分钟后,小P问道。
     “sequence diagram表示了对象间数据交换的顺序和过程,你可以在每个message上看到标注的数字,那表示顺序。”老C接着说道,“每个对象下面垂直的虚线 叫life ine,表示对象的生存期;虚线上的长条矩形叫做activation,表示对象是否活跃,你就认为是函数的执行期,activation之间可以重叠; 水平的实线实心箭头表示同步消息,关于同步消息和异步消息我们以后再讨论,你现在全部使用同步消息就可以了,指向对象自己的消息表示调用自己的函数;虚线 表示返回消息,你可以理解为返回值;中间的方框叫combined fragments,包括alternatives, options 和 loops。你可以根据我们已经有的代码体会体会sequence diagram的用法。”他想了想,“对了,关于图的名称也有要求,sequence diagram要求以sd开头,后面是所描述场景的概要说明,比如我们这里的sd PlayAppleGame。”
     “哦,我学习学习。有什么线索没有?”小P追问。
     “嗯,关于UML工具有很多,跨平台,GPL的也不少,我试用了一些,感觉visual paradigm和magic draw还不错,这两个都有community版本的,可以供我们学习和进行非商业活动用。你还可以登陆到www.umlchina.com,那里也有一 些很不错的资料和书籍介绍。但是根据我的经验,UML还是要多用,而且不要一次学习的过于深入为好,因为UML的语义很丰富且理论性比较深一些,而且同样 的事情可能有不同的图形都可以描述,所以最好根据需要,一点一点的学习,边学边用最好。”老C说道。
     “哦,是啊。”小P点点头。
     “UML是建模工具,不是编程工具。模型需要对实际的事物进行合理的剪裁和取舍,注意模型的清晰性比信息的完备性更重要,如果不论青红皂白的将所有信息一 股脑全部放在模型上,那样图形看起来会很恐怖的。”老C接着解释,“所以不要要求模型完全反应细节信息,只要在大方向上对就可以了。同时你还要了解模型所 要描述的问题规模,如果是一个大型的交易系统,按照我绘出的sequence diagram的详细程度,那是根本不可能的。在描述这样的系统时,可以省略足够的细节,可以在框架结构的规模上表现清楚就可以了。”老C道。
     “是么?看来我还需要在实践中学习啊。”小P说道,“看来以后你还要多给我说说这方面的道理。”
     “呵呵,好啊。反正国庆假期也快到了,如果你没有什么事情的话就继续完善我们的sd PlayAppleGame如何?将List类也加入其中。” 老C问道。
     “好啊好啊。”小P道,“我可以趁没有出去玩的时候自己画画试试。”他想了想,“但是如果有什么不会的我可要打你的电话啊。”
     “当然可以,”老C说道,“如果没有人接那是我在外面没有听见,你最好晚上打。”

(看看小P如何完成sd PlayAppleGame)

注: 本章中的许多内容都穿越啦。Visual Paradigm在2003年还没有出来这一套UML2.1标准的UML工具,而老C说的在class model中导航的OCL语言也是在2006年左右才出来的。本章中sequence diagram中使用的很多符号都是UML2.0标准的,这在2003年根本没有……


posted on 2009-02-26 15:34 Anderson 阅读(1862) 评论(5)  编辑 收藏 引用

评论

# re: 第二桶 基于对象的编程 第一桶 老C初谈统一建模 小P开练建模语言(之一) 2009-02-26 20:22 ZJOK

很好,
再通俗点就好了!!!!!!!!!!!!!!!!  回复  更多评论   

# re: 第二桶 基于对象的编程 第一碗 老C初谈统一建模 小P开练建模语言(之一) 2009-03-16 19:01 supersand

楼主继续~  回复  更多评论   

# re: 第二桶 基于对象的编程 第一碗 老C初谈统一建模 小P开练建模语言(之一) 2009-05-23 17:47 ty

阅过留名,楼主辛苦了!  回复  更多评论   

# re: 第二桶 基于对象的编程 第一碗 老C初谈统一建模 小P开练建模语言(之一) 2009-09-07 23:17 billow

跟进阅读中,感谢lz。  回复  更多评论   

# re: 第二桶 基于对象的编程 第一碗 老C初谈统一建模 小P开练建模语言(之一)[未登录] 2010-10-07 22:07 Andrew

看不到代码的?  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2009年1月>
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

导航

统计

常用链接

留言簿(6)

随笔档案(21)

文章档案(1)

搜索

最新评论

阅读排行榜

评论排行榜