前言
软件开发工作无论是从宏观还是微观上看,都可以看作一个问题解决的过程。从宏观上看,软件开发,简单来说,就是弄清楚客户的需求是什么,然后通过分析、设计、编码和测试等一系列活动解决如何将需求转换为代码的问题。从微观上看,开发人员的日常工作中也面临各式各样的问题。比如,用于调试代码的Web服务器突然启动不了,开发人员必须先解决这个问题,否则手头上的工作可能无法进展。
作为开发人员,与其抱怨加班,不如去反思下自己的时间都去哪里了。我相信开发人员的大部分时间都花在解决各种各样的问题上了。不管是资深的开发者、还是新手,在日常的工作中都会遇到各式各样的问题。所不同的是,资深开发者可以在几秒内解决的问题,新手却可能要花上几个小时,甚至一两天的时间!可见,提高开发者的问题解决能力,无论对于个人还是对于团队,都有着重要的意义。
其实,心理学作为一门独立的学科,对于问题解决有其专门的研究。其研究成果值得我们借鉴,以提高我们自身以及团队中的其它成员的问题解决能力。本文将为读者介绍心理学关于问题解决方面的知识,并结合软件开发工作的特点给出提高问题解决能力的相关指导意见。没有心理学背景的读者,也不必担心“隔行如隔山”,本文所涉及到的一些心理学术语,大多都是浅显易懂的。
重新审视什么是“问题”
提高问题解决能力,首先要弄清楚究竟什么是“问题”,然后才能谈如何更有效率地去解决问题。
心理学将“问题”定义为“给定信息和目标之间有某些障碍需要被克服的刺激情境”。通俗的理解就是,对于给定的事物的初始状态(所谓“给定信息”)和目标状态,我们不清楚如何将初始状态转换为目标状态(所谓“障碍”),“问题”就产生了。例如,著名的梵诺塔问题,其初始状态是64个盘子在A杆,目标状态是所有盘子在C杆,并且每个小盘都在大盘之上。所存在的需要被克服的“障碍”就是如何将64个盘子从A处移动到C杆。
图 1. 梵诺塔问题
按照上述定义,解决问题就是克服“障碍”的过程,即寻找到一条从初始状态通往目标状态的通路的过程。如梵诺塔问题中,我们反复借助B杆,最终将A杆上的所有盘子“原封不动”地移动到C杆的过程就是问题解决的过程。
那么,提高问题解决的能力就是提高我们找到一条从初始状态通往目标状态的路径的能力。
为了下文讨论方便,这里简单地将软件开发领域的“问题”划分为界定清晰的问题(Well-defined problem)和界定含糊的问题(Ill-defined problem)。前者指初始状态和目标状态都很清楚的问题,如梵诺塔问题。后者指初始状态、目标状态或者二者都很模糊的问题,这类问题往往更难解决,对问题解决者的要求也更高。与软件运维有关的问题多属于这类问题。比如这样一个问题:某个生产环境上的数据库系统自动重启,需要查明其原因。
解决问题的心理过程
就像了解计算机处理信息的原理有助于我们更好地使用计算机,了解人类解决问题的过程有助于我们更好地解决问题。
心理学家一般把问题解决的过程分解为问题表征、设计解题计划、执行解题计划和监控这四个步骤。
问题表征指明确问题的初始状态、目标状态和允许的操作和必须满足的限制。梵诺塔问题中,问题解决者首先对问题进行表征,即弄清楚:64个盘子在A杆上,小的盘子在大的盘子上面(初始状态)、目标是将这64个盘子移动到C杆上,C杆上的每个盘子仍然保持小盘在上,大盘在下(目标状态)、移动过程中可以借助B杆,但是移动过程中保证小盘始终在大盘上面(允许的操作和必须满足的限制)。
设计解题计划指确定解题的步骤。梵诺塔问题的问题解决者通过比较问题的初始状态和目标状态,准备借助B杆递归地将A杆的所有盘子逐步地移动到C杆,就是设计解题计划。
问题解决者设计好解题计划后,就执行解题计划,并在执行过程中时刻进行自我检查当前的操作是否有助于解决问题、相关操作是否满足问题的限制,即执行监控。如梵诺塔问题的问题解决者在移动盘子过程中要注意小的盘子是否在大的盘子上面,移动盘子的结果是否如事先预期的那样能够使越来越多的盘子放在了C杆上。
下面我们讨论,影响问题解决的心理因素。
影响问题解决的心理因素
问题的表征方式
问题解决的第一个步骤中的问题表征,还可以再分为两个小步骤:问题表层理解和深层理解。
问题表层理解就是将问题用问题解决者自身的语言来描述的过程,这是解决问题的最基础的一步。问题的深层理解是在问题表层理解的基础上,进一步把问题的每一陈述综合成条件和目标的统一体。这一子步骤中,非常重要的一点是区分问题中有关的信息和无关的信息。对于无关的信息,可以忽略之,也可以采用不同的方式去理解和表示之(即表征)。
在问题深层理解的过程中,问题的表征采用的方式不同对问题的解决难度可能有很大的影响。这点,可以从典型的一个问题——和尚上山问题(见左边侧栏)反映出来。
和尚上山问题给人的直觉的反映是似乎不大可能存在这样一个点,因为和尚上下山的速度不一样。然而,当我们发现这个问题可以看作这样一个问题时:两个和尚在同一时间点,沿着同一条山路,一个下山,另一个上山,答案就非常直白:这条山路上必然存在一个点,在某一时刻这两个和尚会相遇。那么,原问题的答案也是肯定的。这个问题的解决中关键的一步是,在对问题进行深层理解的过程中,我们采用与问题表层理解中不同的方式来表征问题:表层理解中问题描述的是同一个和尚上下山,而深层理解时我们发现是否是一个和尚上下山是一个“无关”的信息,我们可以将这个信息理解成两个和尚同时上下山。
下面看一个软件开发中的实际例子:我们要对网页上的一个表示文章关键字列表的字段的值进行合法性校验。校验的规则是该字段的值不能为空,若字段值不为空,则多个关键字间用英文分号分隔。例如:“keyword1;keyword2;keyword3”。显然,这个可以用正则表达式来校验。问题就转化为这个正则表达怎么写。按照问题的表层理解(如上面文字的描述),关键字列表的字段值的格式会被表征为:
(关键字1)+;+(关键字2)+;+(关键字3)+…
这样的表征固然直白简单,但依照这个表征,相应的校验正则表达式不是那么容易写。相反,如果把字段值的格式换作另外一种表征,相应的正则表达式就容易写得多:
(关键字1)+(;关键字2)+(;关键字3)+ …
依照上述表征(即从第二个关键字开始,每个关键字都需要以”;”为前缀),可以得出相应的正则表达式(Javascript语言表述)为:“^[^;]*(;[^;]+)*$”。
因此,当我们在解决问题,尤其是一些比较困难的问题时,若没有什么进展,而又没有什么新的思路时,不妨回到问题的原点,重新去表征问题,换一种新的方式去表征问题。或许,这个时候就会豁然开朗。这就好比我们在侦探题材的影视作品中经常看到的情景:侦探在查案过程中,费了许多人力和时间案情都没有什么进展,这个时候要突破困境的一个好的方法是从“零”开始:重新回到案发现场,重新去寻找蛛丝马迹,重新进行推敲。这个时候,案情往往就柳暗花明了!
问题的表征充分程度
若我有一小时的时间来拯救世界,我会花59分钟来定义这个问题,并花一分钟的时间来寻找解决方案(If I had an hour to save the world, I would spend 59 minutes defining the problem and one minute finding solutions––– Albert Einstein)。
心理学研究表明,在解决常规问题时,专家比新手快得多。而在解决困难问题时,专家用于表征问题的时间比新手要长一些,他们会用更多的时间去收集问题的相关信息,因而对问题的表征更加充分。
有这样一个个案。运维人员报告某个生产环境的进程数过多,向研发人员求助定位该问题。而对方所提供的信息仅仅是说“主机上的进程数过多”,附带一款监控软件所报的告警信息:“XXX主机上的进程数超过260”。
该问题的解决过程是:首先,弄清所谓“进程数过多”,具体是什么意思。结合监控软件的告警信息,可以回答该疑问:所谓进程数过多,是指主机上所启动的进程数大于监控软件所预设的进程数量(如260)。此时,问题似乎明朗了:找出260个进程之外的进程是哪些,问题应该就能解决。但这也存在一个问题,假设进行问题定位的时候,该主机的进程数是265个,这其中的每个进程对我们来说都是没有差别的,我们又如何将这些进程区分为两部分呢?进一步向对方询问得知,问题所涉及的主机系一个集群环境(共几十台主机)中的一台,而经过确认其它主机上并没有出现该问题。那么,通过比较该主机上的进程名称列表和集群环境中另外一台主机的进程名称列表,可以发现出现问题的主机“多出”了哪些进程。最后发现,该问题系运维人员定制了一个定时任务,该定时任务调用的Shell脚本重复运行(前一次脚本运行对应的进程未结束,新的脚本运行又开始了),从而导致进程数越来越多。
当笔者将上述问题写为问题定位案例给新手进行定位时,新手的反应是懵了,不知从何下手。
正如上述个案所展示的,软件行业中遇到的问题多数是定义模糊的问题,尤其是一些生产环境中出现的问题。对于这样的问题,专家能够通过自己的分析判断、进一步收集与问题有关的信息,使问题逐步转化为定义良好的问题,再通过适当的问题解决策略(如上述的比较法),从而解决问题。而新手往往不知所措。
因此,对于定义模糊的问题,其解决思路大体上是试图将其转化为定义良好的问题,途径是通过分析判断,收集有关问题的更多信息。而对于新手,平时通过观察专家解决问题的过程,并试图模仿之,也是一个提高解决问题能力的方法。
观察能力
一切推理都应该从观察和实验中得来。
––– 伽利略
在解决软件行业的问题过程中,视觉是人脑获取信息的主要途径。解决问题的过程中,人脑并不是被动地接受视觉信息,而是通过有意识的、带有目的性的主动观察获取信息。另外,软件开发过程中遇到的问题多数是界定含糊的问题,通过观察获得有关问题的更多信息有助于对问题进行充分的表征。因此,观察能力在解决问题的过程中显得非常重要。在我们的日常工作中也不难发现一点:专家在解决问题过程往往能够从一堆视觉信息中快速捕捉到其所需的关键信息,而新手面对专家所赖以解决问题的信息时却往往视若无睹!
例如,如图2所示的一个几十行的Call Stack信息中,专家可以快速地定位到第35行这行关键信息,从而断定问题系磁盘空间不足所致,而新手则可能不知从何下手。
图 2. 从错误信息中快速定位关键信息
日志文件、软件界面等所呈现的错误信息是问题定位的一个重要信息来源。但是经验告诉我们,“二八原则”在此也是适用的:这些错误信息中的大部分对于解决问题来说是无用或者用处不大的,而那些对问题的定位和解决能够起到决定性作用的关键信息往往就那么几行甚至一行。因此,能否在这些大量的错误信息快速找出那些我们需要的关键信息,往往决定了问题解决的效率。
快速找到我们所需的关键信息,需要问题定位者的拥有敏锐的观察能力。提高观察能力,首先需要意识到观察能力的重要性。其次,在日常工作中逐步地学会区分自己在问题定位过程中所遇到的错误信息,哪些是关键的,哪些是帮助不大的。再次,掌握一些获取关键信息的基本技能。例如,对于与数据库有关的错误信息,要能够重点关注数据库系统所报的错误码。对于Java Call Stack信息,重点关注“Caused by”部分的头几行。
笔者曾经通过引导组员意识到其观察能力的薄弱和观察能力的重要性,并通过实际的问题定位向其展示如何快速获取关键信息,帮助了组员一定程度上提高了观察能力。
小结
本篇介绍了问题解决的心理过程以及问题表征阶段影响问题解决的一些心理因素。并结合笔者实际经历的例子通过比较专家与新手在解决问题时表现出的差异给出提高问题定位与解决能力的指导意见。下篇将介绍影响问题解决的其它心理因素,并给出相关指导意见。