GO学习记录1——设计原则

GO学习记录(1)

一、设计原则:面向接口编程

所谓的面向接口编程,是指:如果你使用到了别的类型,那么用的一定是接口。
这里有一些争议的点:

  • 如果我当下只有一个实现,我需要定义一个接口吗?
    答案是,如果你预期你负责维护这段代码的时间内,有可能有新的实现,那你就要定义接口(实践中可以多定义几个接口)。
  • 什么时候不用接口,而是用具体实现呢?
    答案是你依赖于具体实现细节的时候。例如说在 Repository 里面,正常读写数据都是用接口方法,但是如果你要依赖于这个 Repository 内部控制缓存预加载的特性,那么就应该用具体的实现。
    在这里插入图片描述

二、为什么要面向接口编程

面向接口编程核心就是为了:扩展性
也就是,在使用接口的时候,我们可以根据需要随时切换不同的实现,而不需要修改已有的代码。
除此以外,面向接口编程还是别的优秀实践的基础:

  • 是坚持开闭原则的基础。
  • 是装饰器模式等设计模式的基础。
  • ……
    在这里插入图片描述

三、依赖注入

所谓的依赖注入就是:

  • 如果 A 用到了 B ,那么 B 一定是 A 的字段。
    否定了包变量的使用,包变量的核心是包里面这个变量只有一个值,一旦有不同实现,需要用到包变量不同的值时不可能实现。
  • 如果 B 是 A 的字段,那么 B 一定是在构造A的时候从外部传入进来的。
    A 去 New B 的实现,否定 A 去初始化 B 这样一个动作。
    以 Redis 客户端为例,一定要从外面传 Redis 的客户端,而不是从 Cache 里去读配置然后初始化,因为一旦自己去初始化,其他人无法替换实现

如果叠加面向接口编程,那么就再加上一条:

  • 如果A用到了B,那么B一定是一个接口。

也就是,在初始化A的时候,传入B的一个具体实现。

四、单一职责原则

单一职责原则,就是指一个接口只干一件事(或者有联系的几件事)。
最直观的说法,就是你的接口不能有很多方法,应该只有寥寥几个方法,而且这些方法应该是类似的。
最大好处就是拆分之后可读性和可维护性都有明显提高,治理力度更加灵活。

五、CQRS

CQRS:命令-查询分离。
换一句更加通俗易懂的话来说,就是读写方法,你要分散到不同的接口里面去。
例如搜索服务拆分成数据同步接口和搜索接口,也可以看做是这种原则的体现。
并且,读写方法分离到不同的接口之后,还有一个最大的好处:分别治理。
读写接口降级写接口;限流的时候可以读接口设置更高的阈值,写接口设置更加低的阈值。

六、开闭原则

开闭原则强调的是:对修改闭合,对扩展开放。
简单来说,就是如果在发生变更的时候,已有的实现不需要改,而是考虑提供新的实现。
例如就是使用装饰器来为已有功能添加新的功能。
以 sms 为例,在 sms 的基础上尝试引入容错、可观测性的时候,并没有修改已有的代码,而是提供了新的实现。

type Service struct{
	svc		sms.Service //已有实现
	tracer	trace.Tracer
func (s *Service) Send(ctx context.Context,
	tplId string,
	args []string, numbers ...string) error{ //新的实现
	ctx,span := s.tracer.Start(ctx, "sms_send")
	defer span.End()
	//你也可以考虑拼接进去 span name 里面
	span.SetAttributes(attribute.String("tplId", tplId))
	err := s.svc.Send(ctx, tplId, args, numbers...)
	if err != nil {span.RecordError(err)}
	return err
}

所以,往往你加一个 if-else 分支的时候,就意味着你没有坚持这条原则。

七、超前设计,但不超前实现

很多时候,为了方便后期维护或者扩展,在设计的时候,需要超前设计。
第一条要记住的就是:超前设计,但是不要超前实现。
也就是说,即便你预期到将来会有很多的变化,但是你不要提早解决应对这些变化,而是通过留出接口的形式来保留应对的可能性。
在这里插入图片描述
而超前的话,也不能超前太多。
那么超前多少才算是超前太多?这要根据具体的现实情况来判定:

  • 先将所有自己能够预想到的、需求分析里面讨论到的都纳入考虑范围内。
  • 正常你考虑的越多,设计的复杂度就会越高,需要的时间、人力就越多。
  • 将接下来两三个迭代内会遇到的变更,在设计的时候留出口子。
  • 如果是后续更长时间内可能出现的变更,此时纳入设计范围的代价并不高,就考虑进来;代价高就放弃。
    在这里插入图片描述

八、异步优先

很多人的思维是优先考虑同步调用。
但是在系统规模开始变大,稳定性、可用性和性能这些问题日益突出的时候,需要转变为异步优先
具体来说,就是不到逼不得已,不用同步调用。
也就是但凡能够借助 Kafka 等来完成的事情,就不要借助同步的 gRPC 或者 HTTP 来完成。
在这里插入图片描述

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值