[思考] 难的问题到底难在哪儿

Table of Contents

前言

什么是问题规模?

什么是抽象程度?

解决困难问题的共通方法


前言

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

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

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

为什么这么说呢?前面三点很好理解没有太大争议,值得展开的是第四点。

什么是问题规模?

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

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

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

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

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

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

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

什么是抽象程度?

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

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

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

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

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

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

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

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

解决困难问题的共通方法

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

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

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

再举一例,有一位知名考研数学老师在讲泰勒公式时有一个经典的讲解方法。这个问题不细讲,大致说一下就是在高等数学里有一个等价无穷小公式:当x趋近于0时,x-sinx等价于(x^3)/6,注意这是一个公式。而出题人出题时必然不会直接给一个公式让我们求,他可能会把x换成任何东西,换言之,真正的x可能比这里公式的x看起来复杂。这位老师身经百战,经验丰富,他一下就识破了出题人的意图,于是就把这x当成了一个整体,说出了一个非常有意思的公式:狗-sin狗 等价于 (狗^3)/6.

现在,我们再看看这个讲法,这不就是把’狗‘这个东西来当作了一个对象吗?这个对象代表的就是一个抽象而已。因此,这不也就是面向对象里面的一个对象吗?没有任何区别啊。x不就是一个代指吗,它可能不是一个数,它可能是任何一个对象。这位老师的讲法事实上就是面向对象思想的一个经典应用。并且,这样的思想在数学上甚至在其他任何学科上,都是无处不在也一直在发挥着它得魔力,当然也包括我们现在讲的软件的世界。只是很多人并没有意识到他们用的这种思想本质上到底是一种什么样的思想。而现在,我们应该渐渐明白了。

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

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

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

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

(本篇完)

 

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 JavaScript 编写的简单俄罗斯方块游戏(附源代码) 项目:使用 JavaScript 编写的简单俄罗斯方块游戏(附源代码) 该游戏是一个使用 HTML5 和 JavaScript 开发的简单项目。这款游戏允许玩家策略性地旋转下落的方块以清除关卡。要在此游戏中得分,您必须通过操纵方块来清除线条,使它们填满水平行。当方块掉落时,您必须 根据需要移动 和旋转它们,使它们均匀地排列在底部。 游戏制作 该游戏仅使用 HTML、CSS 和 JavaScript。谈到这款游戏的功能,这款游戏的 PC 控制也很简单。首先,您必须按空格键才能开始游戏。您可以使用箭头键来更改下落方块的位置。您可以在侧栏看到形成的分数和行。 该游戏包含大量的 javascript,用于对游戏的某些部分进行验证。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox, 以获得更好、更优化的游戏体验。要玩游戏,首先,单击 index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值