如何使用Golang进行无心智负担的编程

2019-06-08 10:54发布

Go语言中文网,致力于每日分享编码知识,欢迎关注我,会有意想不到的收获!

不知读者是否也会时刻想: 我该怎么写这段代码才优雅, 后期改起来方便?

努力思考却还是得不到最佳答案, 烦躁等负面情绪不约而来。这便是在编程过程中的心智负担。

这篇文章将从多个方面来简化思考, 希望它能给努力思考的你带来一点小灵感.

题外话: Golang哲学就是"少便是多", 志在减少开发者的心智负担. 不过再好的语言也敌不过"人", 请接受Golang的风格 否则写出PHPGo, JavaGo真是作茧自缚。

关于设计模式

java的23种设计模式? 再见.

不是说他们没有作用,只是说它们太死板复杂,学习它们通常入不敷出。

对于编程还有很多需要注意的地方(下文),而不要只局限于设计模式。

我给出的建议是只需要理解一个大概,在平时编程中能用则用。

关于面向对象

Golang相比Java来说, 对"面向对象"这件事的支持是"不完整"的.

但话又说回来现在的"面向对象编程"渐渐被扭曲为了"面向类编程"(COP),而COP是复杂并难以理解的,COP有好处但要发挥出来并不容易。所以Golang决定抛弃所有不必要的概念以改善这个问题。

现在不必再理解 封装(这个简单到不需要理解), 多态, 继承.

在golang中只需要理解两个更实在的东西: 接口, 组合.

接口

Java 之父 James Gosling 在某次会议上有过这样一次问答:

I once attended a Java user group meeting where James Gosling (Java’s inventor) was the featured speaker.

During the memorable Q&A session, someone asked him: “If you could do Java over again, what would you change?”

“I’d leave out classes,” he replied. After the laughter died down, he explained that the real problem wasn’t classes per se, but rather implementation inheritance (the extends relationship). Interface inheritance (the implements relationship) is preferable. You should avoid implementation inheritance whenever possible.

大意是:

问:如果你重新做 Java,有什么是你想改变的?

答:我会把类(class)丢掉。真正的问题不在于类本身,而在于基于实现的继承(the extends relationship)。基于接口的继承(the implements relationship)是更好的选择,你应该在任何可能的时候避免使用实现继承。

---- 摘自 Golang OOP、继承、组合、接口 https://studygolang.com/articles/20972

在Golang中只需要记得一个东西: Interface(接口).

参见io.Reader接口就知道这种设计有多厉害.

读文件是它, 读网络请求也是它, 更骚的是 对于linux(Every thing is a file)来说用它就能操作近乎整个系统了.

简单的说: 当某个功能(如去北京)有多种(或者以后可能有多种)实现方式(如坐火车/飞机/骑车)的时候, 用接口.

组合

组合理解起来并不复杂, 不过是一个语法糖, 就算没有组合功能也毫不影响Go程序的运行.

如下代码, 没有组合换一种写法即可.

// 组合
type L struct {
sync.Mutex
}
// 这样使用
L.Lock()
// 没有组合
type L struct{
l sync.Locker
}
// 这样使用
L.l.Lock()

简单的说: 组合能用则用,如果你不知道如何使用或者不用也并无大碍。

关于可维护性

"开闭原则"对我启发很大.

原文是这样:

伯特兰·迈耶一般被认为是最早提出开闭原则这一术语的人,在他1988年发行的《面向对象软件构造》中给出。这一想法认为一旦完成,一个类的实现只应该因错误而修改,新的或者改变的特性应该通过新建不同的类实现。新建的类可以通过继承的方式来重用原类的代码。衍生的子类可以或不可以拥有和原类相同的接口。

但其实我们在开发的时候并不是一直都在和对象打交道.

在我看来, "开闭原则"适用于平时写的任何代码.

完整理解"开闭原则"可能还是会造成心智负担, 所以先打住, 只需要这样:

  • 一个函数只做一个功能(事情), 一旦这个功能开发完成, 这个函数应当"闭合", 不应该再修改(bug除外).
  • 当需要修改功能, 应当尽量将修改也写成一个函数,尽早的进入分支判断去调用新修改,而原代码不变。

这便是 "对修改闭合, 对扩展开放".

这里不得不在提及"面向函数编程", 它的思想包括但不限于:

  • 一个函数只做一个功能
  • 函数无副作用

它正好利于修改, 利于写出符合"开闭原则"的代码.

关于错误处理

默认的errors包在对于多层的复杂应用是不够的,这种情况下建议自行封装,但别太追求完美 在项目中够用就好。我们等待官方方案即可: https://github.com/golang/go/issues/29934

关于命名

restful能解决大部分命名问题.

你的代码完全可以这样无脑命名而不失优雅.

这样的白话文真的很好命名与理解(根本不需要词汇量).

并发

无脑Goroution, 80%的情况下都没问题.

如果你实在担心, 用channel的做下并发数量控制就好, 或者使用更完整的工具叫"协程池", 他们的实现都不复杂.

第三方库

得益于golang的开源和这几年的蓬勃发展,golang的生态已经十分完善,所以很多情况下我们应该"面相github编程",第三方提供的代码已能满足我们大多数需求。同时 选用一个受欢迎的第三方代码库通常比自己的更可靠,后续维护也省心很多。

关于编码风格

最省心的行为是: 先跟随团队再提出意见

那么省下来的时间和精力用来干嘛?

  1. 重构(自己的)老代码。
  2. 研究更高级的与语言弱相关的架构,如Devops/分布式/微服务。
  3. 实现更多的产品或功能。

本文作者 bysir:https://www.jianshu.com/u/b3f7227e6640

文章来源: https://www.toutiao.com/group/6699732731598733838/