返回顶部
首页 > 资讯 > 后端开发 > Python >DeepModule深模块之软件设计
  • 931
分享到

DeepModule深模块之软件设计

2024-04-02 19:04:59 931人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录正文1,模块化设计2,接口里有什么3,抽象4,深模块5,浅模块6,Classitis7,例子8,结论正文 类是不是越小越好?最近在读John Ousterhout的《A Phil

正文

类是不是越小越好?最近在读John Ousterhout的《A Philosophy of Software Design》,感到作者文笔流畅,书中内容具有启发性。这里摘要一部分内容,以供开发工作中的参考、学习

在软件复杂度的管理当中,最重要的技术之一是通过对系统的设计,使开发者任何在时候都只需要面对整体复杂度中的一小部分。这个过程被称为模块化设计

复杂度是什么?在本文中,复杂度的定义是:和软件系统结构有关的、会导致理解和修改系统变困难的东西。

1,模块化设计

在模块设计中,软件系统被分解为相对独立的模块集合。模块的形式多种多样,可以是类、子系统、或服务等。在理想的世界中,每个模块都完全独立于其它模块:开发者在任何模块中工作的时候,都不需要知道有关其它模块的任何知识。在这种理想状态下,系统复杂度取决于系统中复杂度最高的模块。

当然,实践与理想不同,系统模块间总会多少有些依赖。当一个模块变化时,其它模块可能也需要随之而改变。模块化设计的目标就是最小化模块间的依赖。

为了管理依赖,我们可以把模块看成两部分:接口实现

接口包含了全部的在调用该模块时需要的信息。接口只描述模块做什么,但不会包含怎么做

完成接口所做出的承诺的代码被称为实现

在一个特定模块内部进行工作的开发者必须知道的信息是:当前模块的接口和实现+其它被该模块使用的模块的接口。他不需要理解其它模块的实现。

在本文中,包含接口/实现的任何代码单元,都是模块。面向对象语言中的类是模块,类中的方法也是模块,非面向对象语言中的函数也是模块。高层的子系统和服务也可以被看作模块,它们的接口也许是多种形式的,比如内核调用或Http请求。本文中的大部分内容针对的是类,但这些技术和理论对其它类型的模块也有效。

好模块的接口远远比实现更简单。这样的模块有2个优点。首先,简单的接口最小化了模块施加给系统其余部分的复杂度。其次,如果修改模块时可以不修改它的接口,那么其他模块就不会被修改所影响。如果模块的接口远远比实现简单,那么就更有可能在不改动接口的情况对模块进行修改。

2,接口里有什么

接口中包含2种信息:正式的和非正式的。

正式的信息在代码中被显式指定,程序语言可以检查其中的部分正确性。比如,方法的签名就是正式的信息,它包含参数的名称和类型,返回值的类型,异常的信息。很多程序语言可以保证代码中对方法的调用提供了与方法定义相匹配的参数值。

接口里面也包含非正式的元素。非正式部分无法被程序语言理解或强制执行。接口的非正式部分包含一些高层行为,比如函数会根据某个参数的内容删除具有相应名字的文件。如果某个类的使用存在某种限制,比如方法的调用需要符合特定顺序,那这也属于接口的一部分。凡是开发者在使用模块时需要了解的信息,都可以算作模块接口的一部分。接口的非正式信息只能通过注释等方式描述,程序语言无法确保描述是完整而准确的。大部分接口的非正式信息都比正式信息要更多、更复杂。

清晰的接口定义有助于开发者了解在使用模块时需要知道的信息,从而避免一些问题。

3,抽象

 抽象这一术语和模块设计思想的关系很近。抽象是实体的简化视图,省略了不重要的细节。抽象很有用,它可以使我们对细节的思考和操纵变简单。

在模块化编程中,每个模块通过接口提供其抽象。抽象代表了函数功能的简化视图。在函数抽象的立场上,实现的细节是不重要的,所以它们被省略了。

“不重要”这个词很关键。如果没有忽略掉不重要的细节,那么抽象会变得复杂,会增加开发者的认知负担;如果忽略掉了重要的细节,那么抽象会变得错误,失去对实践的指导意义。设计抽象的关键是理解什么是重要的,并寻找最小化重要信息的设计。

依赖抽象来管理复杂度不是编程的专利,它遍布在我们的日常生活中。就像车子会提供一个简单抽象来让我们驾驶,并不需要我们理解发动机、电池、ABS之类的东西。

4,深模块

最好的模块提供了强大的功能,又有着简单的接口。术语“”可以用于描述这种模块。为了让深度的概念可视化,试想每个模块由一个长方形表示,如下图,

长方形的面积大小和模块实现的功能多少成比例。顶部边代表模块的接口,边的长度代表它的复杂度。最好的模块是深的:他们有很多功能隐藏在简单的接口后。深模块是好的抽象,因为它只把自己内部的一小部分复杂度暴露给了用户。

浅模块的接口复杂,功能却少,它没有隐藏足够的复杂度。

可以从成本与收益的角度思考模块深度。模块提供的收益是它的功能。模块的成本(从系统复杂度的角度考虑)是它的接口。接口代表了模块施加给系统其余部分的复杂度。接口越小而简单,它引入的复杂度就越少。好的模块就是那些成本低收益高的模块

某些语言中的垃圾回收(GC)是深模块的例子之一。这个模块没有接口,它在需要回收无用内存的场景下不可见地工作。在系统中加入垃圾回收的做法,缩小了系统的总接口,因为这种做法消除了用于释放对象的接口。垃圾回收的具体实现是相当复杂的,但这一复杂度在实际使用程序语言的时候是隐藏的。

5,浅模块

相对的,浅模块就是接口相对功能而言很复杂的模块。下面是个可能有些极端的例子,

private void addNullValueForAttribute(String attribute) {
  data.put(attribute, null);
}

从复杂度管理的角度来看,该方法把事情变糟了。它没有提供抽象,因为所有的功能都是在接口上可见的。思考这一接口并不会比思考它的完整实现更简单。如果方法有合适的文档,文档也不会比方法的代码具有更多信息。相比于直接操作data,它的长名字甚至会导致开发者敲击键盘的次数变多。这种方法增加了复杂度(引入了一个需要开发者了解的新接口),但并没有提供与之相应的收益。注意:小的模块会更倾向于变浅。

6,Classitis

当今,深模块的价值并没有被广为接受。一般常识是类需要小,而不是深。学生们被告知:类设计中最重要的事情是把大类拆分成更小的类。相似的建议还包括:“要把方法行数大于N的方法分成多个方法”,有时候N甚至只有10这么小。这会导致大量的浅模块,增加系统的总复杂度。

极端的“类应该小”的做法是一种综合症的表现,这种症状可以被称为Classitis。它源于一种错误思维:“类是好的,所以越多类越好”。这种思想最终会导致系统层面积累了巨大的复杂度,程序风格也会变得啰嗦。

7,例子

Java类库可能是Classitis的最明显例子之一。Java语言本身不需要很多小类,但Classitis文化可能已经在Java语言社区扎了根。比如,为了打开文件读取其中的序列化对象,你必须创建多种对象:

FileInputStream fileStream =
    new FileInputStream(fileName);
BufferedInputStream bufferedStream =
    new BufferedInputStream(fileStream);
ObjectInputStream objectStream =
    new ObjectInputStream(bufferedStream);

FileInputStream对象只提供初步的I/O,它不具备缓存I/O的能力,也不能读写序列化对象。BufferedInputStream和ObjectInputStream分别提供了后面两项功能。文件打开之后,fileStream和bufferedStream就没用了,未来的操作只会用到objectStream.。

必须显式单独创建BufferedInputStream对象来请求缓存,这很烦人而且易出错。如果开发者忘记创建它,就不会有缓存,而且I/O会慢。大概Java开发者会辩解说,不是所有人都需要缓存,所以它不应该包含在基本读写机制中。他们也许会说让缓存独立更好,借此用户可以选择是否使用它。提供选择空间当然很好,但接口需要设计为对常用场景尽可能简单,几乎所有文件I/O用户都想使用缓存,所以就应该默认提供它。对于少数不需要的情况,库可以提供机制以禁用。禁用缓存的机制应该明确地在接口中分离(例如,为FileInputStream提供不同的构造器,或者通过一个方法禁用/替换缓存机制),这样大部分开发者甚至不需要意识到它的存在。

8,结论

通过将模块的接口和实现分离,我们可以对系统的其它部分隐藏实现的复杂度。模块的使用者只需要理解接口提供的抽象。在设计类和其它模块时,最重要的问题是让它们深,它们要对常见用例有足够简单的接口,但同时依然提供强大的功能。这就最大化地隐藏了复杂度。

以上就是Deep Module深模块之软件设计的详细内容,更多关于Deep Module深模块的资料请关注编程网其它相关文章!

--结束END--

本文标题: DeepModule深模块之软件设计

本文链接: https://www.lsjlt.com/news/154082.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • DeepModule深模块之软件设计
    目录正文1,模块化设计2,接口里有什么3,抽象4,深模块5,浅模块6,Classitis7,例子8,结论正文 类是不是越小越好?最近在读John Ousterhout的《A Phil...
    99+
    2024-04-02
  • Deep Module深模块之软件设计实例分析
    今天小编给大家分享一下Deep Module深模块之软件设计实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。...
    99+
    2023-07-02
  • Java设计模式之单件模式深入讲解
    目录定义Java单件模式经典单件模式的实现多线程单件模式的实现急切创建实例双重检查加锁Python单件模式模块实现new关键字实现装饰器实现函数装饰器类装饰器定义 单件模式确保一个类...
    99+
    2024-04-02
  • 软件工程(十三) 设计模式之结构型设计模式(一)
    前面我们记录了创建型设计模式,知道了通过各种模式去创建和管理我们的对象。但是除了对象的创建,我们还有一些结构型的模式。 1、适配器模式(Adapter) 简要说明 将一个类的接口转换为用户希望得到的另一个接口。它使原本不相同的接口得以协同工...
    99+
    2023-08-30
    软件工程 设计模式 java
  • 软件开发基础之设计模式概述
    成为一名优秀的软件开发工程师,设计模式的重要性不言而喻,本章节是对设计模式的前置知识概述,涉及概念性较大,读者可在设计模式学习过程中参阅本文档。 在第一章节,主要介绍软件设计的七大原...
    99+
    2024-04-02
  • 揭秘 ES6 模块:深入探索模块化设计的魅力
    ES6 模块的优势 ES6 模块提供了以下优势,使其成为构建现代 JavaScript 应用程序的必要工具: 代码重用: 模块化设计允许将代码组织成可重用的块,从而减少代码重复。 可维护性: 模块可以独立维护,使修复、更新和扩展代码更...
    99+
    2024-03-02
    ES6 模块 模块化设计 代码重用 可维护性 可扩展性
  • 软件工程(十四) 设计模式之结构型模式(二)
    1、组合模式 简要说明 将对象组合成树形结构以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。 速记关键字 树形目录结构 类图如下 由类图其实可以看出,组合模式就是将具有父子关系的结构,组装形成一棵树,并且根据...
    99+
    2023-08-30
    软件工程 设计模式
  • 软件设计中模块划分应遵循的准则有哪些
    这篇文章给大家分享的是有关软件设计中模块划分应遵循的准则有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。软件设计中模块划分应遵循的准则是高内聚低耦合。软件设计是从软件需求规格说明书出发,根据需求分析阶段确定的...
    99+
    2023-06-14
  • Java设计模式之单例模式深入探索
    目录什么是设计模式?单例模式是什么?单例模式设计的原则是什么?Java实现单例模式的5种方式?懒汉饿汉静态内部类双重校验锁DCL(Double Check Lock)枚举(num)小...
    99+
    2024-04-02
  • Java设计模式之组合模式深入刨析
    目录1.基本介绍2.结构3.组合模式解决的问题4.组合模式解决学校院系展示5.组合模式的注意事项和细节1.基本介绍 1)组合模式(Composite Pattern),又叫部分整体模...
    99+
    2024-04-02
  • Java设计模式之策略模式深入刨析
    目录1.基本介绍2.传统方式3.采用策略模式4.策略模式的注意事项和细节1.基本介绍 1)策略模式(Strategy Pattern)中,定义算法族(策略组),分别封装起来,让他们之...
    99+
    2024-04-02
  • 深入了解Java设计模式之策略模式
    目录定义解决的问题核心要点类图溢出效用代码实现核心接口实现类-三个Context类Main方法拓展JDK源码Spring源码定义 定义了算法家族,分别封装起来,让他们之间可以相互替换...
    99+
    2024-04-02
  • 深入理解Java设计模式之状态模式
    目录一、什么是状态模式二、状态模式的结构三、状态模式的使用场景四、状态模式和策略模式对比五、状态模式的优缺点六、状态模式的实现七、总结一、什么是状态模式 定义:当一个对象的内在状态改...
    99+
    2024-04-02
  • 深入理解Java设计模式之命令模式
    目录一、什么是命令模式二、命令模式的使用场景三、命令模式的优缺点四、命令模式的实现五、总结一、什么是命令模式 命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你...
    99+
    2024-04-02
  • 深入理解Java设计模式之原型模式
    目录一、前言二、什么是原型模式三、原型模式的适用场景四、原型模式的实现1.浅拷贝实现2.深拷贝实现五、总结一、前言 单例模式可以避免重复创建消耗资源的对象,但是却不得不共用对象。若是...
    99+
    2024-04-02
  • 深入理解Java设计模式之策略模式
    目录一、什么是策略模式二、策略模式的结构三、策略模式的应用场景四、策略模式的优缺点六、策略模式的实现七、策略模式和简单工厂模式的结合八、策略枚举的实现九、总结一、什么是策略模式 策略...
    99+
    2024-04-02
  • 深入理解Java设计模式之单例模式
    目录一、什么是单例模式二、单例模式的应用场景三、单例模式的优缺点四、单例模式的实现1.饿汉式2.懒汉式3.双重加锁机制4.静态初始化五、总结一、什么是单例模式 单例模式是一种常用的软...
    99+
    2024-04-02
  • 深入理解Java设计模式之装饰模式
    目录一、前言二、什么是装饰模式1.定义:2.意图3.别名4.动机5.作用6.问题三、装饰模式的结构四、装饰模式的使用场景五、装饰模式的优缺点六、装饰模式的实现七、装饰模式的.NET应...
    99+
    2024-04-02
  • 深入理解Java设计模式之桥接模式
    目录二、桥接模式的结构三、桥接模式的使用场景四、桥接模式的优缺点五、装饰,桥接和适配器模式的异同适配器模式:桥接模式:装饰器模式:六、桥接模式的实现七、总结一、什么是桥接模式 桥接模...
    99+
    2024-04-02
  • 深入理解Java设计模式之组合模式
    目录一、什么是组合模式动机(Motivation)意图(Intent)二、组合模式的结构结构图说明:三、组合模式的使用场景四、组合模式的优缺点五、组合模式的实现六、组合模式的.NET...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作