当前位置: 首页 > news >正文

设计心得——分层和划分模块

一、分层

在实际的设计开发过程中,对于稍微大一些的项目,基本都涉及到分层。什么是分层呢?其实非常简单,就是利用某种逻辑或域的范围等把整个项目划分成多个层次。它们之间通过接口(可能是简单的函数接口也可以是服务等)进行通信。分层地目的其实非常明显,就是为了整个设计的解耦和重用,使得整个项目结构更清晰和控制更合理,也便 于后期的维护和扩展。
一般来说,分层是在更高层次上进行抽象,它属于对整个项目的横向切分。分层的优点非常多,比如高内聚、低耦合以及便于维护和接口扩展,提供了更好的技术更新接口等等。但在明白其的优势之后,更要明白它的劣势所在:
1、降低性能
增加层次的最主要的问题就是导致一定的性能损失。毕竟大家都明白,直接调用比通过接口处理一下,理论上一定是要快的。特别是在通信量巨大并且并发较高的情况下,其性能的损失会非常的明显。
2、增加复杂性
分层设计需要进行良好的层间接口设计,否则极有可能导致因为接口的问题导致层间的通信问题,比如对于一个任务是需要调用一个接口完成(单一原则)还是一个以上接口(效率)实现呢?这就需要设计者不断的根据实际情况进行调整。
3、工程化的风险
设计者们往往有一个爱好,一旦觉得某项技术不错,便会不断的在这个基础上进行强化,也就是过度设计。体现在分层上就是更乐意通过分层来解决很多问题。虽然分层在很多情况下可以将问题简化,但过多的引入分层等于变相的增加了另外一种复杂性。也就是说,设计者一定要明白,分层的适度性和科学性。而且过多的分层往往导致测试的复杂性和增加测试的难度。

虽然明白了分层的优势,但说起分层来大家可能有点熟悉又陌生的感觉,其实举一个常见的MVC的例子大家就明白了,它其实就是把整个程序分成了三层,上层的表示层用来处理接收的输入数据和处理后返回的数据;中间的控制层用来进行上下的交互数据管理;而最下面的模型层则进行数据的最终存储逻辑控制。
通过MVC明白了这种分层的设计的具像化,那么其它也就好理解了,比如常见的另外一种分层,网络分层,TCP/IP的分层等等。某些情况下,分层类似于见到的过滤器,一层层的过滤掉不同的物质(或者说一层只处理一个或几个业务)。这样,大家应该就对分层有了一个很显性的认识。
但需要注意的是,软件设计的分层往往从不同的角度看有不同的理解,大家不要教条和僵化,慢慢思考、理解和学习即可。

二、模块化

说了分层,再说设计高频遇到的名词,模块。其实模块这个概念就是一组功能相近的软件代码或组件。这里面水儿深着哪。首先,什么是一组,另外什么是功能相近?什么是代码或组件?这个其实没有强制的定义。给大家举个例子,一个函数就有可能是一个模块,而一个类也可能是一个模块,一个文档可能也是。一个软件可能也是…凡此种种。而模块化就是以模块为基础的设计方式。
模块会根据场景不一致而呈现中不同的情况。而上面所提到的功能相近等其实也可以站不同的角度和层次上来看。再举一个例子,一个大型的变电站运行软件,可能分成服务端软件,客户端软件,移动端软件和设备端软件等等。那么从这个角度来看,它们每个都算是一个独立的模块。一般来说,模块属于是在纵向上的划分,即更强功能的组合。
需要提醒的是,不要混淆模块的一些概念,比如在不少的程序语言中,都有模块这个概念。它们和设计中提到的模块基本类似,但也有着一些显著的不同。切记。
模块化设计的优点很多,和分层差不多,毕竟二者都是朝着同一个目的而来的。
模块化设计的主要优点包括:高内聚,低耦合,接口清晰,易维护,方便代码重用及团队协作。但它的缺点也不少:
1、模块化设计增加了设计的难度
不是每个设计者都能很好的把握模块的设计,这就可能导致模块设计的不合理性,进而导致各种问题。
2、降低效率
和分层一样,通过接口调用的模块,理论上会降低整体的效率
3、工程上的过度设计
一如分层,模块的过度设计,同样会导致整个软件的难于控制,过多的模块往往使得业务的碎片化;而过少的模块除了引入了一些复杂性,几乎没有体现出模块的优势。
4、模块的维护
设计完成的模块,需要从开始到结束都一套完善的管理流程,包括文档、工具等。如果开发者们没有按照设计要求进行,则可能导致引入不少的风险。最简单的例子就是不同的模块间,使用了不同的技术标准实现或者引入不相同功能的不同版本的库。都可能导致问题的出现,而且极有可能很难发现问题的原因。
但正如成语说得好,不能“因噎废食”。设计就是一种取舍和妥协!

三、二者关系

在分析了上述的分层和模块后,不少的新手可能会有一个疑问,怎么看待二者的设计上的抽象的不同呢?一般情况下,分层的抽象是高于模块的抽象的,但具体情况上则有可能有所不同 。比如在上面提到的变电站软件中,每个模块中,可能又会划分成不同的层次。这样看来,模块包含着分层。也就是说,实际应用中,分层和模块间没有明确的界限,二者可以互相包容。
其实,稍微大一些软件的设计,一般来说是分层优先,然后进行模块划分。经常可以看到系统的整体设计架构图,就是这样的。但凡是都有例外,分层和模块二者之间其实是一个互相补充互相协作上的抽象关系。从整体抽象看,分层是较大粒度的划分而模块则是较小粒度的划分。也即上面提到的分层是基于横向的水平划分而模块是基于纵向的垂直划分。
一般的情况下,分好的层次中,每层都包含若干个模块。模块间以接口通信,整合后通过层间的接口再与其它层进行通信。层次之间的数据依赖单向为主,但模块间的依赖则灵活很多。

四、二者的应用

分层和模块化的应用场景在不少的场景下是重叠的,但整体上来看,还是可以进行区别划分的。
1、分层的应用
a) 大规模的应用,特别是企业级的应用。包括框架、库和系统等
b) 分布式应用,为更好的协调分布式各个节点间的通信,分层是一个非常好的设计思路
c) Web应用,这个更容易理解,常见的MVC设计在Web服务中体现的最明显
d) 复杂应用,对业务或逻辑处理深度较大,恰恰是分层设计的良好应用场景
e) 其它一些特殊场景

2、模块化的应用
模块化设计几乎是所有的程序设计都离不开的。除非程序很小或者说一些例程,正常情况下,一个软件都要进行模块化的设计。

五、总结

设计一个从抽象到具体,从整体到细节,不断具体而微的过程。俗话说得好“教的曲儿唱不得”。设计不像技巧,多问两下多看两下代码就会用了。所以设计中的一些具体的手段和方法,要不断的从不同的角度不同的场景进行分析学习,并不断在实践中进行检验。反思得失,总结教训,形成自己的一套解决问题、处理问题的逻辑和流程。最终升华为自己的设计思想。
这一定是一个长期的,不断的否定之否定的过程!愿与诸君共勉!

相关文章:

设计心得——分层和划分模块

一、分层 在实际的设计开发过程中,对于稍微大一些的项目,基本都涉及到分层。什么是分层呢?其实非常简单,就是利用某种逻辑或域的范围等把整个项目划分成多个层次。它们之间通过接口(可能是简单的函数接口也可以是服务…...

uniapp使用蓝牙,usb,局域网,打印机打印

使用流程(支持安卓和iOS) 引入SDK 引入原生插件包地址如下 https://github.com/oldfive20250214/UniPrinterDemo 连接设备 安卓支持经典蓝牙、ble蓝牙、usb、局域网(参考API) iOS支持ble蓝牙、局域网(参考API&…...

PQL查询和监控各类中间件

1 prometheus的PQL查询 1.1 Metrics数据介绍 prometheus监控中采集过来的数据统一称为Metrics数据,其并不是代表具体的数据格式,而是一种统计度量计算单位当需要为某个系统或者某个服务做监控时,就需要使用到 metrics prometheus支持的met…...

day1 redis登入指令

[rootlocalhost data]# redis-cli -h ip -p 6379 -a q123q123 Warning: Using a password with -a or -u option on the command line interface may not be safe. ip:6379> 以上, Bigder...

2025 年 AI 网络安全预测

🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 微软和 OpenAI 宣布延长战略合作伙伴关系,加强对推进人工智能技术的承诺,这表明强大的 AI 将在未来占据主导地位。 随着人工智能 &#x…...

[Windows] 多系统键鼠共享工具 轻松跨系统控制多台电脑

参考原文:[Windows] 多系统键鼠共享工具 轻松跨系统控制多台电脑 还在为多台电脑需要多套键盘鼠标而烦恼吗?是不是在操控 Windows、macOS、Linux 不同系统电脑时手忙脚乱?现在,这些问题通通能解决!Deskflow 软件闪亮登…...

单片机的发展

一、引言 单片机自诞生以来,经历了四十多年的风风雨雨,从最初的工业控制逐步扩展到家电、通信、智能家居等各个领域。其发展过程就像是一场精彩的冒险,每一次技术的革新都像是在未知的海域中开辟新的航线。 二、单片机的发展历程 &#xff…...

Spring 构造器注入和setter注入的比较

一、比较说明 在 Spring 框架中,构造器注入(Constructor Injection)和 Setter 注入(Setter Injection)是实现依赖注入(DI)的两种主要方式。它们的核心区别在于依赖注入的时机、代码设计理念以及…...

uploadlabs通关思路

目录 靶场准备 复现 pass-01 代码审计 执行逻辑 文件上传 方法一:直接修改或删除js脚本 方法二:修改文件后缀 pass-02 代码审计 文件上传 1. 思路 2. 实操 pass-03 代码审计 过程: 文件上传 pass-04 代码审计 文件上传 p…...

迷你世界脚本自定义UI接口:Customui

自定义UI接口:Customui 彼得兔 更新时间: 2024-11-07 15:12:42 具体函数名及描述如下:(除前两个,其余的目前只能在UI编辑器内部的脚本使用) 序号 函数名 函数描述 1 openUIView(...) 打开一个UI界面(注意…...

【情境领导者】评估情境——准备度水平

本系列是看了《情境领导者》一书,结合自己工作的实践经验所做的学习笔记。 在文章【情境领导者】评估情境——什么是准备度-CSDN博客我们提到准备度是由能力和意愿两部分组成的。 准备度水平 而我们要怎么去评估准备度呢?准备度水平是指人们在每项工作中…...

2025 ubuntu24.04系统安装docker

1.查看ubuntu版本(Ubuntu 24.04 LTS) rootmaster:~# cat /etc/os-release PRETTY_NAME"Ubuntu 24.04 LTS" NAME"Ubuntu" VERSION_ID"24.04" VERSION"24.04 LTS (Noble Numbat)" VERSION_CODENAMEnoble IDubun…...

Android中AIDL和HIDL的区别

在Android中,AIDL(Android Interface Definition Language) 和 HIDL(HAL Interface Definition Language) 是两种用于定义跨进程通信接口的语言。AIDL 是 Android 系统最早支持的 IPC(进程间通信&#xff0…...

通过数据库网格架构构建现代分布式数据系统

在当今微服务驱动的世界中,企业在跨分布式系统管理数据方面面临着越来越多的挑战。数据库网格架构已成为应对这些挑战的强大解决方案,它提供了一种与现代应用架构相匹配的分散式数据管理方法。本文将探讨数据库网格架构的工作原理,以及如何使…...

Python基于Django的医用耗材网上申领系统【附源码、文档说明】

博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…...

Python爬虫实战:一键采集电商数据,掌握市场动态!

电商数据分析是个香饽饽,可市面上的数据采集工具要不贵得吓人,要不就是各种广告弹窗。干脆自己动手写个爬虫,想抓啥抓啥,还能学点技术。今天咱聊聊怎么用Python写个简单的电商数据爬虫。 打好基础:搞定请求头 别看爬虫…...

STM32之I2C硬件外设

注意:硬件I2C的引脚是固定的 SDA和SCL都是复用到外部引脚。 SDA发送时数据寄存器的数据在数据移位寄存器空闲的状态下进入数据移位寄存器,此时会置状态寄存器的TXE为1,表示发送寄存器为空,然后往数据控制寄存器中一位一位的移送数…...

【C++】中的赋值初始化和直接初始化的区别

在C中,赋值初始化(也称为拷贝初始化)和直接初始化(也称为构造初始化)虽然常常产生相同的结果,但在某些情况下它们有不同的含义和行为。 赋值初始化(Copy Initialization) 使用等号…...

Python ❀ Unix时间戳转日期或日期转时间戳工具分享

设计一款Unix时间戳和日期转换工具,其代码如下: from datetime import datetimeclass Change_Date_Time(object):def __init__(self, date_strNone, date_numNone):self.date_str date_strself.date_num date_num# 转时间戳def datetime2timestamp(s…...

本地部署Dify及避坑指南

Dify作为开源的大模型应用开发平台,支持本地私有化部署,既能保障数据安全,又能实现灵活定制。但对于新手而言,从环境配置到服务启动可能面临诸多挑战。本文结合实战经验,手把手教你从零部署Dify,并总结高频…...

大白话CSS 优先级计算规则的详细推导与示例

大白话CSS 优先级计算规则的详细推导与示例 答题思路 引入概念:先通俗地解释什么是 CSS 优先级,让读者明白为什么要有优先级规则,即当多个 CSS 样式规则作用于同一个元素时,需要确定哪个规则起作用。介绍优先级的分类&#xff1…...

OpenCV计算摄影学(19)非真实感渲染(Non-Photorealistic Rendering, NPR)

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 非真实感渲染(Non-Photorealistic Rendering, NPR)是一种计算机图形学技术,旨在生成具有艺术风格或其他非现实…...

深度学习(斋藤)学习笔记(五)-反向传播2

上一篇关于反向传播的代码仅支持单变量的梯度计算,下面我们将扩展代码使其支持多个输入/输出。增加了对多输入函数(如 Add),以实现的计算。 1.关于前向传播可变长参数的改进-修改Function类 修改方法: Function用于对…...

数据库基础练习1

目录 1.创建数据库和表 2.插入数据 创建一个数据库,在数据库种创建一张叫heros的表,在表中插入几个四大名著的角色: 1.创建数据库和表 #创建表 CREATE DATABASE db_test;#查看创建的数据库 show databases; #使用db_test数据库 USE db_te…...

TypeError: Cannot create property ‘xxx‘ on string ‘xxx‘

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…...

极狐GitLab 17.9 正式发布,40+ DevSecOps 重点功能解读【三】

GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料: 极狐GitLab 官网极狐…...

lsblk命令linux查询设备信息

lsblk命令是Linux中用于列出所有可用块设备信息的工具,它能够显示设备之间的依赖关系,但不会列出RAM盘的信息。块设备包括硬盘、闪存盘、CD-ROM等。lsblk命令包含在util-linux包中,该命令的常用参数包括: -d:仅列出磁盘…...

【智能体架构:Agent】LangChain智能体类型ReAct、Self-ASK的区别

1. 什么是智能体 将大语言模型作为一个推理引擎。给定一个任务, 智能体自动生成完成任务所需步骤, 执行相应动作(例如选择并调用工具), 直到任务完成。 2. 先定义工具:Tools 可以是一个函数或三方 API也…...

鸿蒙开发:弹性布局Flex

前言 代码案例基于Api13。 正在开发一个搜索组件,其中一个功能是针对历史搜索的内容进行展示,由于搜索的内容长度不一,需要进行流式布局展示,效果如下: 以上的效果,相信大家在很多的应用里或多或少都见到过…...

【DeepSeek】5分钟快速实现本地化部署教程

一、快捷部署 (1)下载ds大模型安装助手,下载后直接点击快速安装即可。 https://file-cdn-deepseek.fanqiesoft.cn/deepseek/deepseek_28348_st.exe (2)打开软件,点击立即激活 (3)选…...