当前位置: 首页 > 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,并总结高频…...

【JavaEE】-- HTTP

1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...

LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》

&#x1f9e0; LangChain 中 TextSplitter 的使用详解&#xff1a;从基础到进阶&#xff08;附代码&#xff09; 一、前言 在处理大规模文本数据时&#xff0c;特别是在构建知识库或进行大模型训练与推理时&#xff0c;文本切分&#xff08;Text Splitting&#xff09; 是一个…...

Matlab实现任意伪彩色图像可视化显示

Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中&#xff0c;如何展示好看的实验结果图像非常重要&#xff01;&#xff01;&#xff01; 1、灰度原始图像 灰度图像每个像素点只有一个数值&#xff0c;代表该点的​​亮度&#xff08;或…...