go后台架构设计浅学习
go后台架构设计浅学习
这里主要是列举几个设计模式 然后说一下优缺点以及代码实现演示 以及一些小技巧 和值得注意的一些东西
参考文章:[Go后台项目架构思考与重构 | 深度长文-CSDN博客](https://blog.csdn.net/dqcfkyqdxym3f8rb0/article/details/105780625#:~:text=1 架构的重要性; 2 重构的几种模式; 3 设计原则;,4 DDD 中领域思想; 5 项目的可测试性; 6 项目的可演进性。) 这里强烈直接观看原文 本blog只是对这个文章中的一些专业名词进行一个解释 而且本文可能对原文的理解有偏差而且并没有实际的代码列子来进行辅助理解 所以建议直接食用原文 当然后续会更新
常见开发遇到的规范问题
个人在开发的时候其实遇到了很多的问题 就是设计框架上面的混乱 本来想着偷偷懒有一些东西都没去多想 想着不会出多大问题 随着代码的累积发现后面程序就积重难返了 这里看见了大佬的文章感觉说得很对(
依赖关系混乱
- 在开发中经常发生这种情况 就是经常在设计模块的时候只要不发生依赖循环我们就会在A依赖B依赖C 然后保证B和C不去依赖A 但是频繁这样做随意去依赖其他模块会导致模块之间依赖极其混乱 模块之间难以复用 所以我们可以采用外部依赖接口化 也就是不直接依赖B和C而是去依赖一个接口D和E 接口D和E规定了我们需要B和C的哪些函数 这样就可以实现各个类之间的解耦操作 同样的做法也可以解决下面出现的通讯混乱
通讯混乱
- 也就是在设计模块的时候经常发生各个模块之间怎么实现通讯或者调用其他模块的函数 很容易出现各个模块直接进行随意的函数调用 将大量函数暴露在各个层级之间
MVC代码设计模式
参考文章:
mvc架构在设计的时候将视图层和业务层进行了分离 这提供了
低耦合性
层级之间不相互依赖 修改比较方便不需要牵一发而动全身 因为不同板块独立性较高所以我们也可以将同一份代码在不同的项目中引用 这提高了较高的重用性
同时mvc由于板块之间分离 调试起来是困难的 以及这样的设计模式对中小型框架是不合适的通常花费大量时间去划分板块换取的效益并不大在中小框架中 其次由于板块之间不互相依赖通常导致一些功能的实现复杂化 框架内部的代码复用性差这里简单的了解一下MVC设计模式 我们重心在后面 因为其实我们大多数时候写的项目都不会很大 MVC对于中小型项目并不是很友好
- 由这几个组成:Model View Controller
Model
封装
与应用
程序业务逻辑相关的数据以及对数据的处理方法通常
model
对数据具备直接访问
的权力 比如数据库等model
通常不需要依赖view
与Controller
通常
view
是通过事先在model
上注册(观察者模式)(观察者模式后面详细解释)
View
- 实现数据有目的的显示 给用户显示出来 然后用户通过view触发一些事件发送给Controller
Controller
- 一般用于处理事件并且做出响应 比如用户行为或者
Model
发生的变化
观察者模型
观察者模式一般是解决这样的场景的 比如实现一个广告系统 然后广告的数据A 显示屏B 报纸C 我们A的数据发生变化的时候 B和C当然也得把对于数据刷新显示出来 如果我们在A数据变化的时候去直接调用B和C的显示函数 从而实现数据变化B和C都发生变化 但是这样会导致类之间紧密耦合 也就是A的稳定性依赖于B和C两个类 并且我们每多一个用于显示的类 都需要在A初始化的时候再多传入一个类 并且调用其函数
- 所以观察者模式就是多设计一个中间人一样的接口 来实现简化这个过程 也就是当A数据更新的时候实际上我们调用的而是D接口 然后B和C都去实现D接口 也就是我们的A接受的是D接口集合 然后在数据更新的时候调用这个集合
发布订阅模式
- 也就是抽象出一个消息代理 也就是比如A是发布者 B是订阅者 C是代理 A负责将消息全部塞给C然后C再转发给B B可以选择自己需要什么消息
失血模型,贫血模型,充血模型和胀血模型
参考文章:DDD(领域驱动设计)系列主题:失血模型,贫血模型,充血模型和胀血模型详细解读和代码案例说明!_贫血模型 充血模型 胀血模型-CSDN博客
OO设计原则 -- OO设计的原则及设计过程的全面总结 - davygeek - 博客园 (cnblogs.com)
这里拿mvc进行举列子
失血模型
也就是mvc中model仅仅包含对象属性的定义并且基础的get/set方法 所有业务逻辑都交给其他层级进行处理
贫血模型
比如说mvc中model仅仅包含对象属性的定义和操作对象的get/set方法 并且包含一些行为 一些基本的函数 但是不依赖Dao层(持久层)的内容 这样层级之间结构清晰 各层之间单向依赖 然后对于业务量小的应用来说 用起来非常自然 开发迅速便于理解 但是同时无法应对非常复杂的逻辑和场景
充血模型
比如mvc中model包含了对象的属性 get/set函数后 还包含了大量相关业务 也依赖于dao层 这样其他的层级负责的东西就比较少 对特定情况进行单独处理 或者其他层级负责权限控制等东西 这是符合OO设计原则的(也就是面对对象设计原则) 同时这样会导致model层业务逻辑模糊 因为我们将分不清楚什么东西该放进model里面什么东西放进其他业务
oo设计原则 也就是基于对象的设计思想 通常特征就是
抽象
、封装
、继承
、多态
通常有这些设计原则:单一职责
,开放封闭
,依赖倒置
,里氏代换
,接口隔离
单一职责
:任何一个软件模块都应该只对一类行为者负责。 并不是一个模块只做一个事情 而是一个模块对一类行为者负责开放封闭
:也就是基于原本的实现进行扩展而不是进行修改 比如当一个架构已经大体固定下来了 去添加新的功能应该是利用继承重写等机制进行添加新的功能而不是直接对原本的代码进行修改 从而让它适配新的功能 比如我有一个A类其中有个B函数 我们应该是继承A类造出C类 然后C重写B来添加新的逻辑 而不是直接在A的B里面进行添加逻辑 因为这样会导致A中的B过于庞大依赖倒置
:也就是依赖抽象,而不是依赖语句的实现 比如我们函数之间传递的应该大多数时候是接口 而不是一个具体的函数或者具体的结构体/类 面向接口进行编程而不是面对实现(1)应该避免在代码中写入与任何具体实现相关的名字,或者是其他容易变动的事物名字;
(2)应在代码中多使用抽象接口,尽量避免使用那些多变的具体实现类;
(3)不要在具体实现类上创建衍生类,Golang 语言天生就符合这一点;
(4)不要覆盖包含具体实现的函数,即别重写,在 Skipper v1 的 Task 模式中违反了这一条,因为 Task 模式为了减少代码重复,所有 Task Handler 都需要内嵌 Default Handler,并重写其觉得需要修改的函数。
SDP
:稳定依赖原则 也就是依赖必须要指向更稳定的方向 也就是一个稳定的组件不能够依赖一个不稳定的组件 如果是在需要依赖那么请用抽象层将它们隔离开 而不是直接接触里氏代换
:子类型必须能够替换到他们的父类型接口隔离
:多个和客户相关的接口要好于一个通用接口迪米特法则
:也就是如果两个类本身没有直接通讯的手段 尼玛就不要让他们直接产生相互作用 比如A类要调用B类的函数 那么就应该多一个第三方来间接转发这个调用 不应该让多个类之间的依赖混乱化
胀血模型
- 包含了属性 以及其全部相关的业务逻辑 也包含了不相关的其他逻辑 这样会导致代码的理解和维护性很差 但是大大简化了代码的封层结构