一句软件工程界的名言,让我想起了一个和一道笔试题有关的故事。希望更多的人了解 UML 背后的思想比他的语法更重要,是笔者写作本文的一点小愿望。

一、从一句软件工程名言说起

  对很多事情的处理上,东西方都大相径庭。究其根底,往往是东西方文化的差异使然。 “ 有工具的傻子还是傻子!( A Fool with a Tool is Still a Fool! ) ” 这句在软件工程界颇为有名的话,就体现了西方人说话不大客气的特点。作为中国人,您可能不大喜欢这句话的表达方式,但其内容的正确性是不容置疑的 —— 他强调了工具背后的思想才是最重要的。

  UML 作为 OMG 组织认可的一种标准化的可视化建模语言,近年来在国内外软件界很盛行 —— 相关的书籍不可谓不多,学习和使用 UML 的人不可谓不众。但是,笔者发现不少人犯了买椟还珠的毛病 —— 他们忘记了 UML 只是我们表达建模思想的工具,其背后的思想才是最重要的。

二、一道笔试题的故事

这道笔试题是这样的:

写出下列程式的运行结果:


    public class Test
    {
        static void Main(string[] args) 
        {
            Child child = new Child();
        }
    }     class Parent
    {
        public Parent()
        {
            Console.WriteLine("to construct Parent.");
        }
    }     class Child : Parent
    {
        public Child()
        {
            Console.WriteLine("to construct Child.");
        }         Delegatee delegatee = new Delegatee();
    }     class Delegatee
    {
        public Delegatee()
        {
            Console.WriteLine("to construct Delegatee.");
        }
    }

这道题很简单,就是考构造函数的执行顺序,输出结果如下:

to construct Delegatee. 
to construct Parent. 
to construct Child.

然而,应试者没有写出程式运行结果,倒是画了一张类图出来:

我问他:“您画的类图很好,用 UML 几年了?”

他说:“ 2 年多了。”

我说:“为什么不写程式运行结果呢?太简单了吗?”

他嘿嘿一笑,说:“这道题考的是构造函数的执行,我记不大清了。”

我说:“构造一个类时,他的父类和成员变量所属类的构造函数都会被自动执行,具体顺序是先 Parent 后 Delegatee 最后 Child ,是吧?”

他说:“对对对。但是,我不喜欢这些细节性的东西,还是图像化的类图更能表达程式的思想。”

我说:“是呀,那么请您谈谈这个简单的类图中的思想好吗?”

他无言。

三、 UML 背后的思想

  真是可惜,我本以为他会说出上面类图中的依赖思想呢。 UML 图里真的充满了思想,哪怕是上面那个如此简单的类图!

1、 继承的箭头为何指向父类

  相信至今更有人会画出类似下面的类图,小小的一个错误却叫人不禁扼腕!其实,大师们把继承的箭头方向规定为指向父类,是有深刻的设计思想的——他代表了依赖的方向!

  举个著名的面向对象原则——依赖倒置原则——的例子吧。依赖倒置原则( Dependency-Inversion Principle )规定:抽象不应依赖于细节,细节应该依赖于抽象。本原则几乎就是软件设计的正本清源之道。因为人解决问题的思考过程是先抽象后具体,从笼统到细节的,所以我们先生产出的势必是抽象程度比较高的实体,而后才是更加细节化的实体。于是,“细节依赖于抽象”就意味着后来的依赖于先前的,这是自然而然的重用之道。而且,抽象的实体代表着笼而统之的认识,人们总是比较容易正确认识他们,而且他们本身也是不易变的,依赖于他们是安全的。依赖倒置原则适应了人类认识过程的规律,是面向对象设计的标志所在。

  下图是著名的观察者模式的一个变体,我们研究一下这个例子中的继承关系。 Braodcaster 和 Listener 是 Framework 层的两个类,负责完成我们在研发的前期就抽象出来的“订阅-通知”机制。而 ConcreteBroadcaster 和 ConcreteListener 是使用“订阅-通知”机制的类,是通过继承实现的。显而易见,依赖倒置原则规定的“细节依赖于抽象”,在这里表现为“继承的箭头从子类指向父类”。

2 、回到笔试题

  其实,构造函数的执行顺序,何尝不是唯“依赖关系”马首是瞻呢?具体而言,就是“被依赖的先构造,依赖于人的后构造”。唯一可能的猫腻是:“跨层依赖”优先于“同层依赖”构造,如下图所示。

3、 买椟还珠

  春秋时代,楚国有一个商人,专门卖珠宝的,有一次他到齐国去兜售珠宝,为了生意好,珠宝畅销起见,特地用名贵的木料,造成许多小盒子,把盒子雕刻装饰得很精致美观,使盒子会发出一种香味,然后把珠宝装在盒子里面。有一个郑国人,看见装宝珠的盒子既精致又美观,问明了价钱后,就买了一个,打开盒子,把里面的宝物拿出来,退还给珠宝商。

  呜呼,买椟还珠的故事在我们身边重演,可惜呀!

一道笔试题和UML思想 ~的更多相关文章

  1. Java中有关构造函数的一道笔试题解析

    Java中有关构造函数的一道笔试题解析 1.详细题目例如以下 下列说法正确的有() A. class中的constructor不可省略 B. constructor必须与class同名,但方法不能与c ...

  2. 一道笔试题来理顺Java中的值传递和引用传递

      题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...

  3. 由阿里巴巴一道笔试题看Java静态代码块、静态函数、动态代码块、构造函数等的执行顺序

    一.阿里巴巴笔试题: public class Test { public static int k = 0; public static Test t1 = new Test("t1&qu ...

  4. 转:一道笔试题-将int型数组强制转换为char*,再求strlen,涉及大小端

    写出如下程序运行结果: #include<stdio.h> #include<string.h> int main() { int a[2000]; char *p = (ch ...

  5. golang 中 string 转换 []byte 的一道笔试题

    背景 去面试的时候遇到一道和 string 相关的题目,记录一下用到的知识点.题目如下: s:="123" ps:=&s b:=[]byte(s) pb:=&b s ...

  6. 通过一道笔试题浅谈javascript中的promise对象

    因为前几天做了一个promise对象捕获错误的面试题目,所以这几天又重温了一下promise对象.现在借这道题来分享下一些很基础的知识点. 下面是一个面试题目,三个promise对象捕获错误的例子,返 ...

  7. IGT一道笔试题

    1到n连续的n个数 输入m 得出m个有序序列 比如 输入为n=5 ,m=3 则输出 543 542 541 532 531 521  432 431 421 321 当前长度为i,每个位上的取之范围为 ...

  8. 一道笔试题:给定编码规则,实现decode()方法

    public class CodeDecode {     /*变换函数encode()顺序考察已知字符串的字符,按以下规则逐组生成新字符串:       (1)若已知字符串的当前字符不是大于0的数字 ...

  9. [matlab]一道笔试题

    x=[1 1; 1 -1; -1 -1; -1 1]'; X=-2:0.01:2; Y=X; N=length(X); [X,Y]=meshgrid(X,Y); Z1=0;Z2=0;Z3=0;Z4=0 ...

随机推荐

  1. nginx版本策略

    近期Nginx发布了1.17.0主线版本与1.16.0稳定版本,并且发布了一篇文章< Introducing NGINX 1.16 and 1.17 >说明Nginx的版本更新策略.推荐分 ...

  2. bzoj 2555 SubString —— 后缀自动机+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 ...

  3. Html5 canvas 元素

    canvas 元素用于在网页上绘制图形. 什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canv ...

  4. Arduino 视频教程

    http://v.youku.com/v_show/id_XNDU1MjI4MzA4.html?from=y1.2-1-176.3.12-2.1-1-1-11

  5. Centos7更新阿里yum源

    一.下载repo文件 wget http://mirrors.aliyun.com/repo/Centos-7.repo 二.备份并替换系统的repo文件 cp Centos-7.repo /etc/ ...

  6. Gym - 101142J Java2016 (构造)

    题意:给定一个数字,让你构造成一些表达式,最后结果是该数字的概率要大于50%. 析:我们可以把一个数分解是2的多少次幂,然后加起来就好. 代码如下: #pragma comment(linker, & ...

  7. 【Java】NIO中Channel的注册源码分析

    Channel的注册是在SelectableChannel中定义的: public abstract SelectionKey register(Selector sel, int ops, Obje ...

  8. Oracle GoldenGate部署系列

    在之前,为了某个项目,研究ogg 如何安装部署,已经对接大数据产品. 因为网上的很多资料都讲得不仔细,或者是版本对应不上,所以在部署时,遇到了非常多的困难. 作者根据自己的经验,录制了OGG整套部署和 ...

  9. 洛谷P4407 [JSOI2009]电子字典

    题目描述 人们在英文字典中查找某个单词的时候可能不知道该单词的完整拼法,而只知道该单词的一个错误的近似拼法,这时人们可能陷入困境,为了查找一个单词而浪费大量的时间.带有模糊查询功能的电子字典能够从一定 ...

  10. Linux常用命令(补充)-grep

    grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正 ...