我的《冒号课堂》学习笔记设计原则间接原则

Posted 庸人、自扰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的《冒号课堂》学习笔记设计原则间接原则相关的知识,希望对你有一定的参考价值。

间接原则

 

All problems in computer science can be solved by another level of indirection, except of course for the problem of too many indirections.

——David Wheeler

这是一句计算机界的名言。在计算机领域中这样的例子数不胜数,像文件系统中的路径path,HTTP中的URI、数据库中的外键foreign key、程序中的变量均具有间接指代作业。

 

先来谈谈变量,在命令范式编程中,变量是抽象化的内存,是不可或缺的机制。即使在非必要的情况下,选择合适的变量仍然是值得推荐的。比方说,初学者代码中经常会出现一些令人费解的常数值,俗称幻数(magic number或magic constant)。尽管从理论上说它们并非错误,但大多数时还是采用变量更为恰当。变量比幻数更能凸显编程者的意图,增强了代码的可读性。当幻数出现在多处而又需要修改时,用变量代替后就能一举多得。再来看函数,函数和变量一样,是在过程式编程中最基本的要素之一,二者的机理也同出一辙——都提供了一种抽象机制和间接手段,分别把代码和表达式抽象化和间接化。抽象的意义在于:一方面掩盖了具体的细节,提高了代码的简洁度;另一方面赋予了明确的语义,提高了代码的清澈度。而简洁的意义在于:一方面建立了名与实的映射,提高了代码的一致性和可维护性;另一方面实现了名与实的分离,提高了代码的灵活性和可拓展性。抽象和间接在字面上相去甚远,但在软件设计中二者却有内在的逻辑关联,尤其当它们同为‘层’(layer)的修饰词时。事实上,那句名言中的indirection常常有意无意地为abstraction所代替。间接层与抽象层可以看作同一事物的两个方面:一个适当的中间层(不限于狭义的代表应用服务层的中间层),在形式上表现为间接层,在实质上体现为抽象层。在软件设计中,体现这种统一性的范例俯拾皆是。比如出于安全原因,应用程序一般无权直接与硬件打交道,只能通过操作系统最核心的部分——内核(kernel)间接地访问底层资源。作为硬件与应用程序的中介,内核提供了抽象的API接口,使得应用程序能借助系统调用(system call)向其请求服务。JVM、CLR之类的虚拟机也当属此类,它们在操作系统之上提供了新的间接抽象层。只不过内核的重点是安全性和性能,而JVM和CLR除此之外还有可移植性、开发效率、业界标准等其他考量。此外,多层架构(multi-layered architecture)也是运用间接原则的典范,最著名的包括网络协议的OSI7层模型(OSI Seven Layer Model)、TCP/IP4层模型和网络应用系统的3层或N层架构(n-tier architecture)。这类架构的特点是:每一层都有特定的职能,一面向上层提供服务,一面向下层寻求服务;下层不依赖于上层,上层只依赖于相邻的下层(这类架构被称为封闭架构(closed architecture)或不透明分层(opaque layering),如果上层能直接请求非相邻下层的服务则被称为开放架构(openarchitecture)或透明分层(transparent layering)。)。特别地,如果某一层是一个相对的独立的子系统,那么它在概念上等同于一个具有特殊使命的虚拟机。

MVC代表3个模块:模型(Model)、视图(View)和控制器(Controller),而最常见的3层架构分别是:表现层(presentation tier/layer)、业务层(business tier/layer)和数据层(data tier/layer)。初看起来,二者似乎是一一对应的关系:模型和数据层都关乎数据访问、视图和表现层都关乎用户界面、控制器和业务层都关乎逻辑控制,但它们之间的相互关系却有很大的差异。

MVC架构和3层架构除了模块之间的相互作用和流程有所不同外,它们的应用领域和范围也各有侧重。MVC作为架构或设计模式主要用于交互式系统,如基于GUI或web的前台(front-end)应用。单以Java为例,既有Swing、JFace等GUI工具包,也有Struts、JSP、Spring MVC、WebWork、Tapestry等web应用框架。而3层架构则通常是最高层的架构设计,多出现在企业级应用中。

MVC架构有很多的变种,图12.2表示的是适用于GUI应用的一种简化形式,图12-3表示的是适用于web应用的一种简化形式。

与一般应用相比,企业应用(enterprise application)通常包含专门领域的商业逻辑,系统的业务需求和应用环境更为复杂多变,常以多用户、大数据量、分布式、高并发、高集成、跨平台为特征,对软件质量的要求相对也更高。人们不仅需要保证包括可拓展性(extensibility)、可维护性(maintainability)、可重用性(reusability)等在内的设计质量,更对包括安全性(security)、可靠性(reliability)、可伸缩性(scalability)、性能(performance)、可获性(availability)、互相性(interoperability)等在内的运行于不同的服务器上,有助于提供软件的运行质量。3层架构与MVC架构并不是对立的,后者常常嵌入前者的表现层。下图是一个基于Java EE的应用架构。

 

下面讨论下间接原则在设计模式上的应用。但在此之前,先从另一个角度重新审视OOP。首先考察封装,它把相关的数据和运算包装后再设置访问控制。外界无法直接操作被隐藏的数据,只能通过公开接口间接地读取或改写这些数据。

类的公开接口集即API担任了间接层的角色,成为外界与内部实现的联系桥梁。在使用者看来,API是访问服务类的唯一中介;在维护者看来,服务类可以自由地更换具体实现而不担心影响客户类。进一步地,人们还能在客户类与服务类之间插入新的间接层——接口(interface)。该接口在编译器为实现类所继承,在运行期通过多态机制绑定实现类。我们从图形上对比一下(如图12-5所示)。

OOP的3大基本特性分别带给对象3种身份,每种身份都是规范抽象的结果。其实分离原则也好,间接原则也罢,背后的核心仍是抽象原则。封装带来的接口与实现的分离,使得类的API成为间接层,从而完成数据抽象;继承和多态带来的接口与实现的分离,使得类的超类型成为间接层,从而将数据抽象升级成多态抽象。在联系到前面探讨的间接层与抽象层之间、规范与抽象之间的关系,我们可以得出这样一个结论:间接、分离、抽象、规范,这几个在日常语义中似乎没有必然联系的概念,却在计算机领域中奇妙地达成了一种契合。特别而言,由于它们充分体现了OOP3个基本特征的精髓,理所当然成为OOD(面向对象式设计)的不二法门。

 

引入具有间接功能的抽象模块,既能降低模块之间的相互依赖性和影响度,又能使每个模块的职责更清晰、更专一,从而使整个系统更符合低耦合和高内聚的要求。不过间接原则也不能滥用,过多的间接层会以牺牲系统的简单性或失控性能为待机,在实践中须权衡利弊。比如,Swing采用的其实是简化版的MVC,它将结合较为紧密的视图和控制器合并为UI委托(UI delegate)。同样,3层架构在简单的系统中可退化为2层架构,在复杂的系统中又可进化为4层或5层乃至更多层的架构。

 

总结:

 

以上是关于我的《冒号课堂》学习笔记设计原则间接原则的主要内容,如果未能解决你的问题,请参考以下文章

我的《冒号课堂》学习笔记设计原则内聚原则

设计模式学习笔记 单一职责原则的判定与设计

C++设计模式学习笔记:面向对象设计原则

C++设计模式学习笔记:面向对象设计原则

设计模式学习笔记“里氏替换原则”

设计模式学习笔记“里氏替换原则”