首先,你必须做到能够高效的解决问题。这是一个关键的起点因为编程就是为了解决问题的。

虽然觉得问题的方法可以有很多,但过程中有几个部分让我印象深刻。拥有出色的解决问题的能力的程序员会先将问题的本质提炼出来,以便于确定总体目标并带着这个目标着手解决问题。然后他们将每个问题分解成容易处理的小问题,依次处理每个小问题,有时还可以通过绘制导图使其实现可视化。

这个过程做起来远比听起来难得多。当我开始学习编程的时候,我也会遇到瓶颈:和大多数人一样,我从未在学校学会如何解决问题,这也不是一项容易传授的技能,曾经,老师在数学课上布置了一组习题,我便一头栽了进去,正如我刚刚开始编程的时候。毋庸置疑,我这是在做无用功并且在最简单的问题就遇到了障碍。

当我开始学习如何解决问题甚至是高效的解决问题,情况开始发生变化。我开始去关注一个问题的最终目的是什么,得益于乔治·波利亚的书《如何解决这个问题》。

我把波利亚的一些想法运用到编程里,比如如何去理解问题。“这个问题必须被理解,”波利亚写道。这包括能够“指出问题的主要部分、未知、数据和条件。”对于每一个问题,我都拿出一张纸,然后写下这些问题的答案:我在解决什么问题,或者我在试图寻找什么?(未知);我现在有什么已知?(数据);我需要注意哪些限制条件或细节?(条件)。

理解这个问题对我们来说似乎是显而易见的,但显而易见的问题很容易被忽视。我不止一次在一个问题上投入了数小时但是毫无收获,过了一会才意识到这个问题,我错过了问题陈述中一个小而关键的细节。写下问题的细节虽然会让我的思维变慢,但是同时这帮助我准确地思考我需要做什么,这就已经成功的一半。

在此基础上,我也会制定了计划,这也是乔治·波利亚的另一个建议,画家在正式作画之前会先画一幅草图,建筑商用图纸和蓝图来建造房屋,编程也一样。与其急着去做,我还不如先想好我要做什么,然后制定一个计划。 具体的实施方法有很多种。有时我用数字的顺序列出我需要采取的步骤:第一件事做这个,第二件事做那个。有时候我也可以把问题可视化,当我学习for loops的时候,我拿出一把杏仁,在这堆杏仁中进行物理循环。这个例子听起来很幼稚,但它能很好的帮助我思考了这个问题。

我也会画一些示意图。对于递归问题,我会绘制图表来说明每次递归调用时发生的情况,直到递归完成为止。我会想办法如何去简化问题,使其更易于处理,并帮助我发现一个合适的解决方法。最重要的是,我是带着目的性去进入一个问题,并在解决问题的过程中始终保持着这种目的明确的感觉。

有时尽管制定了最好的计划,问题仍然很难被解决,我还是有可能没有思路。成为一个高效的问题解决者需要时间;我仍在努力的学习这个技能,这是绝对值得的。

当我阅读由一个优秀程序员编写的代码时,最直观的感觉就是它很干净,很容易理解。变量被很好的命名,函数简单明了,每一行代码都有特定的用途。代码的清晰性度反映了程序员的思考过程:我可以从头到尾阅读程序,并确切地知道发生了什么。这是很棒的解决问题的方法,也是我所追求的。

掌握计算机科学

程序员

学习计算机科学是编程基础的第二部分。我最近开始学习计算机科学,并且喜欢它,因为学会了这些就能站到比别人更高的地方去看问题。比如我开始从幕后的角度去了解使用内置函数时会发生什么。我还学习了内存和运行时间等许多其他主题。简而言之,我正在学习计算机为什么要做它所做的事情。

明白“为什么”让我对前后关系理解更深刻,帮助我成为一个见多识广的程序员。因此我在编写代码时更加深思熟虑。现在我对时间复杂度有了一些了解,举个例子,我更倾向于使用二分查找,而不是遍历列表中的每个元素。

这也丰富了我对于核心编程概念如何运作的理解。打个比方,曾经我在研究一个递归问题,但没有得到我预期的结果。经过仔细审视,我明白了原因:这与调用堆栈的执行有关,几个月前的我并不知道这个。

学习计算机知识也帮助我去使用类。对于类,我苦苦挣扎了很长一段时间,也不敢使用它。我知道如何编写类,但不确定什么时候用,为什么用。当我了解到当我的计算机中创建实例和调用方法时实际发生的事情时,情况就发生了变化。当我有了一些相关知识之后,我就敢使用类了。对于递归和类,计算机科学填补了我知识上的空白。

所有这些基础要素往往都被抛到一边。进步是缓慢的因为人们往往倾向于选择有趣的工作当他们有选择的余地的时候。这太可惜了。而掌握基本要素的程序员似乎对编程充满信心:他们清楚的知道他们的编程时的“如何”和“为什么”,这改进了他们的工作并增强了他们在其他人的面前的可信度。

另外,扎实的基础知识使学习新的编程语言和技术没那么困难。例如,花时间真正理解一种编程语言的核心概念像迭代、递归和抽象这样的核心概念有助于学习另一种语言。简单地说,掌握了基本知识,将会获益匪浅,几乎没有什么损失。