思维能力:抽象思维

我们工程师每天都要动用抽象思维,对问题进行分析,归纳,综合,判断,推理。从而抽象出各种概念,所以我们大部分时间并不是写代码,而是在梳理需求,理清概念,当然也包括尝试看懂哪些该死的别人的代码。

什么事抽象

百度百科

抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。具体地说,抽象就是人们在实践的基础上,对于丰富的感性材料通过去粗取精、去伪存真、由此及彼、由表及里的加工制作,形成概念、判断、推理等思维形式,以反映事物的本质和规律的方法。
实际上,抽象是与具体相对应的概念,具体是事物的多种属性的总和,因而抽象亦可理解为由具体事物的多种属性中舍弃了若干属性而固定了另一些属性的思维活动。

Wikipedia的解释是:

抽象是指为了某种目的,对一个概念或一种现象包含的信息进行过滤,移除不相关的信息,只保留与某种最终目的相关的信息。例如,一个皮质的足球,我们可以过滤它的质料等信息,得到更一般性的概念,也就是球。从另外一个角度看,抽象就是简化事物,抓住事物本质的过程

简单而言抽象过程就是从具象的事物中归纳出共同的特征“抽取到一般化过程中”
为了更方便理解抽象,看毕加索的画

思维能力:抽象思维

从这个简单的案例中,我们可以到抽象的三个特点:

第一,抽象是忽略细节的。抽象类是最抽象的,忽略的细节也最多,就像抽象牛,只是几根线条而已。在代码中,这种抽象可以是Abstract Class,也可以是Interface。

第二,抽象代表了共同性质。类(Class)代表了一组实例(Instance)的共同性质,抽象类(Abstract Class)代表了一组类的共同性质。对于我们上面的案例来说,这些共同性质就是抽象牛的那几根线条。

第三,抽象具有层次性。抽象层次越高,内涵越小,外延越大,也就是说它的涵义越小,泛化能力越强。比如,牛就要比水牛更抽象,因为它可以表达所有的牛,水牛只是牛的一个种类(Class)。

抽象的这种层次性,是除了抽象概念之外,另一个我们必须要深入理解的概念,因为小到一个方法要怎么写,大到 一个系统要如何架构,以及我们后面第三章要介绍的结构化思维,都离不开抽象层次的概念。

在进一步介绍抽象层次之前,我们先来理解一下外延和内涵的意思:

抽象是以概念(词语)来反映现实的过程,每一个概念都有一定的外延和内涵.概念的外延就是适合这个概念的一切对象的范围,而概念的内涵就是这个概念所反映的对象的本质属性的总和.例如“平行四边形”这个概念,它的外延包含着一切正方形、菱形、矩形以及一般的平行四边形,而它的内涵包含着一切平行四边形所共有的“有四条边,两组对边互相平行”这两个本质属性。

所谓的抽象层次就体现在概念的外延和内涵上,这种层次性,基本可以体现在任何事物上,比如一份报纸就存在多个层次上的抽象,“出版品”最抽象,其内涵最小,但外延最大,“出版品”可以是报纸也可以是期刊杂志等。

一个出版品

一份报纸

《旧金山纪事报》

5 月 18 日的《旧金山纪事报》

当我要统计美国有多少个出版品,那么就要用到最上面第一层“出版品”的抽象,如果我要查询旧金山5月18日当天的新闻,就要用到最下面第四层的抽象。

每一个抽象层次都有它的用途,对于我们工程师来说,如何拿捏这个抽象层次是对我们设计能力的考验,抽象层次太高和太低都不行。

比如,现在要写一个水果程序,我们需要对水果进行抽象,因为水果里面有红色的苹果,我们当然可以建一个RedApple的类,但是这个抽象层次有点低,只能用来表达“红色的苹果”。来一个绿色的苹果,你还得新建一个GreenApple类。

为了提升抽象层次,我们可以把RedApple类改成Apple类,让颜色变成Apple的属性,这样红色和绿色的苹果就都能表达了。再继续往上抽象,我们还可以得到水果类、植物类等。再往上抽象就是生物、物质了。

你可以看到,抽象层次越高,内涵越小,外延越大,泛化能力越强。然而,其代价就是业务语义表达能力越弱。

思维能力:抽象思维

编程语言的发展史也是一个典型的分层抽象的演化史。

机器能理解的只有机器语言,即各种二进制的01指令。如果我们采用O1的输入方式,其编程效率极低(学过数字电路的同学,体会下用开关实现加减法)。所以我们用汇编语言抽象了二进制指令。然而汇编还是很底层,于是我们用C语言抽象了汇编语言。而高级语言Java是类似于C这样低级语言的进一步抽象,这种逐层抽象极大的提升了我们的编程效率。

思维能力:抽象思维

简单的重构无外乎就是把这段代码提取出来,放到一个Util类里面给大家复用。然而我认为这样的重构只是完成了工作的一半,我们只是做了简单的归类,并没有做抽象提炼。

简单分析,不难发现,此处我们是缺失了两个概念:一个是用来表达搜索条件的类——SearchCondition;另一个是用来组装搜索条件的类——SearchConditionAssembler。只有配合命名,显性化的将这两个概念表达出来,才是一个完整的重构。

重构后,搜索条件的组装会变成一种非常简洁的形式,几十处的复用只需要引用SearchConditionAssembler就好了。

由此可见,提取重复代码只是我们重构工作的第一步。对重复代码进行概念抽象,寻找有意义的命名才是我们工作的重点。

因此,每一次遇到重复代码的时候,你都应该感到兴奋,想着,这是一次锻炼抽象能力的绝佳机会,当然,测试代码除外。

强制类型转换是抽象层次有问题

面向对象设计里面有一个著名的SOLID原则是由Bob大叔(Robert Martin)提出来的,其中的L代表LSP,就是Liskov Substitution Principle(里氏替换原则

简单来说,里氏替换原则就是子类应该可以替换任何父类能够出现的地方,并且经过替换以后,代码还能正常工作。

思考一下,我们在写代码的过程中,什么时候会用到强制类型转换呢然是LSP不能被满足的时候,也就是说子类的方法超出了父类的类型定义范围,为了能使用到子类的方法,只能使用类型强制转换将类型转成子类类型。

举个例子
在苹果(Apple)类上,有一个isSweet()方法是用来判断水果甜不甜的;西瓜(Watermelon)类上,有一个isJuicy()是来判断水分是否充足的;同时,它们都共同继承一个水果(Fruit)类

代码

因为pick方法的入参的类型是Fruit,所以为了获得Apple和Watermelon上的特有方法,我们不得不使用isMemberOfClass做一个类型判断。然后使用强制类型转换转成子类类型,以便获得他们的专有方法,很显然,这是违背了里式替换原则的。

这里问题出在哪里于这样的代码我们要如何去优化呢细分析一下,我们可以发现,根本原因是因为isSweet和isJuicy的抽象层次不够,站在更高抽象层次也就是Fruit的视角看,我们挑选的就是可口的水果,只是具体到苹果我们看甜度,具体到西瓜我们看水分而已。

因此,解决方法就是对isSweet和isJuicy进行抽象,并提升一个层次,在Fruit上创建一个isTasty()的抽象方法,然后让苹果和西瓜类分别去实现这个抽象方法就好了。

思维能力:抽象思维

重构之后的代码

通过抽象层次的提升我们消除了isMemberOfClass 和强制类型的转换,让代码重新满足了里式替换原则。抽象层次的提升让代码更加优雅了。

所以,每当我们在程序中准备使用isMemberOfClass做类型判断,或者做强制类型转换的时候。每当我们的程序不满足LSP的时候。你都应该警醒一下,好家伙,这又是一次锻炼抽象能力的绝佳机会。

如何提升抽象思维能力

抽象思维能力是我们人类特有的、与生俱来的能力,除了上面说的在编码过程中可以锻炼抽象能力之外,我们还可以通过一些其他的练习,不断的提升我们的抽象能力。

多阅读

为什么阅读书籍比看电视更好呢为图像比文字更加具象,阅读的过程可以锻炼我们的抽象能力、想象能力,而看画面的时候会将你的大脑铺满,较少需要抽象和想象。

这也是为什么我们不提倡让小孩子过多的暴露在电视或手机屏幕前的原因,因为这样不利于他抽象思维的锻炼。

抽象思维的差别让孩子们的学习成绩从初中开始分化,许多不能适应这种抽象层面训练的,就去读技校了,因为技校比大学会更加具象:车铣刨磨、零部件都能看得见摸得着。体力劳动要比脑力劳动来的简单。

多总结沉淀

小时候不理解,语文老师为什么总是要求我们总结段落大意、中心思想什么的。现在回想起来,这种思维训练在基础教育中是非常必要的,其实质就是帮助学生提升抽象思维能力。

记录也是很好的总结习惯。就拿读书笔记来说,最好不要原文摘录书中的内容,而是要用自己的话总结归纳书中的内容,这样不仅可以加深理解,而且还可以提升自己的抽象思维能力。

我开始系统的记录笔记,做总结沉淀,构建自己的知识体系。

命名训练
每一次的变量命名、方法命名、类命名都是一次难得的抽象思维训练机会,前面已经说过了,语言和抽象是一体的,命名的好坏直接反应了我们的问题域思考的是否清晰,反应了我们抽象的是否合理。

现实情况是,我们很多的工程师常常忽略了命名的重要性,只要能实现业务功能,名字从来就不是重点。

实际上,这是对系统的不负责任,也是对自己的不负责任,更是对后期维护系统的人不负责任。写程序和写文章有很大的相似性,本质上都是在用语言阐述一件事情。试想下,如果文章中用的都是些词不达意的句子,这样的文章谁能看得懂,谁又愿意去看呢。

同样,我一直强调代码要显性化的表达业务语义,其中命名在这个过程中扮演了极其重要的角色。为了代码的可读性,为了系统的长期可维护性,为了我们自身抽象思维的训练,我们都不应该放过任何一个带有歧义、表达模糊、意不清的命名。

小结

抽象思维是程序员最重要的思维能力,抽象的过程就是寻找共性、归纳总结、综合分析,提炼出相关概念的过程。

语言和抽象是一体的,抽象思维也叫词思维,因为抽象的概念只能通过语言才能表达出来。

抽象是有层次性的,抽象层次越高,内涵越小,外延越大,扩展性越好;反之,抽象层次越低,内涵越大,外延越小,扩展性越差,但语义表达能力越强。

对抽象层次的拿捏,体现了我们的设计功力,视具体情况而定,抽象层次既不能太高,也不能太低。

重复代码意味着抽象缺失,强制类型转换意味着抽象层次有问题,我们可以利用这些信号来重构代码,让代码重新变的优雅。

来源:Z苗

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年5月22日
下一篇 2021年5月22日

相关推荐