什么是你解决(编程)问题的Modus操作手册?

在解决任何编程问题时,你的操作方法是什么? 你如何解决一个问题?
你能写出关于错误或问题的可观察行为的一切吗?

带我通过你采取的行动的心理清单。

(正如他们所说 – First, solve the problem. Then, write the code

离开电脑 ,如果你愿意,可以拿一些纸和一支钢笔或铅笔。

如果我在计算机周围,那么我尝试编写一个解决scheme,然后通常不正确或只是废话。 笔和纸迫使我多思考一下。

首先,我去一家自行车店 ; 或另一个 。

一旦我发现没有人发明那种特殊的自行车,

  • 找出适当的数据结构的领域和问题,然后映射所需的algorithm来处理这些数据结构以您需要的方式。

  • 分而治之。 解决问题的子集

这个algorithm从来没有让我失望:

  1. 采取行动。 经常坐在那里,被这个问题吓坏了,不会帮助解决这个问题。 而且,往往没有多less思考就能解决问题。 所以你必须把你的手弄脏,并解决头部问题。

  2. testing。 在什么条件下,input值或状态,是否会发生问题? 做一个心理模型,说明为什么这些特定的条件可能会导致问题。 检查不会导致问题的类似情况。 testing一下,以便对问题有清晰的认识。

  3. 可视化。 把debugging代码,转储variables的内容,单步代码。 在问题条件下,做任何能够明确说明发生了什么的事情。

  4. 简化。 删除或注释代码,将值戳入variables,运行具有特定值的特定函数。 尽你所能,通过削减那些与手头问题无关的东西来解决问题。 将代码复制到一个单独的项目中,并运行它(如果必须的话)以删除依赖项。

  5. 接受。 一个伟大的人说:“无论如何,不​​pipe不可能,一定是真相”。 换句话说,在尽可能地简化之后,无论起初看起来多么奇怪,什么都留下来一定是问题。

  6. 逻辑。 双重,三重检查问题的逻辑。 是否有意义? 为了有意义,什么是真实的? 有什么你失踪? 你对algorithm的理解错了吗? 如果一切都失败了,重新devise这个问题。

作为步骤3的附加,作为最后的手段,我经常使用寻找任性代码的二分查找方法。 只需评论一半的代码,看看问题是否消失。 如果是的话,那一定是在那一半(反之亦然)。 其余一半的代码继续。

  • Google非常适合寻找错误消息和常见问题。 在某个地方,有人经常遇到你的问题,并find了解决办法。

  • 铅笔和纸。 伪代码和工作stream程图。

  • 与其他开发者讨论这个问题。 当你不得不强迫自己简化别人理解的问题时,这真的很有帮助。 他们也可能有另一个angular度。 有时很难通过树木看到森林。

  • 出去走走。 把你的头摆脱这个问题。 退一步,试图看到你想要实现的大局。 确保你正在“试图”解决的问题是你“需要”解决的问题。

  • 一个大的白板是伟大的工作。 用它来写出工作stream程和关系。 与其他团队成员交谈

  • 继续。 做别的事。 让你的潜意识解决问题。 让解决scheme来找你。

  1. 写下这个问题
  2. 想得很辛苦
  3. 写下答案

我不能相信没有人发布这个:

在StackOverflow上写下你的问题,让其他一些人为你解决。

我的方法,一些分析性的思考:

  1. 冷静。 深呼吸一下。 把注意力集中在你要解决的问题上。 这可能包括去散步,清洁白板,获得草稿纸和铅笔订购,一些零食等避免压力。

  2. 高层次的理解问题。 如果它是一个错误,它是什么时候发生的? 在什么情况下? 如果这是一个新的任务,试图分歧需要什么结果。 重新收集数据,证据,获得接受的描述,也许文件或与知道这个问题的人谈话。

  3. 设置testing操场。 试着对所需的工具感到满意。 使用上一步收集的数据来自动化一些东西,如果是这样的话,希望有bug,否则会有一些失败的testing。

  4. 开始减速,总结一下你所知道的,反映在代码上。 执行一次又一次。 如果你对结果不满意,回到第二步重新思考,分歧多:也许应用工具(按成本顺序),即分而治之,debugging,multithreading,反汇编,剖析,静态分析工具,指标等。进入这个循环,直到你能够找出问题并通过电话testing 。

  5. 现在是解决问题的时候了,但是你已经build立了所有的工具。 这不会太麻烦。 开始编写代码,应用重构,享受在文档中描述您的解决scheme。

  6. 让别人来尝试你的解决scheme。 她最终可以让你步骤2,但没关系。 优化您的解决scheme并重新部署。

我把这个解释为修正一个错误,而不是devise问题。

隔离问题。 它总是会发生吗? 这是否只是第一次运行一组新数据? 它是以特定的价值发生,而不是与其他价值发生?

系统是否生成与该问题相关的错误消息? validation问题没有发生时,不会生成错误消息。

最近有什么改变了吗? 那些可能是开始寻找的地方。

找出我知道工作之间的差距(例如,我可以启动应用程序,并试图做一个查询),我知道什么是行不通的(例如,它给了我一个错误,而不是预期的结果)。 在代码中寻找一个中间点,看起来有可能寻找一个问题(这是否包含有效的数据?)。 这使我能够隔离我所看到的一方或另一方的问题。

阅读堆栈的痕迹。 如果您有堆栈跟踪,请查找提及内部代码的第一行。 问题不在你的图书馆。 也许会变成这样,但是可能会先忘掉它。 错误在你的代码中。 这不是Java中的错误,它不是Apache公共HTTP客户端中的错误,而是写在你的组织中的代码。

认为。 拿出系统可能做的事情,可能会导致你看到的症状。 find一种方法来validation这是否是系统正在做的事情。

没有可能性的错误是在你的代码? 谷歌任何你能想到的相关。 也许这是一个图书馆的错误,或者是糟糕的文档导致你错误地使用它。

逻辑。

打破这个问题,使用自己的大脑和系统的每个组成部分的知识来确定究竟发生了什么,为什么; 那么在此基础上,你会发现问题不在哪里,从而确定它的位置。

直到明天我才停止工作。 我通常在第二天在淋浴中解决我的问题。 我发现离开这个问题,并让我的大脑清楚,允许在这个问题上有一个全新的视angular。

按以下顺序回答这三个问题:

Q1:什么是期望的输出?
我不在乎这是不是涂在餐巾纸上的。 我想要一些能够告诉我最终结果应该是什么样子的东西。 如果我至less得不到这个,那我就停下来。

Q2:什么是input?
我find了哪些数据来自哪里。 我可能需要什么公式 B之前可能存在哪些依赖关系? 获取这些数据需要什么权限。 然后我问问题3。

问题3:是否有足够的input来创build输出?
如果答案是否定的,那么我会回到第二季度 ,从那些可以给我的人那里得到更多的意见。

对于非常大的问题,我分阶段进行分解,并在每个阶段应用Q1Q2

用道格拉斯·亚当斯的话来说,编程很简单。 你只需要盯着一个空白的屏幕,直到你的额头出血。 对于那些额头尖锐的人来说,我的理想build筑师和更大的问题的build设会是这样的。 (对于较小的问题,比如George Jempty,我只能推荐Feynmanalgorithm 。)

我写的是现场业务环境,但在开源或分布式团队中有类似的情况。 我不能假装每一个,甚至大部分的项目都是这样的。 这只是我梦寐以求的一系列事件,偶尔会发生。

  1. 获得先进的,简明的警告,问题可能是什么样子。 这不是完整的最后的会议,而是一个非正式的讨论。 只要客户(或经理)诚实,在某些规范细节中的不确定性就很好。 然后拿一张纸或文本编辑器,尝试把你所学到的内容压缩到五个要点,然后试图将这些内容压缩成一个单独的句子。 很高兴你可以在不参考你的任何文档的情况下看到要解决的核心问题。

  2. 也许可以考虑几个小时,也许是玩代码和原型,但是不能以完整的体系结构为目标:如果你有时间,或者去散步,你甚至应该做其他的事情。 如果你能在上class时间前一个小时了解一份工作,以便在第二天中午作出决定,那么这很好,所以你可以在上面睡觉。 花时间看看潜在的图书馆,框架,数据标准。 尝试将至less两种语言或资源(例如,PHP生成的HTML上的Javascript;或者将Python存根与RPC服务器交谈)绑定在一起。 充实核心问题; 放大细节; 缩小以确保整个形状仍然是不同的和有意义的。

  3. 在会议之前将任何问题发送给客户或经理,以讨论问题和您提出的解决scheme。 尽可能地邀请尽可能多的利益相关者和您的编程同事(并且您的经理很满意)。向您解释问题,然后提出您的解决scheme。 尽可能地解释; 在你的听众面前描述技术细节,而且让你的解释在你自己的思维模型中填入更多细节。

  4. 2和3迭代,直到每个人都快乐。 幸福是特定领域的。 您的行业可能需要UML图表和行项目报价,或者可能会对带有几乎看不见的干擦标记的白板上的内容感到满意。 确保每个人对你将要build立的东西都有相同的期望。

  5. 当你的客户或经理很高兴你开始,清除一切。 closuresTwitter,即时通讯,IRC和电子邮件一两个小时。 从你看到的整体结构开始。 放下你的一些原型代码,看看它是否正确。 如果没有,尽早改变结构。 但最重要的是确保你的同事给你几个小时的空间。 尽量不要在这个时候扑灭火灾。 从一个好心和欢呼开始,并对这个项目感兴趣。 当你以后陷入困境的时候,你会很高兴看到最初几个小时的清晰度。

如何从那里编程取决于实际是什么,以及完成的代码需要执行什么任务。 而且,如何最终构build您的代码,以及您使用的外部资源将始终取决于您的经验,偏好和领域知识。 但是,给你的项目和利益相关者团队最有希望,最激动人心,最积极的开始,你可以。

铅笔,纸和一个白板。 如果您需要更多的组织,请使用MindManager等工具。

安迪·亨特的语用思维和学习在这个问题上有很多话要说。

问:你怎么吃大象?

答:一次咬一口。

我喜欢用于真正大项目的一种技术是进入一个带有白板和一堆正方形便利贴的房间。

把你的任务写在便利贴上,然后把它们粘在白板上。

随着时间的推移,您可以用多个笔记replace过大的任务。

您可以移动笔记来改变任务发生的顺序。

使用不同的颜色来表示不同的信息; 我有时使用不同的颜色来表示我们需要做更多的研究。

这是一个与团队合作的好方法。 每个人都能看到大局,能够以高度互动的方式做出贡献。

可能是过于简单化了:

构想。 计划。 执行。 160wpb4.png

但是,这确实是100%的事实。

构想

你有什么想法? 你可能有一个问题,但首先你必须更明确地定义它。 你有一个你想吃的冷冻比萨饼。 你需要那个披萨! 在编程方面,这通常是你的头脑风暴会议,提出一个髋关节的解决scheme。 在这里你决定你的方法是什么。

计划

那么,当然,你需要煮披萨! 但是,如何! 你会用烤箱吗? 不太容易 你想build立一个太阳灶,所以你可以在任何地方吃太阳授权给你的冷冻披萨。 这是你的devise阶段。 这是你的铅笔和纸相。 这是你开始形成一个一步一步的方法来实施的一个有凝聚力的方法。

执行

那么,你要打造一个太阳能烤箱来烹饪你的冷冻比萨。 你已经决定了 。 现在做吧。 编写代码。 testing。 承诺。 重构。 承诺。

  1. 我仔细想想。 我花了几分钟到几周的时间仔细研究这个问题,制定了一个总的攻击计划。
  2. 敲出一个初步的解决scheme。 这个解决scheme可能不完善,一个或多个方面可能无法正常工作。
  3. 细化该解决scheme。 继续解决问题,直到我有解决问题的东西。
  4. (这个过程可以在这个过程中的任何一步完成)提出堆栈溢出的问题,以清除我目前遇到的任何困难。

我的一个前同事有一个独特的Modus Operandi 。 每当遇到困难的编程问题(例如背包问题或某种非标准的优化问题 )时,他都会被扔到杂草上,声称他能够显示复杂的状态(比如recursion函数在堆栈上传递的操作) )大大改善。 唯一的困难是,第二天他无法理解他自己的代码。 所以最终我向他展示了TDD,他已经戒烟了。

我把它写在一张纸上,从我可怕的class级图表或stream程图开始。 然后我把它写在便签上把它分解成“TO DO”。

1便签= 1任务。 1倾销粘滞便笺= 1完成的任务。 到目前为止,这对我来说确实很好。

添加问题到StackOverflow,等待大约5-10分钟,你通常有一个辉煌的解决scheme! 🙂

以下内容适用于一个bug,而不是从头开始构build一个项目(但即使如此,如果重写一下,也可以这样做):

  1. 背景 :手头有什么问题? 这是什么预防,做错了,还是不做?

  2. 控制 :涉及哪些variables(广义上的)? 问题能够被复制吗?

  3. 假设 :有足够的数据说明正在发生什么或需要什么,可以假设,即绘制有关问题的心理图像。

  4. 评估 :修正需要多less努力,成本等等? 确定是否显示塞子或轻微的刺激物。 此时可能还言之过早,但即便如此,也是一种评价。 这将允许优先级。

  5. 计划 :如何解决问题? 它需要规格吗? 如果是的话,先做他们。

  6. 执行 :AKA有趣的部分。

  7. testing :AKA不那么有趣的部分。

重复满意。 最后:

反馈 :怎么会这样呢? 什么引导我们呢? 这可能是被阻止了,如果是这样,怎么样?

编辑:

真正总结,停止,分析,行动。

相关的问题可能有用:

有用的观点,概念或方法来思考每个新手应该知道的问题

我在计算机上解决的每个问题都与解决现实世界中的任务有关。 因此,我学会了如何在现实世界中完成某些事情,并将其映射到计算机问题上。


例:

我需要跟踪学生的成绩,并得出一个全年平均成绩的最终成绩?

那么,我会保存在一个日志(数据库)的成绩,我会为每个学生(Field StudentID),等等…

我总是先把问题带到博客上。 Stackoverflow将是一个很好的开始。 当别人过去可能已经解决了类似的问题,为什么浪费你的时间重新发明轮子? 如果有什么,你会得到一些好的想法来解决它自己。

我用科学的方法 :

  1. 根据关于编程问题的可用信息,我提出了一个关于可能的原因的假设 。

  2. 然后,我devise/想出一个将拒绝或证实假设的实验。 这可能是观察debugging器或屏幕/文件输出中的东西。 或稍微改变程序。

  3. 如果假设被拒绝,则重复1.收集的信息可能有助于提出新的假设。

  4. 如果假设得到证实,那么这个假设可以被细化/变得更具体(重复1)。 或者可能已经清楚问题是什么。

发现问题的有针对性的方法比随机地改变事情要有效得多,观察会发生什么,并尝试(不适当地)使用统计。

没有人提到真理表! 但是这可能是因为他们通常只有一点帮助;)(虽然你的里程可能会有所不同),我在昨天的8年编程中第一次使用了一个。

在白板或纸上画图一直对我非常有帮助。

当面对非常奇怪的错误。 像这样: 在重新部署glassfish后,JPA停止工作

我从头开始。 做一个新的项目。 它工作吗? 是。 开始重新创build我的应用程序的组件一次。 D B。 检查。 部署。 检查。 直到它rest。 继续,直到它rest。 如果它永远不会中断。 好。 你刚刚重新创build你的整个应用程序。 丢弃旧的。 当它破裂。 你指出了确切的问题。

  1. 我想 – 我在找什么?
  2. 什么方法最好的解决了这个问题?
  3. 用坚实的逻辑来实现它 – 没有代码
  4. 伪代码
  5. 编码粗略剪切
  6. 执行

这是我优先考虑的方法

  1. 分析
    一个。 试着找出问题的根源
    湾 定义所需的结果
    C。 集思广益解决scheme
  2. 尝试错误(如果我不想分析)
  3. Google有点儿了。 当然,看看在stackoverflow
  4. 当你生气的时候,从个人电脑走一杯咖啡
  5. 当你在10杯咖啡后仍然疯狂的时候,晚上睡一觉来思考问题

金色的提示
永不放弃。 坚持将永远胜利