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

SOLID原理:用Golang的例子来解释

随着软件系统变得越来越复杂,编写模块化、灵活和易于理解的代码非常重要。实现这一目标的方法之一是遵循SOLID原则。这些原则是由罗伯特-C-马丁(Robert C. Martin)提出的,以帮助开发人员创建更容易维护、测试和扩展的代码。
本文将对每个SOLID原则进行概述,并通过用Golang编写的例子说明它们在贸易生态系统中的应用。
单一责任原则(SRP):该原则指出,一个类应该只有一个变化的理由。如果我们违反了这一原则,这个类就会有多个责任,使得它更难维护、测试和扩展。这可能导致代码紧密耦合,难以重用,并且容易出错。
在一个贸易生态系统中,一个贸易类应该负责存储和处理贸易数据。另一个类,如TradeValidator,可以负责根据业务规则来验证交易。通过分离这些关注点,每个类可以更容易地被测试和维护。

type Trade struct {TradeID intSymbol stringQuantity float64Price float64
}type TradeRepository struct {db *sql.DB
}func (tr *TradeRepository) Save(trade *Trade) error {_, err := tr.db.Exec("INSERT INTO trades (trade_id, symbol, quantity, price) VALUES (?, ?, ?, ?)", trade.TradeID, trade.Symbol, trade.Quantity, trade.Price)if err != nil {return err}return nil
}type TradeValidator struct {}func (tv *TradeValidator) Validate(trade *Trade) error {if trade.Quantity <= 0 {return errors.New("Trade quantity must be greater than zero")}if trade.Price <= 0 {return errors.New("Trade price must be greater than zero")}return nil
}

开放-封闭原则(OCP):这一原则指出,类应该是开放的,可以进行扩展,但对修改来说是封闭的。如果我们违反了这一原则,我们可能不得不修改现有的代码来增加新的功能,这可能会引入错误,使代码难以维护。这也会导致代码难以测试和重用。
在一个贸易生态系统中,TradeProcessor类应该被设计成对扩展开放,但对修改封闭。这意味着,如果增加了新的交易类型,TradeProcessor类应该能够处理它们而不需要修改现有的代码。这可以通过定义一个处理交易的接口并为每个交易类型实现它来实现。

type TradeProcessor interface {Process(trade *Trade) error
}type FutureTradeProcessor struct {}func (ftp *FutureTradeProcessor) Process(trade *Trade) error {// process future tradereturn nil
}type OptionTradeProcessor struct {}func (otp *OptionTradeProcessor) Process(trade *Trade) error {// process option tradereturn nil
}

里氏替换原则(LSP):该原则指出,子类型应该可以替代其基类型。如果我们违反了这一原则,我们可能会引入出乎意料和不一致的行为,这可能会导致难以追踪的错误。这也会使我们很难写出能与各种不同类型一起工作的代码。
在一个贸易生态系统中,FutureTrade类应该是Trade类的一个子类型,这意味着它应该能够代替Trade类而不引起任何问题。例如,如果一个TradeProcessor类期望一个Trade对象,但收到一个FutureTrade对象,它应该仍然能够处理交易而不会有任何问题。

type Trade interface {Process() error
}type FutureTrade struct {Trade
}func (ft *FutureTrade) Process() error {// process future tradereturn nil
}

接口隔离原则(ISP):该原则指出,客户不应该被迫依赖他们不使用的接口。如果我们违反了这一原则,我们的接口可能会过大,并且包含与某些客户无关的方法,这可能会导致代码难以理解和维护。这也会导致代码无法重用,而且会造成模块之间不必要的耦合。
在一个交易生态系统中,一个Trade接口应该只包括与所有类型的交易相关的方法。可以创建额外的接口,比如OptionTrade或FutureTrade,以包括那些交易类型所特有的方法。这样一来,只需要处理特定类型的交易的代码就可以依赖适当的接口,而不是一个包含不必要的方法的更大的接口。

type Trade interface {Process() error
}type OptionTrade interface {CalculateImpliedVolatility() error
}type FutureTrade struct {Trade
}func (ft *FutureTrade) Process() error {// process future tradereturn nil
}type OptionTrade struct {Trade
}func (ot *OptionTrade) Process() error {// process option tradereturn nil
}func (ot *OptionTrade) CalculateImpliedVolatility() error {// calculate implied volatilityreturn nil
}

依赖性反转原则(DIP):这一原则指出,高层模块不应依赖低层模块。相反,两者都应该依赖于抽象的东西。如果我们违反了这个原则,我们可能会有难以测试和重用的代码,而且是紧密耦合的。这也会导致代码难以维护和扩展。
在一个贸易生态系统中,TradeProcessor类应该依赖于一个接口,如TradeService,而不是一个具体的实现,如SqlServerTradeRepository。这样一来,TradeService接口的不同实现可以互换,而不影响TradeProcessor类,这可以使其更容易维护和测试。例如,可以用MongoDBTradeRepository代替SqlServerTradeRepository,而不用修改TradeProcessor类。

type TradeService interface {Save(trade *Trade) error
}type TradeProcessor struct {tradeService TradeService
}func (tp *TradeProcessor) Process(trade *Trade) error {err := tp.tradeService.Save(trade)if err != nil {return err}// process tradereturn nil
}type SqlServerTradeRepository struct {db *sql.DB
}func (str *SqlServerTradeRepository) Save(trade *Trade) error {_, err := str.db.Exec("INSERT INTO trades (trade_id, symbol, quantity, price) VALUES (?, ?, ?, ?)", trade.TradeID, trade.Symbol, trade.Quantity, trade.Price)if err != nil {return err}return nil
}type MongoDbTradeRepository struct {session *mgo.Session
}func (mdtr *MongoDbTradeRepository) Save(trade *Trade) error {collection := mdtr.session.DB("trades").C("trade")err := collection.Insert(trade)if err != nil {return err}return nil
}

综上所述,如果我们不使用SOLID原则,我们最终可能会得到难以维护、测试和重用的代码。这可能会导致错误,性能差,以及无法为代码添加新功能。通过遵循这些原则,我们可以创建更加模块化、更加灵活、更加容易理解的代码,这可以使软件整体上更加完善。

相关文章:

SOLID原理:用Golang的例子来解释

随着软件系统变得越来越复杂&#xff0c;编写模块化、灵活和易于理解的代码非常重要。实现这一目标的方法之一是遵循SOLID原则。这些原则是由罗伯特-C-马丁&#xff08;Robert C. Martin&#xff09;提出的&#xff0c;以帮助开发人员创建更容易维护、测试和扩展的代码。 本文将…...

mysql是如何使用索引的?

摘自官网 MySQL使用索引进行以下操作: WHERE条件中,快速查找匹配的行。(快速查询数据) 从准备查询的数据中消除多余行。如果可以在多个索引之间进行选择,则MySQL通常会使用查找最少行数的索引。 如果表具有多列索引,那么优化器可以使用索引的任何最左前缀来查找行。 举例来…...

自动驾驶IPO第一股及商业化行业标杆 Mobileye

一、Mobileye 简介 Mobileye 是全球领先的自动驾驶技术公司&#xff0c;成立于 1999 年&#xff0c;总部位于以色列耶路撒冷。公司专注于开发视觉感知技术和辅助驾驶系统 (ADAS)&#xff0c;并在自动驾驶领域处于领先地位。Mobileye 是高级驾驶辅助系统&#xff08;ADAS&#…...

Linux前后端程序部署

1.总述 首先安装包类型分为 二进制发布包安装:找到对应自己的linux平台版本(CentOS还是redhat等),的具体压缩文件,解压修改配置 源码编译安装:需要自己进行编译 对于redhat安装包,可以使用rpm命令进行安装,但是rpm命令安装不能够解决依赖库的问题,常用的rpm命令,只用于卸载…...

手把手 S32K344移植FreeRTOS

版本信息 RTD:2.0.0.2022 S32DS:3.4.0.2020 下载 从S32K3参考软件下载FreeTROS FreeRTOS安装链接&#xff1a;https://www.nxp.com/webapp/swlicensing/sso/downloadSoftware.sp?catidSW32K3-REFSW-D 根据S32DS版本和S32K3 RTD 2.0.0 Package找到对应的FreeRTOS的zip安装…...

《云原生安全攻防》-- 云原生安全概述

从本节课程开始&#xff0c;我们将正式踏上云原生安全的学习之旅。在深入探讨云原生安全的相关概念之前&#xff0c;让我们先对云原生有一个全面的认识。 什么是云原生呢? 云原生&#xff08;Cloud Native&#xff09;是一个组合词&#xff0c;我们把它拆分为云和原生两个词来…...

综合分享1

VM及安装配置windows server 2008 1&#xff09;安装配置VM 确保是否正确安装&#xff1a; 1&#xff09;检查本地“网络与internal设置”中的虚拟网卡是否创建成功&#xff08;vmnet1和vmnet8&#xff09; 2&#xff09;必须通过services.msc查看vmware的所有是否已经…...

Redis -- set集合

挑战自己&#xff0c;每天进步一点点&#xff0c;成就将属于不停止脚步的你。 目录 Redis集合&#xff1f; 集合基本命令 sadd smembers sismember scard spop srandmember smove srem 集合间操作 sinter sinterstore sunion sdiff sdiifstore Redis集合&#…...

明天是几号(c++题解)

题目描述 题目描述 在某国&#xff0c;每年有 个月&#xff0c;每个月有 天。 求 年 月 日的下一天的日期。 输入格式 第一行&#xff1a;两个整数 。 第二行&#xff1a;三个整数 输出格式 输出三个整数&#xff0c;表示 年 月 日的下一天的日期。 样例 样例…...

PHP安装后错误处理

一&#xff1a;问题 安装PHP后提示错误如下 二&#xff1a;解决 1&#xff1a;Warning: Module mysqli already loaded in Unknown on line 0解决 原因&#xff1a;通过php.ini配置文件开启mysqli扩展的时候&#xff0c;开启了多次 解决&#xff1a;将php.ini配置文件中多个…...

Unity3D开发之鼠标单双击判断

在开发游戏和交互式应用程序时&#xff0c;经常需要对用户的鼠标点击进行准确的响应。其中&#xff0c;单击和双击事件的判断是常见需求之一。本文将介绍如何在Unity中优雅地实现鼠标单双击判断&#xff0c;使代码结构清晰、易读、易维护。 背景 在许多项目中&#xff0c;我们…...

openGauss学习笔记-214 openGauss 性能调优-确定性能调优范围

文章目录 openGauss学习笔记-214 openGauss 性能调优-确定性能调优范围214.1 性能因素214.2 调优范围确定 openGauss学习笔记-214 openGauss 性能调优-确定性能调优范围 数据库性能调优通常发生在用户对业务的执行效率不满意&#xff0c;期望通过调优加快业务执行的情况下。正…...

JAVA——Stream流

1.Stream流的作用&#xff08;流水线&#xff09; 结合了Lambda表达式&#xff0c;简化集合、数组的操作&#xff1b; 2.Stream流的使用步骤 ①先得到一条Stream流&#xff08;流水线&#xff09;&#xff0c;并将数据放上去&#xff1b; ②利用Stream流中的API进行各种操作…...

QXlsx Qt操作excel(1)

QXlsx 是一个用于处理Excel文件的开源C库。它允许你在你的C应用程序中读取和写入Microsoft Excel文件&#xff08;.xlsx格式&#xff09;。该库支持多种操作&#xff0c;包括创建新的工作簿、读取和写入单元格数据、格式化单元格、以及其他与Excel文件相关的功能。 关于QXlsx的…...

20240131在ubuntu20.04.6下使用whisper不同模式的比对

20240131在ubuntu20.04.6下使用whisper不同模式的比对 2024/1/31 16:07 首先你要有一张NVIDIA的显卡&#xff0c;比如我用的PDD拼多多的二手GTX1080显卡。【并且极其可能是矿卡&#xff01;】 2、请正确安装好NVIDIA最新的驱动程序和CUDA。可选安装&#xff01; 3、配置whisper…...

HTTP相关问题

目录 1.从输入URL到页面展示到底发生了什么&#xff1f; 2.HTTP状态码有哪些&#xff1f; 2.1 2XX(成功状态码) 2.2 3XX(重定向状态码) 2.3 4XX(客户端错误状态码) 2.4 5XX(服务端错误状态码) 3.HTTP 请求头中常见的字段有哪些&#xff1f; 4.HTTP和HTTPS有什么区别&…...

闲人闲谈PS之五十三——离散制造中的魔鬼--物料套裁

惯例闲话&#xff1a;最近和老婆大人商议买车事宜&#xff0c;闲人以为会陷入买油车还是电车的纠结&#xff0c;没想到老婆大人无比坚定&#xff0c;买电车。在买车这方面&#xff0c;老婆的想法居然比闲人超前。闲人对车定位在代步工具&#xff0c;2年前&#xff0c;对车还是印…...

Dell服务器iDRAC9忘记密码, 通过RACADM工具不重启 重置密码

系列文章目录 文章目录 系列文章目录前言一、RACADM工具二、linux环境1.解压安装RACADM工具测试RACADM工具重置iDRAC密码 Windows环境 前言 一、RACADM工具 RACADM工具 官网参考信息 https://www.dell.com/support/kbdoc/zh-cn/000126703/%E5%A6%82%E4%BD%95-%E9%87%8D%E7%BD…...

2024年Java架构篇之数据结构与算法面试题

2024年Java实战面试题_java 5 年 面试-CSDN博客 2024年Java架构篇之数据结构与算法面试题 1、判断一个数是否是2的N次方&#xff0c;比如2、4、8、16是6、10不是 1:01、2:10、3:011、4:100、7:0111、8:1000、15:01111、16:10000 if(n&(n-1) 0) 那么n就是2的次方 n > 1...

蓝桥杯刷题day06——平均

1、题目描述 有一个长度为n 的数组&#xff08;n 是 10 的倍数&#xff09;&#xff0c;每个数ai都是区间 [0,9] 中的整数。 小明发现数组里每种数出现的次数不太平均&#xff0c;而更改第i 个数的代价为bi&#xff0c; 他想更改若干个数的值使得这10 种数出现的次数相等&…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

PydanticAI快速入门示例

参考链接&#xff1a;https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...

拟合问题处理

在机器学习中&#xff0c;核心任务通常围绕模型训练和性能提升展开&#xff0c;但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正&#xff1a; 一、机器学习的核心任务框架 机…...

李沐--动手学深度学习--GRU

1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...

精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑

精益数据分析&#xff08;98/126&#xff09;&#xff1a;电商转化率优化与网站性能的底层逻辑 在电子商务领域&#xff0c;转化率与网站性能是决定商业成败的核心指标。今天&#xff0c;我们将深入解析不同类型电商平台的转化率基准&#xff0c;探讨页面加载速度对用户行为的…...

代理服务器-LVS的3种模式与调度算法

作者介绍&#xff1a;简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们上一章介绍了Web服务器&#xff0c;其中以Nginx为主&#xff0c;本章我们来讲解几个代理软件&#xff1a…...