怎么去思考一个问题,提高解决问题的能力_提一个问题,解决一个问题不同觉悟-程序员宅基地

技术标签: 杂七杂八  程序人生  

怎么去思考一个问题,提高解决问题的能力

前言:

#:本文转发自【半路歌雨】
#:http://blog.jboost.cn/think-like-a-programmer.html
#:如有侵权,联系即删

技术人员的价值,不在于你能写出多么优美的代码,也不在于你能设计出一个多么大而全的高屋建瓴的架构,而在于你实实在在的解决问题的能力,在于你使用技术手段服务于业务的能力”。

导入:

先罗列一两个遇到的现象:

某同事汇报,测试提了一个Bug,当某个用户绑定的卡信息超过50个的时候,后台显示数据就会出现混乱,问能不能限制绑定的卡不超过50个。我问:数据显示出现混乱是什么意思?答:不清楚;我再问:为什么超过50个就会混乱了,少于50个有没有可能出现混乱,造成混乱的原因是什么?答:不知道。我说你先去搞清楚什么叫“混乱”,然后再搞清楚为什么会出现“混乱”再来说解决办法。经过与测试人员的一番沟通后,跟我反馈说不是显示混乱,是显示不全,自己通过查看实现是因为在服务端做了字符串拼接,超过多少就被截断了。

某同事在抱怨,这个问题很难复现,我不知道怎么解决,要不要把这块整体优化下算了。我问他你优化的目的是什么,是优化目前实现的流程、结构?还是通过优化来解决这个难以复现的问题?答:来解决这个问题。我说你问题都没定位到,怎么通过优化来解决,不怕老问题没解决,优化出新的问题出来了?

你有没有也曾经说过或听过“这个问题太复杂了, 我解决不了”,“这个功能我没办法实现”,“我也不知道为什么会出现这个问题”之类的话语。

以上的现象与话语,可能都是一个人解决问题的能力或方式方法还不成熟的体现。那么如何来提高解决问题的能力,我想首先需要先从思维方式或思维习惯上寻求改变。在网上看到有这么一篇文章——《How to think like a programmer — lessons in problem solving》(文章地址见文末参考部分),介绍了通过5个步骤来帮忙人们建立高效解决问题的思维框架。本文以这5个步骤为基础,结合自身的理解与体会进行介绍。

一.怎么去看待问题

“这个国家的每个人都应该学计算机编程,因为它会教你如何思考”

像程序员一样思考
像程序员一样思考,到底意味着什么,需要如何来做?
像程序员一样思考本质上来说,是一种更为有效的解决问题的方法。

解决问题的能力是一项元技能
什么叫元技能
类比于元数据——描述数据的数据叫元数据,我理解元技能就是提升技能的技能,就是说当你掌握了解决问题的能力,你就可以通过这种能力去提升其它各项专业技能。

解决问题的能力也是最重要的能力,比精通编程语言,调试能力,以及系统设计能力都更为重要。

提高解决问题能力的方法
我们平时解决问题的方式可能是:

尝试一种解决方案。
如果这种解决方案无效,再尝试另一种方案。
如果还是没有用,重复第二步直到你碰巧把问题解决了。
这种方法被作者 Richard Reis 定义为解决问题最糟糕的方式。因为它不但浪费时间,而且能不能达到目的还得看运气。

一.怎么去解决问题

经过对优秀程序员在编程时的思维框架的分析,作者总结出提高解决问题能力的最好方法包括:

有一个处理问题的框架
按照这个框架反复练习
那么,当你遇到一个新的问题时,该如何来解决?

第一步:理解
遇到问题时,我们应该先要弄明白问题本身。大部分情况下,问题之所以难解决只是因为你没真正理解它们(很多时候是出于沟通的不充分),理解问题是解决问题的第一步。

如何确定自己是否真正理解一个问题?

最有效的方法是,尝试用自己的语言来说出它,看有没有逻辑漏洞。当你能讲清楚一个问题时,说明你理解了它。优秀的程序员编程时,一般都会写下自己遇到的问题,画出流程或序列草图,或同产品经理、其它开发人员、测试人员等一起讨论确认。这个过程,就是在确定自己对问题的理解有没有偏差。

“如果你不能用简单的语言来解释一个事情,那意味着你根本就没有理解它” —— Richard Feynman

面对一个新需求时,你应该了解这个需求产生的场景——什么人,在什么时候通过执行什么操作,来达到什么目的?这个场景及其中的行为逻辑是否合理,设计是否存在漏洞,然后带着问题来与需求提出方讨论确认,而不是断章取义或不经任何思考直接编码开干。不做代码的搬运工,要做有思想的程序员。

同样,面对一个 Bug 时,你应该首先了解这个 Bug 产生的场景——什么人,在什么场景,通过什么操作会产生这个问题?要追本溯源,定位问题的本源在哪里。
我认为定位问题的本源比解决问题更重要!因为你只有正确地找到了问题的症结,才有可能去解决它,而解决办法却可能有多种。且从花费的时间来说,定位问题往往会占整个解决问题时间的一半以上。

如果没有找到问题的本源,只是头痛医头脚痛医脚,那么可能不仅对解决问题无事无补,甚至还可能引进新的问题。常见的头痛医头脚痛医脚的处理方式包括,CPU占用高了,内存溢出了——升级服务器配置(可能过两天又得升级了!);接口超时了——增大超时时间(可能导致用户投诉或其它依赖的服务级联超时),等等。

那么日常工作中,如何来定位问题的根源?对于一般问题来说,可能通过查看日志大致就能找到问题所在,对于比较棘手的问题,针对问题的性质一般可通过如下方法进行定位:

对于易复现的问题: 常用的就是 Debug,通过 IDE 断点来跟踪数据的流转与变更,一个个环节检查数据输入输出是否正确来进行排查。可借助条件断点、异常断点等技巧来提高 Debug 效率。
对于不易复现的问题:可通过对比法——对比其它地方的类似功能或实现,寻找两者之间的差异,差异之处往往就是问题所在;分析法——走读整体流程代码,捋清各个环节的逻辑,分析定位问题;日志法——在各个关键环节添加日志,将场景镜像下来,当下次复现的时候,通过分析日志定位问题。
第二步:计划
理解了问题,接下来就是解决问题的方案。没有明确的方案计划时,不要轻易去着手解决问题,不要寄希望于碰运气蒙混过关。许多开发人员习惯于快速扫一眼需求,就打开 IDE 开始垒代码,垒完发现要么与需求不符,要么漏洞百出。

nobug

制定计划,就是制定解决问题的战略步骤。

不论面对需求还是 Bug,都应该好好计划你的解决方案。设计好解决方案中的各个环节,如业务需求的数据表设计、接口设计、流程逻辑,Bug 修复的具体实施步骤。并给自己一点时间思考与预演,该解决方案可能存在的漏洞与影响有哪些,除了这样处理,还有没有另外更好的解决方案。

在没有想清楚解决方案时,不要直接上来就撸代码,暂停一下,给你的大脑一些分析问题和处理信息的时间。

第三步:分解
这是思维框架中最重要的一步。

分解,就是化繁为简,就是我们常说的分治思想,拆分法——将大问题拆分为若干个小问题,然后逐个击破各个小问题,再合并总结。微服务架构,MapReduce 算法,都是这一思维(或思想)的体现。

不要尝试一次解决一个复杂的大问题,而应把复杂的大问题分解成若干个简单的小问题(或子问题),从最简单的子问题开始(最简单意味着你知道怎么解决它或它更容易被解决,也或者这个子问题的解决不需要依赖于其它子问题),一个一个逐步解决。一旦你解决了所有的子问题,把它们串联起来,一般就意味着你解决了之前的那个复杂的大问题。

分解问题的能力是解决问题的基石。这也是优秀的程序员在编程中最常用到的技能,对于他们来说,分解问题的能力,要比编程语言的熟练度、系统设计等技术更为重要。

第四步:卡壳了怎么办?
当你理解了问题,做出了解决方案的计划,将复杂问题分解为子问题后,在处理子问题时依然卡壳了怎么办?

首先,淡定!然后告诉自己,这很正常,每个人都会遇到。

优秀程序员或解决问题的高手,与普通人之间的差别就在于,他们对问题更有求知欲,更有耐心,他们的注意力更多地是在如何解决问题上,而不是为此恼火或甩锅发牢骚。

当遇到卡壳的情况时,可以试试这几种方法:

Debug:与前面定位问题一样,一步一步调试,直到找出究竟哪里出错了。
“Debug 的艺术关键在于你究竟让软件干了些啥,而不是你以为你让软件干了些啥。”—— Andrew Singer

重新评估问题:退回去,从另一个角度重新审视问题,别让自己迷失在细节里,有时候我们容易迷失在具体的细节中而忽略了更一般的原则。重新评估问题的另一种途径是推倒重来,可以删除(回滚)所有已做的事,重新开始,有时这是非常行之有效的方式。

搜索解决方案:利用搜索引擎找到类似问题的解决办法,向他们学习。使用搜索引擎需要学会提炼关键字,关键字越有代表性,越容易找到答案。对搜索结果应该抱着参考的态度,而不是照搬,要明白为什么如此这般处理就能解决问题,并在解决问题后能依次延伸了解其上下游或相关知识,比如SQL查询慢,发现是索引未生效,则可以延伸了解都有哪些场景会导致索引失效;比如并发问题,则可以依此了解如何保证线程安全,同步机制,锁机制等相关知识。事实上,即使问题已经解决,你也可以经常这么做,因为这样你可以从其他人的解决方案中及上下游知识中学到更多。

寻求支援:当通过以上方法都无法获得解决办法时,向你的同事、上级或朋友求援,如果是开源项目,到开源社区、技术群,或 github 的 issue 列表中发帖求援。

记录问题与解决方案:将你本次遇到的问题与最终的解决方案用(电子)笔记本记录下来,便于后面回顾或参考。

第五步:练习
罗马不是一天建成的,你也不可能期盼通过解决一两个问题就能成为解决问题的高手。但是,如果你能以学习的态度来寻求问题的解决办法,通过以上四个步骤来建立一套解决问题的思维框架,每一个问题的处理都是提高你能力的机会。那么距离成为一个解决问题的高手,就只差一步了,那就是:练习,练习,再练习。在问题中练习,训练你的思维方式与习惯。

“我不害怕一次练习1000个踢打动作的人,但我害怕将一个踢打动作练习1000次的人”

总结
其实,解决问题的能力,不论在IT技术领域,还是在其它各个领域,都是一种最基本的技能。当你在说出“这个问题我解决不了”,“这个问题我没办法定位”前,试试本文介绍的理解、计划、分解、卡壳时怎么处理的建议方法,多一些耐心,一步步实践,说不定慢慢就看到曙光了。按照这个处理模式或习惯,在日积月累的问题处理中,你可能已在不知不觉成为了解决问题的高手。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_26129413/article/details/110138344

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文