难的问题到底难在哪儿

版权声明:未经博主同意,谢绝转载!(请尊重原创,感谢) https://blog.csdn.net/topdeveloperr/article/details/86302229

Table of Contents

前言

什么是问题规模?

什么是抽象程度?

解决困难问题的共通方法


前言

为什么会有动机写这样一篇文章,是因为在我们的每一天的开发工作,学习当中,总是会层出不穷,永无尽头的遇见各种各样的问题,从上学开始面对一道又一道考试题目,到后来工作中面临一个又一个bug或者功能需求,到生活当中需要处理一个又一个的事情。我们不停的解决问题,不停遇到新的问题,甚至可以说每个人的一生不过都是类似如此的一个循环。

有的问题我们轻而易举就可以解决,有的问题我们努力一点可以解决,有的问题我们拼尽全力才能解决。笔者在自己的观察和对自己的经历的反思当中也渐渐的发现了很多有意思的事情,或者说规律。

  1. 不同的人在面对相同的问题时的解决能力是不一样的,甚至是千差万别的,因此同一个问题有人会说难,有人会说不难,这非常正常。明白这一点的人就不会去取笑比他笨的人或是一个不如他的人。
  2. 一个人解决问题的能力主要来自于三个方面:先天智力/体力条件,知识水平(包括分析问题的能力和借助工具帮助的能力),自信心。
  3. 人的自信心会在不停的解决问题,或者说完成事情当中积累,也可能因为一些失败受到影响,自信心是动态的这和马太效应是一脉相承的,不停解决各种问题的人,自信心会逐渐的变得更强,这也反过来帮助他在之后遇到问题时能表现的更加好。
  4. 抛开人的因素不看,那么一个难的问题到底难在哪儿?主要就是两个方面:一是问题的规模,二是这个问题涉及的抽象程度。这一点可以说放之四海皆准,在任何行业,任何场景都适用。

前面三点很好理解,值得展开的是第四点。

什么是问题规模?

问题规模就是指的问题的大小。举例说明:

一道难的数学题:计算量往往是很大的。注意这里的计算量理解的不应该太死板。也许数学题答案最后写出来也许几步但是草稿纸必然不止几步,草稿纸用的少,大脑里做的计算也绝对不会少。

一篇很难的英语阅读:句子往往是很长,文章也不可能只有几句话。

一个很难实现的功能:所需要的代码量肯定是不小的,注意直接调用写好的方法不算代码量小。例如java常用的类HashMap仅仅这一个类的代码就超过2000行,这还不算它所用到的依赖的其他地方的代码。

还有一些例子并不是一个具体的问题,而是一个具体的实物。

一台汽车,或者说生产一台汽车:任何一台汽车,组成他的零部件都上万个,不说生产,光是把这些零部件拼在一起,这就是一个巨量的工程。生产其他机器同理,如飞机,电脑等。我们要知道,在古代的皇帝也不过只能坐轿子。

上面这些问题都是非常难的问题,他们的问题规模也都很大。

什么是抽象程度?

抽象在科学里的定义是:从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃,这种思维过程,称为抽象。

在计算机的世界当中,抽象是我们用来简化复杂的现实问题的途径。

所谓抽象程度,笔者的总结是指一个问题抽象之后是否能被我们理解,从另一个角度来说就是当我们要描述这个抽象的问题时,是否容易给别人描述清楚,假设表达能力正常,则越难描述清楚抽象程度越高,越容易描述清楚则抽象程度越低。

这里有一个非常有意思的现象,就是抽象程度是会动态变化的,因为抽象程度本质是一个相对于人的理解的概念,当人们对一个专业的术语或是代号,公式,都公认且应用熟练之后,这个抽象对于他们来说将变得非常容易理解。一个比较常见的例子是,在一个行业的人如果去另外一个行业体验的话,一定会遇到很多这个行业的特定代指某一事物的一些称呼,这些代号在一开始肯定是听不懂的,但是假以时日,我们就能马上get到它的意思了。

再比如未知数这样一个概念,我们在上学时都有学习过设未知数x来解决问题的经历,那么在没有引入未知数这个概念时,我们解决问题的思路都是从已知的出发去算。突然有一天有人告诉你我们可以把不知道的设为x。但是对于一个上小学或者中学的学生来说,他在第一次看到这个x的时候一定是很难理解的,这个x本质上就是对未知数的一个抽象。

但是,我们的生活当中以及后来的学习当中,要求的答案并不都是一个数字,因此那个x所代表的抽象并不都全是数字,x所代表的抽象我们越难以理解,那么我们要求这个x也就越难。现在,我想假设人生的意义为x,然后我的问题是,那么人生的意义是什么呢?

再举一个编程时的例子,在我们测试我们编写的程序时,或者在工作当中,有时候会遇到一些很难解决的bug,这些bug假如是第一次遇到的话,我们往往会无从下手,因为我们不能并理解这个错误的意思,因此要修复就没那么容易。而当我们通过查阅资料,更改代码,再结合自己的知识解决了问题之后,当下一次遇到这样的问题时,我们就能渐渐的‘猜’出可能是哪里出错了。这个过程可以说就是一个bug的抽象程度在相对我们的理解能力提高而降低的一个过程。

我们可以简单把问题抽象程度理解为这个问题是否容易理解的程度。

解决困难问题的共通方法

认识了一个难得问题难在哪儿,以及难题的规律之后,对我们解决这些问题就会大有裨益。这里要引入程序员最熟悉不过的面向对象,不过这里只谈思想不谈具体编码。同时在这里推荐一本书《面向对象分析与设计》。这本书最重要的内容就是讲了面向对象思想如何帮助我们认识了这个复杂的世界,和本文的主题一脉相承。

首先,面向对象思想的三大特点:封装,继承,多态。在这里博主认为可以加上抽象,但是抽象和封装以及继承都有一些重叠的地方,我们之后再来谈这一点。它们的定义如下:

封装: 在软件世界当中它指的是:把数据和对数据进行的操作封装在一起,数据被保存在内部,程序的其他部分只有通过被授权的操作(成员方法)才能对数据进行操作。事实上我们完全可以跳出软件的范围来看封装的概念。举例说明,在你驾驶汽车的时候,你只需要点火,踩油门,转方向盘等操作,你曾经去关心过汽车内部这些操作是如何实现的吗?一般情况下我们不会这样做,而是直接去进行这些操作,也就是调用汽车提供的方法。

继承:在软件当中的定义是: 当多个类存在相同的属性和方法时,可以从这些类中抽象出一个父类,在父类中定义这些相同的属性和方法,所有的子类只需要通过extend来声明继承父类就可以获得这些共同属性。事实上面向对象的理论往往第一句话就是:everything is an object. 因此这里虽然表述的是类,但我们同样可以把这个概念应用于生活中的几乎任何场景。还是以汽车为例,丰田卡罗拉的同一型号的不同款式汽车,在生产时,大部分的架构必然是采用同一个生产线,只是有一些不同型号的配置,他们可以根据自己的特点进行改变或者添加。

多态:在软件当中:通过指向父类的指针,来调用在不同子类中实现的方法。这个概念貌似只是一个纯软件概念。但是依然来源于生活,还是以驾驶汽车为例,当我们学驾驶技术的时候,即调用汽车的,转方向盘,踩油门,打灯等方法时,我们学的是通用的方法,并不会因为换了一辆汽车,学的这些驾驶技术就需要重新学。

在上面的描述当中,我们已经提到了抽象,正如上文所说,抽象蕴含在了封装,继承,多态当中。将事物的一些特性封装在一起,这就是一个抽象的过程。将类的共同属性和方法提取到父类当中,这也是一个抽象的过程。

因此,我们在看待生活中的事物,以及一些所谓的难题之时,可以按照这样的思路去抽丝剥茧,这样一个再难的问题也会变为可以理解的,可以被实现的。但有一点不得不提的时,随着抽象层次的复杂,问题量的变大,有的东西相对于一个人的脑力来说的确会显得十分复杂,我们也很难去做到面面俱到的了解。例如,一个大型银行的所有业务系统。但是,必须指出的是做到面面俱到的了解往往是无意义的。对我们来说,掌握这样的方法和理论,帮助我们构建这样的复杂系统,以及分析其中的问题,才是我们应该去做和值得去做的事情。

猜你喜欢

转载自blog.csdn.net/topdeveloperr/article/details/86302229
今日推荐