代码大全2(读书笔记7)

来源:互联网 发布:mac桌面的u盘图标 编辑:程序博客网 时间:2024/05/21 14:55

83、(抽象在里是一个归类,一个概念)抽象是一种能让你在关注某一概念的同时,可以放心地忽略其中一些细节的能力----在不同的层次处理不同的细节。任何时候当你在对一个聚合物品工作时,你就是在用抽象了。当你把一个东西称为“房子”而不是玻璃、木材和钉子构成的组合体时,你就是在用抽象了。当你把一组房屋称为“城镇”时,你还是在使用抽象。

以复杂度的观点看,抽象的主要好处就在于它使你能忽略无关的细节。大多数现实世界中的物体,都已经是某种抽象了。正如上面所提到的,房屋是门\窗\墙\线路\管道\隔板等物体及其特定的组织方式所形成的抽象。同样,门是一块长方形材料加上合叶和把手以及一种特定的组织方式的抽象。而门把手又是铜\镍\铁\钢等的一种特定形式的抽象。

人们一直都在使用抽象。如果每天你开门的时候都要单独考虑那些木纤维\油漆分子以及铁原子的话,你就别想再出入房间了。抽象是我们用来得以处理现实世界中复杂度的一种重要手段。(概念的总体性,主要性)

软件开发人员有时就是在木材纤维\油漆分子以及铁原子这一层次来构建系统,系统因此变得异常复杂,难以通过人的智力去管理。程序员没有给出足够高层的编程抽象时,系统有时就会被卡在门口了。

优秀的程序员会在子程序接口的层次上\在类接口的层次上及包接口的层次上―――-换句话说,在门把手的层次上\门的层次上及房屋的层次上―――进行抽象,这样才能更快\更稳妥地进行开发。

84、封闭就是实现抽象与高层次的主要方法。我只需要某个模块的主的功能,其它你都封装起来,我不用看,我只知道用。具体细节,你内部去处理。

 

85、信息隐藏是软件的首要技术使命中格外重要的一种启发式方法,因为它强调的就是隐藏复杂度,这一点无论是从它的名称还是其实施细节上都能看得很清楚。只留要用的东西,而且尽量简单易用。其它的东西,全部隐藏。

 

86、信息隐藏还有一个好处是,发生错误时只发生在一个区域,而不波及其它地方。

 

87、设计类的接口与设计其他环节一样,都是一个迭代的过程。如果你第一次没有得到合适的接口,好坏么就多试几次,直到设计稳定下来。如果设计仍不稳定,那你就需要换种方法再尝试。

 

88、隐藏设计决策对于减少“改动所影响的代码量而言是至关重要的。

 

89、隐藏设计的一个例子

假设你有一个程序,其中的每个对象都是通过一个名为id的成员变量来保存一种唯一的ID。一种设计方法是用一个整数来表示ID,同时用一个名为g_maxId的全局变量来保存目前已分配的ID的最大值。每当创建新的对象时,你只要在该对象的构造函数里简单地使用id=++g_maxId这条语句,就肯定能获取一个唯一的ID值,这种做法会让对象在创建时执行的代码量最少。可这样设计可能有问题吗?

好多地方都可能出错。如果你想把某些范围的ID留做它用该怎么办?如果你想使用非连续ID来提高安全性又该怎么办?如果你想重新使用已销毁对象的ID呢?如果你想增加一个断言来确保所分配的ID值不会超过预期的最大范围呢?如果程序中到都是id=++g_maxId这种语句的话,一旦上面说的任何一种情况出现,你就需要修改所有这些语句。另外,如果你的程序是多线程的话,这种方法也不是线程安全的。

创建新ID的方法就是一种你应该隐藏起来的设计决策。如果你在程序中到处使用++g_maxId的话,你就暴露了创建新ID的方法,也就是通过简单递增g_maxId.相反,如果你在程序中都使用语句id=NewId(),那就把创建新ID的方法隐藏起来了。你可以在NewId()子程序中仍然只用一行代码,return(++g_maxId),或者其他与之等价的方法。但如果日后你想把某些范围的ID留做它用,或者生用旧的ID时,只要对NewId()子程序的内部加以改动即可,无须改动几十个甚至成百个id=NewId()语句。无论NewId()内部做了多么复杂的改动,这些改动都不会影响到程序的其他部分。

现在再假设你发现需要把ID的类型由整数改为字符串。如果你已经在程序内部大量地使用了int id这样的变量声明的话,那么即使改用NewId()子程序也无济于事。你还得深入到程序内部,进行几十次甚至几百次的修改。

因此,另一个需要隐藏的秘密就ID的类型。对外界透露ID是个整形变量的做法,实质上是在鼓励程序员们对ID使用针对整数的操作,如> < =等。在C++里,你可以简单地使用typedef来把ID定义为IdType――――一个可以解释为int的用户自定义类型―――而避免将其直接定义成int类型。在C++和其他语言中,你也可以创建一个简单的IdType类。再强调一下,隐藏设计决策对于减少“改动所影响的代码量“而言是至关重要的。
原创粉丝点击