为什么你需要抽象思维?

1,664 阅读4分钟

抽象思维是一种至上而下的思考解决问题的思维模型。它可以帮助你从复杂的关系与逻辑中,理出一条清晰的思路,它简单确实用~

本文从三个方面来说明抽象思维的力量

  1. 思维抽象
  2. 逻辑抽象
  3. 设计抽象

思维抽象

在开发过程中,通常我们容易陷入具体的代码实现中,特别是实现很复杂的逻辑时,大多数据人的思维都是一个顺序的,也就是从头到尾的写代码。而一个正确的流程应该是先实现抽象逻辑,后实现细节

我们以一个最简单的例子来说明问题

在下面的示例中有三个逻辑块,这是一个流式编码的过程,从上向下一步步实现,我们的大脑分析信息的能力都是有限的,如果下面的逻辑非复杂,你的大脑会转不过来,你可能会反复的修改你的逻辑,然后看着几百代的这个代码头疼,我相信你肯定有过这样的体验:

func doSomething(arg int) {
	// step1
	// step1.1
	// step1.2
	// step1.3

	if arg > 100 {
		// step2
		// step2.1
		// step2.2
		return
	}

	// step3
	// step3.1
	// step3.2
	// step3.3
}

而从抽象思维就是去考虑问题时,我们首先考虑的是整体逻辑的可行性,是否满足业务需求,是否存在逻辑上的漏洞,此时我们不去思考每一步具体如何实现,这样我们大脑就有更多能量去充分思考:

func doSomething(arg int) {
	doStep1()
	if arg > 100 {
		doStep2()
		return
	}
	doStep3()
}
// 具体逻辑先不考虑如何实现
func doStep1() {}
func doStep2() {}
func doStep3() {}

同时,通过抽象的编码形式,我们的代码逻辑层次更加清晰,这样针对性的单元测试更容易编写,这对复杂逻辑编码是非常有用的。在我的另一篇文章中就有过类似的说明 单元测试理论及实践

逻辑抽象

开发中另一个需要训练的就是逻辑抽象能力,我相信一个具象的逻辑功能思考清楚之后,你就可以实现它。但此时你应该停下来思考一下,你的逻辑是否可以抽象出接口,是否与系统中其它功能具有共性,通过提供共性,简化上层逻辑的同时也增加了系统的扩展性

比如io包中的Reader,它就是一个高度抽象的接口:

type Reader interface {
	Read(p []byte) (n int, err error)
}

在下面的方法中,我们没有依赖具体的实现,而是依赖了io.Reader接口,它的作用就是从任何缓冲中读取出数据。

func readPacket(r io.Reader) ([]byte, error) {
	// 读取4字节
	arr := make([]byte, 4)
	_, err := r.Read(arr)
	if err != nil {
		return nil, err
	}
	size := binary.BigEndian.Uint32(arr)

	// 读取固定长度的数据
	data := make([]byte, size)
	_, err = r.Read(data)
	if err != nil {
		return nil, err
	}
	return data, nil
}

因此,在上层可能的调用逻辑就非常简单,可以是任何实现了这个方法的对象,比如:

  1. net.Conn socket连接
  2. os.File 打开的文件
  3. bytes.NewBuffer([]byte{}) 二进制缓冲

通过抽象,可以很好的复用逻辑,以及依赖最小化。

设计抽象

设计能力就是以最小的代价对系统完成抽象的表达。其中除了编写文档之外,最重要的就是训练作图能力,因为图更加生动好理解,传播能力更强。而不同类型的图(用例图、流程图、时序图、状态图等)就是你从不向的视角对一个对象的描述

这就类似于,你设计一辆汽车时,如果你从正面、侧面、顶面和内部不同的角度来给出一张图的话,可以让其它人更加容易了解你设计的汽车的真实样子。否则你给出的设计反而会让别人生产偏差,也就导致了严重的后果。

在一个软件产品的生命周期过程中,分为多个阶段。

graph TD
立项 --> 需求分析;
需求分析--> 系统设计-->需求分析;
系统设计 --> 开发-->系统设计;
开发 --> 测试 --> 开发;
测试 --> 验收 --> 开发;
验收 --> 上线;

在这个实施的过程中,涉及到很多个角色:经理、产品、UI、开发、测试等。通过他们的沟通与分工来完成一个产品从无到有的过程。而在沟通过程中达成语言上一致是相对容易的,但是在逻辑层达成共识是困难的,也就是看似说明白了,实现上每个人的理解不同。于是就会导致结果与期望的不一致,而这里的代价往往是很大的。而解决方法就是通过抽象化每个阶段的核心内容,并给出一个明确的定义,最后通过沟通和评审来达到逻辑层的共识

角色定义
产品界面原型、需求文档
技术管理架构图、系统设计文档等
研发流程图、时序图、状态图、接口文档等
测试测试用例文档

因此,设计抽象能力也将是你必须要学习的核心技能!

感谢观看到最后,如果对你有一点帮助,请不要吝啬你的点赞,感谢!