架构设计系列之基础:基础理论(一)

在软件开发和软件架构领域,深厚的理论基础是构建高质量、可维护、可扩展系统的关键,本部分内容将围绕这些基础理论展开。(本部分内容介绍第一部分:编程三范式、架构设计原则、软件设计七原则)

一、编程三范式

编程范式是程序设计的基本思想和方法,对于程序员来说,他是告诉我们在实际编码和设计的过程中不能做什么,而非可以做什么。了解和灵活运用编程范式,有助于构建更加清晰、灵活、可维护的代码。

1 、结构化编程(Structured programming)

是基于过程的一种编程范式,将问题分解为一系列的步骤,每个步骤都由一个过程或函数表示。强调程序的执行过程,是用于简单的任务和流程。

结构化编程是对程序控制权的直接转移进行了限制和规范。

优势
  • 直观且易于理解和实现
  • 适用于线性、简单的任务
适用场景
  • 独立脚本编写
  • 简单的操作和流程

2、面向对象编程(Object-oriented programming)

是一种以对象为基础的编程范式,将数据和操作封装在对象中,强调对象之间的交互和关系。

核心思想是通过抽象、继承、封装和多态等概念,提高代码的重用性和可维护性。

面向对象编程是对程序控制权的间接转移进行了限制和规范。

优势
  • 模块化,提高代码的可维护性
  • 重用性高,减少重复代码
适用场景
  • 复杂系统设计
  • 大规模团队协作

3、函数式编程(Funtional programming)

是一种以函数为基础的编程范式,将计算视为数据函数的求值过程。强调纯函数、不可变性和无副作用,通过组合函数来构建复杂的系统。

函数式编程是对程序中的赋值进行了限制和规范。

优势
  • 副作用少,易于调试和测试
  • 并行计算友好
适用场景
  • 数据处理和转换
  • 并行和分布式系统

了解并灵活运用这三个范式,有助于根据问题的性质选择最合适的编程方式,提高代码的质量和可维护性。在实际项目中,通常会综合运用多种范式,以充分发挥他们的优势。

4、编程范式与架构设计的关系

编程范式和架构设计是有着密切关系的:

  • 结构化编程是在做各个模块设计和实现时的基础要求
  • 面向对象编程中比如多态是跨越架构边界的手段
  • 函数式编程是用来规范和限制数据存放位置与访问权限的手段

基于上面的分析,你会发现,这三点和架构设计中的功能性、组件独立性、数据管理是密切相关的。

二、架构设计原则

1 、 合适原则

架构设计应该全面考虑时间、人力、能力、效率、成本,选择当前最为合适的方案。

合适的方案并非简单化,而是在充分考虑投资回报率(ROI)的基础上,根据项目需求和实际情况进行权衡和决策。

在实现功能的前提下,追求高效率和降低成本是合适方案的关键。

2 、简单原则

简单原则强调在满足功能需求的前提下,追求简洁和可读性。

简单设计有助于提高研发效率、降低成本、减少错误率,并能够提高系统的可维护性和可扩展性。

核心思想是简单优于复杂。在实现功能的前提下,减少代码量和复杂性,避免过度设计带来的复杂度。

简单的设计更容易理解、测试和部署,同时也易于维护和扩展,减少未来的开发难度和成本。

3 、演化原则

演化原则是指导设计出能够适应未来变化的重要原则,要求技术人员具备前瞻性。

架构设计应该具备灵活性和可扩展性,以便在未来的开发过程中能轻松应对新功能的研发、适应新的需求和变化。

核心思想是演化强于一步到位。任何一个软件产品和系统都需要不断变化和演进,因此在设计过程中要避免过于复杂、难以维护和扩展的结构。

持续的演化有助于保持系统的健康状态,适应业务和技术的不断发展。

三、软件设计七原则

做好一个系统,要先从写出整洁和易维护的代码开始。如果代码质量不佳,那架构能起到的作用就不会太大,多好的架构也绷不住堆砌的烂代码。反之,如果架构设计的不太理想,代码写的再好其实也无太大用处。两者之间是相辅相成,互相成就的。

1 、SRP(Single responsibility Principle)单一职责原则

SRP 是一项简单易懂且重要的原则,但是在实际过程中往往最容易忽略的,它强调在应用中,一个类应该只有一个引起变化的原因,只有一个职责。

SRP 是基于康威定律的推导结论:软件系统的最佳结构高度依赖于开发这个系统的组织的内部结构,每个软件模块都有且只有一个需要被改变的理由。

优点
  • 降低类之间的耦合:将不同职责分解为不同的类,降低类之间的依赖关系,提高系统的灵活性和可维护性
  • 提升类的可维护性和可重用性:当一个类只有一个职责时,修改该职责不会影响到其他职责,使得类更加稳定,易于维护和重用
  • 简化设计过程:SRP 原则使得类的设计更加清晰,每个类都专注于解决一个问题,降低了设计的复杂性
示例代码

多职责的类设计

public class UserService {/*** 运营部员工绩效计算 */public BigDecimal calculateKPIResultForOperation() { }/*** 商务员工绩效计算 */public BigDecimal calculateKPIResultForBusiness() { }/*** 产品部员工绩效计算 */public BigDecimal calculateKPIResultForProduct() { }/*** 技术部员工绩效计算 */public BigDecimal calculateKPIResultForTechnology() { }
}

SRP 后的类设计

public interface UserService {public BigDecimal calculateKPIResult();
}// 不同部门实现接口
public class OperationUserService implement UserService {}
public class BusinessUserService implement UserService {}
public class ProductUserService implement UserService {}
public class TechnologyUserService implement UserService {}
注意点
  • 拆分多职责类:如果一个类承担了多个职责,就一定要拆分为多个类,确保每个类只有一个职责
  • 识别变化原因:识别引起类变化的原因,然后职责分配到对应的类,确保每个类的变化原因是明确的
  • 避免过度设计:尽可能简单,避免过度设计和复杂性,SRP 的目标是简化设计,而不是增加不必要的结构

2 、OCP(Open/Close Principle) 开闭原则

OCP 的核心思想是通过扩展已有的代码,增加新的行为和功能,而不是修改已有的代码。

优点
  • 提高代码的可维护性和可重用性:允许系统通过扩展已有的代码来应对新的需求,而不是修改已有的代码,降低引入错误的风险
  • 减少代码的耦合度:模块化的设计使得系统个部分之间的耦合度降低,一个模块的修改不会对其他模块产生影响
  • 提高系统的可扩展性和可升级性:新功能可以通过添加新的类或模块来实现,而不是修改已有的代码,使得系统更容易扩展和升级
示例代码

无 OCP 的代码

public class Calculator {  public int add(int a, int b) {  return a + b;  }  public int subtract(int a, int b) {  return a - b;  }  public int multiply(int a, int b) {  return a * b;  }  public int divide(int a, int b) {  return a / b;  }  
}

有 OCP 的代码

public interface Operation {  int calculate(int a, int b);  
}  public class AddOperation implements Operation {  public int calculate(int a, int b) {  return a + b;  }  
}  public class SubtractOperation implements Operation {  public int calculate(int a, int b) {  return a - b;  }  
}  public class MultiplyOperation implements Operation {  public int calculate(int a, int b) {  return a * b;  }  
}  public class DivideOperation implements Operation {  public int calculate(int a, int b) {  return a / b;  }  
}
注意点
  • 使用 OCP 原则:把实体设计成可扩展,通过新加类、模块或者函数来扩展功能和行为
  • 抽象化已有代码:对已有代码进行抽象,将具体的实现细节封装,对外仅提供抽象的接口
  • 避免过度设计:OCP 原则的目标是简化设计而不是增加不必要的结构

3 、LSP(Liskov Substitution Principle)里氏替换原则

LSP 强调在软件中,子类必须能够替换其父类,即子类应该具有与父类相同的行为和功能,而不仅仅是继承父类的属性和方法。

优点
  • 提高代码的可读性和可维护性:子类与父类具有一致的行为和功能,使得代码更易于理解和维护
  • 减少代码的冗余和复杂性:子类继承父类的方法和属性,可以避免重复编写相似的代码
  • 提高系统的可扩展性和可升级性:新的子类可以无缝地替换父类,不会影响系统的其他部分
示例代码

无 LSP 代码

class Shape {  void draw() {  System.out.println("Drawing a shape");  }  
}  class Circle extends Shape {  void draw() {  System.out.println("Drawing a circle");  }  
}

有 LSP 代码

interface Drawable {  void draw();  
}  class Shape implements Drawable {  public void draw() {  System.out.println( "Drawing a shape");  }  
}  class Circle extends Shape {  public void draw() {  System.out.println("Drawing a circle");  }  
} 
注意点
  • 子类具有一致的行为和功能:子类必须具有与父类相同的行为和功能,但不能改变父类的行为和功能
  • 抽象类定义抽象方法:抽象类应该定义抽象方法,具体方法在子类中实现
  • 避免继承滥用:避免使用继承来共享行为,继承是用来实现多态行为的,而不是为了代码的重用。如果子类需要不同的功能和行为,那应该通过重写父类方法来实现

4 、ISP(Interface Segregation Principle)接口隔离原则

ISP 强调在应用中使用多个特定的接口,而不是一个单一的总接口,从而避免端侧就不需要被强制依赖他们不需要的接口。

优点
  • 提高代码的可维护性和可重用性,特定接口提供特定服务,代码可以更加模块化和可定制化
  • 减少端侧的复杂性,端侧只需要依赖实际使用的接口,避免对不相关接口的强制依赖
  • 提高系统的可扩展性和可升级性,新的接口可以被添加而不会影响实际使用的接口,使得系统更容易扩展和升级
示例代码

无 ISP 代码

interface ShoppingCart {  void addItem(Product product, int quantity);  void removeItem(Product product);  void updateQuantity(Product product, int quantity);  
}  class ShoppingCartImpl implements ShoppingCart {  private Map<Product, Integer> items = new HashMap<>();  @Override  public void addItem(Product product, int quantity) {  items.put(product, quantity);  }  @Override  public void removeItem(Product product) {  items.remove(product);  }  @Override  public void updateQuantity(Product product, int quantity) {  int currentQuantity = items.get(product);  items.put(product, currentQuantity + quantity);  }  
}

有 ISP 代码

interface AddToCart {  void addItem(Product product, int quantity);  
}  interface RemoveFromCart {  void removeItem(Product product);  
}  interface UpdateQuantity {  void updateQuantity(Product product, int quantity);  
}  class ShoppingCartImpl implements AddToCart, RemoveFromCart, UpdateQuantity {  private Map<Product, Integer> items = new HashMap<>();  @Override  public void addItem(Product product, int quantity) {  items.put(product, quantity);  }  @Override  public void removeItem(Product product) {  items.remove(product);  }  @Override  public void updateQuantity(Product product, int quantity) {  int currentQuantity = items.get(product);  items.put(product, currentQuantity + quantity);  }  
}
注意点
  • 接口定义尽可能小:每个接口提供有限的服务,方法尽可能少,不要妄想一个接口走遍天下
  • 分离不相关功能:如果接口中提供的功能不相关,需要将接口进行分离操作,形成独立接口,代码可更模块化和可定制化
  • 避免使用过大的总接口:总接口应该根据需要提供适当的功能,而不是一刀切提供所有功能

5 、DIP(Dependency Inversion Principle)依赖倒置原则

DIP 强调在应用中,高层模块不应该依赖于底层模块,它们应该依赖于抽象。

优点
  • 提高代码的可读性和可维护性:高层模块依赖于抽象,而不是具体实现,使得代码更灵活和易于理解
  • 降低类之间的耦合度:依赖抽象不依赖具体实现,减少了高层模块和底层模块之间的直接依赖,提高了系统的灵活性
  • 提高系统的可扩展性和可升级性:新的实现可以通过实现抽象来引入,不需要修改高层模块的代码
示例代码

无 DIP 代码

class UserService {  private UserDao userDao;  public UserService(UserDao userDao) {  this.userDao = userDao;  }  public User getUserById(int userId) {  return userDao.getUserById(userId);  }  
}  class UserDao {  public User getUserById(int userId) {  // 具体实现逻辑,如从数据库中获取用户信息  return new User(userId, "John Doe");  }  
}

有 DIP 代码

interface UserDataAccess {  User getUserById(int userId);  
}  class UserDao implements UserDataAccess {  @Override  public User getUserById(int userId) {  // 具体实现逻辑,如从数据库中获取用户信息  return new User(userId, "John Doe");  }  
}  class UserService {  private UserDataAccess userDataAccess;  public UserService(UserDataAccess userDataAccess) {  this.userDataAccess = userDataAccess;  }  public User getUserById(int userId) {  return userDataAccess.getUserById(userId);  }  
}
注意点
  • 通过接口或抽象类定义依赖关系:使用接口或抽象类来定义高层模块和底层模块之间的依赖关系
  • 避免直接依赖具体类:如果直接依赖具体类,一旦有修改,依赖元就要同步改动,影响和成本都较高
  • 使用依赖注入解耦:使用依赖注入来解耦类之间的依赖关系,通过注入抽象的实现来实现高层模块对底层模块的依赖

6 、CARP(Composition/Aggregation Reuse Principle)合成/聚合复用原则

CARP 强调在应用设计过程中优先使用合成/聚合的关系,而不是继承的关系来实现复用。

优点
  • 更好地代码封装:通过使用合成/聚合,可以将对象的不同部分封装在不同的类中,更好地隐藏细节,提高代码的模块化和可维护性
  • 更灵活的代码结构:通过使用合成/聚合,可以更容易地改变对象的行为和结构,只需要修改相关的类,不需要修改整个继承体系
  • 更好的可重用性:通过使用合成/聚合,可以根据需要组合不同的对象来实现代码的可重用性,且合成/聚合本身是一种松耦合,可以更便捷地组装新的对象类型
  • 更好的可扩展性:通过使用合成/聚合,更便捷地添加新的功能和行为到应用中,这种灵活的关系,可以更容易适应新的需求和变化
示例代码

无 CARP 代码

class Car {  private Engine engine;  private Transmission transmission;  private Wheel wheel;  private Door door;  public Car(Engine engine, Transmission transmission, Wheel wheel, Door door) {  this.engine = engine;  this.transmission = transmission;  this.wheel = wheel;  this.door = door;  }  public void start() {  engine.start();  }  public void shift(int gear) {  transmission.shift(gear);  }  public void turn(int degrees) {  wheel.turn(degrees);  }  public void open() {  door.open();  }  
}

有 CARP 代码

interface Engine {  void start();  
}  
interface Transmission {  void shift(int gear);  
}  
interface Wheel {  // 可以添加一些方法,例如 rotate() 和 brake() 等  
}  
interface Door {  void open();  
}  
class Car {  private Engine engine;  private Transmission transmission;  private Wheel wheel;  private Door door;  public Car(Engine engine, Transmission transmission, Wheel wheel, Door door) {  this.engine = engine;  this.transmission = transmission;  this.wheel = wheel;  this.door = door;  }  
}
注意点
  • 封装变化:将变化的部分封装起来,使得变化对其他部分的影响最小
  • 强调组合/聚合:首选使用组合/聚合关系,而不是直接继承关系,以提高灵活性和可维护性
  • 松耦合:合成/聚合是一种松耦合关系,允许系统更容易地适应变化

7 、LoD(Law of Demeter)迪米特法则

LoD 强调在应用中应该尽量减少对象之间的直接依赖关系,降低耦合度,提高可维护性和可重用性。

核心思想是一个对象对其他对象保持最少的了解,并且只和那些和自己最有直接关系的对象进行交互。

一个对象只暴露必要的接口给其他对象,并且应该通过这些接口与其他对象进行交互。

优点
  • 降低耦合度:减少对象之间的直接依赖关系,使得系统更容易扩展和维护
  • 提高可维护性:对象之间的松耦合关系使得修改一个对象的内部实现不会影响其他对象
  • 提高可重用性:松耦合关系允许对象更容易地被独立重用在不同的上下文中
示例代码

无 LoD 代码

class Account {  private User user;  private List<Transaction> transactions;  public Account(User user, List<Transaction> transactions) {  this.user = user;  this.transactions = transactions;  }  public double getBalance() {  double balance = 0.0;  for (Transaction transaction : transactions) {  balance += transaction.getAmount();  }  return balance;  }  public void debit(double amount) {  user.setBalance(user.getBalance() - amount);  }  
}

有 LoD 代码

interface UserService {  double getBalance(User user);  
}  interface TransactionService {  void debit(User user, double amount);  
}  class Account {  private UserService userService;  private TransactionService transactionService;  public Account(UserService userService, TransactionService transactionService) {  this.userService = userService;  this.transactionService = transactionService;  }  public double getBalance() {  return userService.getBalance(userService.getUser());  }  public void debit(double amount) {  transactionService.debit(userService.getUser(), amount);  }  
}
注意点
  • 定义接口:将对象的相关操作定义在接口中,而不是直接依赖于具体的实现
  • 通过接口交互:对象应该通过接口进行交互,而不是直接调用其他对象的方法
  • 减少依赖关系:一个对象应该只与其直接的朋友发生交互,避免依赖过多的对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/217586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能技术在宽域飞行器控制中的应用

近年来&#xff0c;以空天飞行器、高超声速飞行器等 ̈1 为典型代表的宽域飞行器蓬勃发展&#xff0c;如图1所示&#xff0c;其 不仅对高端装备制造、空间信息以及太空经济等领 域产生辐射带动作用&#xff0c;进一步提升了中国在航空航 天领域的自主创新能力&#xff0c;同时也…

112. 路径总和(Java)

目录 解法&#xff1a; 官方解法&#xff1a; 方法一&#xff1a;广度优先搜索 思路及算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 方法二&#xff1a;递归 思路及算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 给你二叉树的…

(C++)最大连续1的个数--滑动窗口

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://le…

MIT18.06线性代数 笔记2

文章目录 正交向量与子空间子空间投影投影矩阵和最小二乘正交矩阵和Gram-Schmidt正交化行列式及其性质行列式公式和代数余子式克拉默法则、逆矩阵、体积特征值和特征向量对角化和A的幂微分方程和exp(At)马尔科夫矩阵 傅里叶级数复习二 正交向量与子空间 向量正交&#xff1a;x…

[RK-Linux] 移植Linux-5.10到RK3399(五)| 检查PCIe并识别M.2 NVMe SSD

ROC-RK3399-PC Pro 引出了 PCIe 座子,用于装载 M.2 NGFF M-Key 接口的 SSD。 文章目录 一、PCIe二、NVMe三、调试一、PCIe PCIe(Peripheral Component Interconnect Express)是一种高速串行总线接口,用于连接计算机系统中的各种外部设备。它是传统PCI总线的进化版本,提供…

《系统架构设计师教程(第2版)》第2章-计算机系统基础知识-05-多媒体

文章目录 1. 概述1.2 多媒体的特征1.3 基本组成1.4 多媒体技术应用2. 关键技术2.1 视音频技术1)视音频编码2)视音频压缩方法2.2 通信技术2.3 数据压缩技术2.4 虚拟现实 (VR)/增强现实 (AR) 技术1) VR技术2) AR技术3)分类4)需要提高的关键技术1. 概述 媒体 (Media) :是承…

【初阶C++】前言

C前言 1. 什么是C2. C发展史3. C的重要性4. 如何学习C 1. 什么是C C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危机&#xff0c; …

【MODBUS】libmodbus库写一个Modbus TCP客户端

libmodbus 是一个用于 Modbus 通信协议的 C 语言库&#xff0c;可以用来创建 Modbus TCP 客户端。以下是一个简单的示例代码&#xff0c;演示如何使用 libmodbus 创建一个 Modbus TCP 客户端。 首先&#xff0c;确保你已经安装了 libmodbus 库。你可以从 libmodbus 的官方网站…

【Linux系统编程二十一】:(进程通信3)--消息队列/信号量(system v标准的内核数据结构的设计模式)

【Linux系统编程二十】&#xff1a;消息队列/信号量(system v标准的内核数据结构的设计模式&#xff09; 一.消息队列二.system v标准的内核数据结构的设计三.四个概念(互斥/临界)四.信号量1.多线程并发访问2.计数器3.原子的4.总结 一.消息队列 一个叫做a进程啊&#xff0c;一个…

点云从入门到精通技术详解100篇-车载激光雷达路面检测

目录 前言 国内外研究现状 车载激光雷达系统研究现状 道路检测研究现状

实现CompletableFuture的返回数据,放入每个list中

为啥使用CompletableFuture 有时候我们后端接口&#xff0c;可能会有多个查询&#xff0c;而且这些查询是互不关联的&#xff0c;使用串行的方式&#xff0c;在数据量不大的时候&#xff0c;时间没什么影响&#xff0c;但是在数据量大的时候&#xff0c;使用CompletableFuture…

如何将LLMs封装成应用并在本地运行

最近我一直在致力于Ollama的工作&#xff0c;因此我花了很多时间思考如何在本地系统上运行大型语言模型&#xff08;LLMs&#xff09;以及如何将它们打包成应用程序。对于使用LLMs的大多数桌面应用程序而言&#xff0c;通常的体验要么是插入OpenAI API密钥&#xff0c;要么是从…

protobuf基础学习

部分内容出自&#xff1a;https://blog.csdn.net/baidu_32237719/article/details/99723353 proto文件来预先定义的消息格式。数据包是按照proto文件所定义的消息格式完成二进制码流的编码和解码。proto文件&#xff0c;简单地说&#xff0c;就是一个消息的协议文件&#xff0c…

Git常用命令大全

1.强制推送&#xff08;慎用&#xff0c;除非你认为其他冲突等可以丢弃 或者不是很重要&#xff09; git push -- force2.创建文件等小命令 touch a // 创建一个a文件 echo 1234 >> a // 把1234这个内容放入a文件 cat a // 打开a文件 读取出a文件中的内容 mkdir test /…

MAC IDEA Maven Springboot

在mac中&#xff0c;使用idea进行maven项目构建 环境配置如何运行maven项目1.直接在IDEA中运行2.使用jar打包后执行 如何搭建spring boot1.添加依赖2.创建入口类3.创建控制器4. 运行5.其他 环境配置 官网安装IDEA使用IDEA的创建新项目选择创建MAEVEN项目测试IDEA的MAVEN路径是…

(第64天)UNPLIUG/PLUG 迁移 PDB

在 Oracle 12C 之前,迁移数据库的方式大多通过 RMAN 或者数据泵的方式,但是在 12C 版本提出 CDB/PDB 架构后,对数据库进行了整合,只需要针对 PDB 进行迁移即可,本文介绍通过 UNPLUG/PLUG 的方式来迁移数据库。 环境信息 测试环境信息: 角色主机名IP地址数据库版本实例名…

【二分查找】【双指针】LeetCode:2565最少得分子序列

作者推荐 【动态规划】【广度优先】LeetCode2258:逃离火灾 本文涉及的基础知识点 二分查找算法合集 有序向量的二分查找&#xff0c;初始化完成后&#xff0c;向量不会修改。 双指针&#xff1a; 用于计算子字符串是s的字符串的子系列。 题目 给你两个字符串 s 和 t 。 你…

《地理信息系统原理》笔记/期末复习资料(10. 空间数据挖掘与空间决策支持系统)

目录 10. 空间数据挖掘与空间决策支持系统 10.1. 空间数据挖掘 10.1.1. 空间数据挖掘的概念 10.1.2. 空间数据挖掘的方法与过程 10.1.3. 空间数据挖掘的应用 10.2. 空间决策支持系统 10.2.1. 空间决策支持系统的概念 10.2.2. 空间决策支持系统的结构 10.2.3. 空间决策…

Java网络编程,使用UDP实现TCP(二), 实现数据传输过程

简介&#xff1a; 经过了三次握手过程&#xff0c;我们的服务端和客户端已经建立了连接。我们接下来需要做的就是数据的传输。 主要步骤&#xff1a; 数据发送&#xff1a;客户端或服务器将数据打包成一个或多个数据段&#xff0c;每个数据段都有一个序列号&#xff08;SEQ&a…

mybatis xml 热部署

平时我们在项目中多多少少会根据不同的情况等等原因去调试sql&#xff0c;在数据库测试完后也需要在代码里面运行测试&#xff0c;但是每次修改就需要重启服务就显得太繁琐&#xff0c;所以如果mybatis的xml也可以热部署当然是最好的了&#xff0c;那我来试试如何可以将mybatis…