《C++编程惯用法——高级程序员常用方法和技巧》——1.1 有关电话号码的抽象模型

简介:

本节书摘来自异步社区出版社《C++编程惯用法——高级程序员常用方法和技巧》一书中的第1章,第1.1节,作者: 【美】Robert B. Murray ,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.1 有关电话号码的抽象模型

在本节中,我们将对用于表示电话号码的类的抽象模型进行最初的探讨。我们期望用这个类来代指各种电话应用程序(如交换机系统、账单系统等)中的电话号码。

我们应该怎么开始我们的第一步呢?一个不错的方法就是:用一句话来描述该对象是用来干什么的(注意,不是“是什么”)。这种描述方式应该尽可能的抽象,尽量不要涉及对象的内部结构。这种“官面总结(executive summary)”应该尽可能的简单,简单到即便是行政人员也可以轻而易举地理解它。

例如,下面就是对于电话号码的一个糟糕的官面总结:

“电话号码包括3位地区号码,后面紧接着3位交换机号码,最后是4位数字。”

这样的描述并没有提及电话号码是用来做什么,或者它和谁交互的问题。相反的是,它简单地把电话号码的结构描述了一遍。这不但没有解释清楚电话号码是做什么的,它还限制了电话号码的范围。例如,通过modem所拨打的电话号码可以含有非数字的字符(如&就用于告诉modem来等待第二次的拨号音,另外还有#和*这两个特殊的按键)。更严重的就是,它还限制了在美国和加拿大之间能够合法通话的电话号码集。

下面的修改就要稍微好一些:

“一个电话号码指定了世界上的某一部特定电话。”

此处我们并没有丝毫提及电话号码的结构,它只是阐述了另一个用于电话号码的抽象。

当你写下这样的句子后,请花一些时间来仔细琢磨它。请像律师对待一份合法的合同那样仔细检查其中的每个单词。这句话中有什么明显的漏洞吗?它所隐含表达的意思又是什么?

让我们先来注意“指定”这个词。它意味着什么呢?一个电话号码是不是唯一指定一部电话呢?换句话说,能不能有两部以上的电话共用同一个号码呢?事实上,在许多的商业机构中,大部分电话都是共用一个电话号码的:在有电话进来时,会有一个本地的交换机将它转到一部空闲的电话上面去。同样,对于一个特定的电话来说,电话号码也不是唯一的。当你拨打555-1234时。对方的电话就取决于你拨打时所处的区域。

这样,我们就得知了:一个电话号码并不代表唯一一部电话,它的含义取决于使用它的区域。为了反映出这种更新,我们进行了如下的官面总结:

“当与呼叫电话关连起来时,电话号码就是决定被呼电话的关键。”

这样,我们就把电话号码与呼出电话的关系给涵盖进去了,并且也隐式地表达了被呼电话的唯一性。但让我们仔细看看这句话的后半部分。是不是说你拨打电话后就可以得到被呼电话呢?也许如此吧,但更精确的说法是:拨打电话会导致一个到被呼电话的连接的建立。这两种说法之间有什么不同呢?它们之间的不同完全取决于电话用户是否会对连接本身有兴趣。那么,在两台电话间的连接有什么属性会让人们感兴趣呢?当然有了:一个连接有一个开始时间(start time),一个结束时间(end time),以及一定的开销。它们不属于这两台电话,而仅仅是电话连接本身的属性。

拨号必定产生一个被呼电话的结论并不总是正确的:有时线路可能比较繁忙;有时也可能因为某些其他原因会导致呼叫失败……所有这些都不会产生我们所期望的被呼电话。有鉴于此,我们将上面的抽象结论继续细化为:

“当从呼叫电话拨号后,电话号码就是决定可能连接到的被呼电话的关键。”

上面的句子与我们开始时所给出的抽象表述相比,它更贴近实际应用中的抽象模型。然而,要想真正地了解它的含义,我们还必须定义一些它所依赖的其他抽象模型。例如:

“(电话间的)连接表示的是在两部(或多部)电话间的逻辑连接。”

1.1.1 什么不应该出现在抽象模型中?

没有出现在抽象模型中的东西和存在于模型中的一样重要。在我们上面给出的那个电话号码的抽象模型中,我们并没有假设出:一个电话号码有多少位;它是否包含非数字字符;电话与电话号码之间是否是一一对应的以及它们间的连接是如何建立的。

在保持实用性的前提下,我们通过尽可能地将该模型最小化以使其尽可能通用化。我们提高了它应付今后未知变化的能力,以避免频繁地修改我们的抽象模型(但实现细节可能有所改变)。例如:蜂窝电话的出现或者是标准电话系统中新增的按键都不致迫使我们修改我们的抽象模型。

1.1.2 如果存在疑问,暂不考虑

在吃不准某个特殊的概念是否应该包含于抽象模型中时,通常的安全做法是不去考虑它,而只是把它包含入我们的抽象模型中去。这是因为,由于缺少造成的错误通常都可以用一种向上兼容的方法进行修复——一般来说我们只需在类中新增一个成员函数就可以了。扩展接口总是比缩减接口要容易得多。从另一方面来说,从类中去除掉一个成员函数通常很难做到与现有代码兼容,因为可能已经有的用户代码中就调用了这个被去除的函数。

相关文章
|
28天前
|
安全 算法 C++
【C/C++ 泛型编程 应用篇】C++ 如何通过Type traits处理弱枚举和强枚举
【C/C++ 泛型编程 应用篇】C++ 如何通过Type traits处理弱枚举和强枚举
46 3
|
30天前
|
安全 算法 编译器
【C++ 泛型编程 进阶篇】深入探究C++模板参数推导:从基础到高级
【C++ 泛型编程 进阶篇】深入探究C++模板参数推导:从基础到高级
246 3
|
30天前
|
设计模式 程序员 C++
【C++ 泛型编程 高级篇】C++模板元编程:使用模板特化 灵活提取嵌套类型与多容器兼容性
【C++ 泛型编程 高级篇】C++模板元编程:使用模板特化 灵活提取嵌套类型与多容器兼容性
258 2
|
1天前
|
存储 搜索推荐 C++
【C++高阶(二)】熟悉STL中的map和set --了解KV模型和pair结构
【C++高阶(二)】熟悉STL中的map和set --了解KV模型和pair结构
|
7天前
|
编译器 C++
C++编程之美:探索初始化之源、静态之恒、友情之桥与匿名之韵
C++编程之美:探索初始化之源、静态之恒、友情之桥与匿名之韵
18 0
|
27天前
|
存储 C++
C++:二叉搜索树模拟实现(KV模型)
C++:二叉搜索树模拟实现(KV模型)
24 0
|
29天前
|
存储 移动开发 安全
【C/C++ 口语】C++ 编程常见接口发音一览(不断更新)
【C/C++ 口语】C++ 编程常见接口发音一览(不断更新)
22 0
|
29天前
|
算法 编译器 C++
【C++ 模板编程 基础知识】C++ 模板类部分特例化的参数顺序
【C++ 模板编程 基础知识】C++ 模板类部分特例化的参数顺序
21 0
|
29天前
|
机器学习/深度学习 人工智能 算法
【C++ 职业方向】C++ 职业方向探索:工作职责、编程技能与MBTI人格匹配
【C++ 职业方向】C++ 职业方向探索:工作职责、编程技能与MBTI人格匹配
163 1
|
29天前
|
安全 编译器 程序员
【C++ 泛型编程 高级篇】C++ 编程深掘:静态成员函数检查的艺术与实践
【C++ 泛型编程 高级篇】C++ 编程深掘:静态成员函数检查的艺术与实践
63 0

热门文章

最新文章