新手程式设计师最常碰到的5个问题 — 你如何解决这些问题

当你开始学习程式设计的时候,很容易碰到问题让你很奇怪一个人如何处理来写一个电脑程式,但事实是,学程式的人都会有那样的经验,当他们开始学习的时候都会碰到同样的问题,我教过几堂基础介绍的程式课程,有些问题几乎绊倒了每个学生—从开始学习到处理程式设计等等的问题。

[adsense][/adsense]

我会做好准备帮助你度过这些挑战—没有一个问题是不可克服的。

安装设定

学习程式设计已经够难的,甚至很容易在你开使前就碰到障碍,首先你需要选一个程式语言(我推荐C++),接着你需要编译器跟一份程式设计教学可以涵盖你所选的程式语言,以及可以跟你设定的编译器运作良好,这全都很复杂,而且全都会在你开始有趣的地方前碰到。

如果你还在奋斗初始化的设定,那么看看工作达人上设定编译器跟开发环境的文章(Code::Blocks跟MINGW),里头用了很多荧幕截图引导你设定编译器,并让你前进到可以实际执行程式的地步。

要有程式设计师的思维

你有看过State Farm的电视广告中洗车公司把车送回给客户时车上还有肥皂泡沫?公司洗车却没有冲洗掉,这是电脑成是的最好比喻,电脑就像洗车公司是非常非常的贴切,他们做的很彻底,只做你告诉他们要做的事;他们不了解含蓄的意思,一开始所需资料的层次可能令人气馁因为它需要全部考虑每个单一的步骤,确认没有一个步骤是错的。

一开始这会让程式设计看起来似乎很难的样子,但是不要绝望,不是所有的东西都需要指定—只有不是电脑可以做的事才要,编译器有的标头档跟函式库(例如, iostream标头档允许你跟使用者互动)提供很多预存的功能,你可以使用网站像是http://www.cppreference.com 或是Cprogramming.com 的函式参考来找到这些预存的功能函式库,在使用前,你可以只专注在确切地说明你的程式独特的地方,甚至一旦你这样做,你将开始看到模式可以被转成函式,这些函式可以包覆一堆步骤到一个单一的函式,这样你就可以到处呼叫,突然复杂的问题会开始变得简单,之间的差异就是:

向前走十英尺
移动你的手到墙上
移动你的手到右边直到碰到障碍
...
按正面朝上的凹陷

然后

走到门前
找电灯开关
打开电灯

程式设计神奇的事就是你可以将一个复杂的行为打包进一个简单的子程序中(通常是一个函式)这样你可以再使用,有时候很难一开始就子程序做的正确,但是一旦你懂了,就不再需要担心了。

你可以到这里阅读更多关于如何有程式设计的思维,这是写给初学者的。

编译器错误讯息

这似乎事件小事情,但因为大部分的初学者不熟悉程式严格的格式(语法),初学者往往会碰到编译器产生的很多抱怨,编译器错误是出了名的隐晦跟啰唆,绝对不是写给想要看的新手。

那就是说,有一些基本的原则你可以使用来航行于讯息堆中,首先,很多时候一个单一的错误会造成编译器搞乱而产生几十个讯息—要以第一个错误讯息开始,第二,行号是谎言,嗯,可能也不会是,但是你不可以完全相信它,编译器在它第一次了解到有问题时就会抱怨,而不是在问题真正发生的地方抱怨,然而,行号显示错误可能发生的最后一行—真正的错误可能在较前面,绝对不会是在后面。

最后,有希望!你最终真的真的可以搞懂编译器真正的意思,今天有些错误讯息似乎非常地隐晦难懂,一旦你知道真正的问题是什么,在短短几个月的时间你会像认识一个老朋友那样,我过去就写了很多这样的资料,如果你想获得更多帮助,可以检查Alex Allain的deciphering compiler and linker errors 这篇文章。

除错

除错是一个重要的技能,但大部分的人天生就无法掌握它,除错很难有些原因;第一,这会让人沮丧,你只是写了一些程式码,即使你相当有把握可以执行,它就不是没办法执行,该死!第二,这很乏味;除错通常需要很多努力才能缩小问题,而且除非你有经验了,否则很难有效地缩小问题,一种问题,记忆体区段错误,就是一个特别好的范例—很多程式设计师试着增加print叙述来显示程式会在多远之前当机以缩小其问题,即使除错器可以正确地告诉他们问题发生在什么地方,而这的确也会引发最后的问题—除错器也是另一个让人搞混的东西,很难设定的工具,就像编译器一样,如果你想要的是你的程式可以执行,最后一件要做的事就是去设定另一个工具来找出原因。

要学习更多除错的技术,检查这篇文章:debugging strategies.

设计一个程式

当你刚开始设计程式时,设计是一个真正的挑战,知道程式设计的思维是一回事,知道如何把程式放在一起的方式使它稍后可以容易的修改他们又是另一回事,像’注解你的程式码’、’封装跟资料隐藏’跟’继承’这样的想法没有什么意义,只有在你感觉没有他们的时候才会痛苦,问题是程式设计就像是吃蔬菜一样,可以让你未来的生活更加容易一样,不好的设计会因未来的改变,或是在你写了之后无法了解而造成程式没有弹性,通常情况下,糟糕的设计暴露出太多事情如何执行的细节,所以程式的每个部份必须知道程式其他部份每个地方所有的细节。.

一个很棒的例子就是写一个跳棋游戏,你需要一些方法来表达棋盘—让你挑一个,一个固定大小的全域阵列:int checkers_board[8][8],你的存取棋盘全都直接透过阵列来进行:checkers_board[x][y] = ….; 这个方法有什么不对吗?完全正确,注意我写的你的存取棋盘全都直接透过阵列来进行,棋盘是一个概念的实体—你所关心的事情,这个阵列恰好在这个特殊的时刻发生,你如何实作这个棋盘,再说一次,两件事情:你表达的东西,跟你表达东吸的方法,藉着所有存取齐盘是直接使用阵列,你把两个概念纠缠在一起,当你决定改变表达棋盘的方法时会发生什么事?你有非常多的程式码要改,但是解决的方法是什么?

如果你建了一个函式可以执行这一种的基本操作,让你在跳棋棋盘上执行(可能是一个get_piece_on_square()方法跟set_piece_to_square()方法),每次的存取棋盘就可以透过这个介面来进行,假如你改变了实作,介面还是一样,而这就是我们说的”封装”跟”资料隐藏”的观念,很多方面的程式设计,像是继承,允许你隐藏特定介面或概念(棋盘)实作的细节(阵列)。

现在就来吃你的波菜吧! 🙂

接下来要学习更多关于这个议题的资讯可以阅读programming design and style

关于这个主题更多进接的文章,可以到object oriented class design这里阅读。

另一个使你的程式更容易地在未来修改可以读clearly comment

接下来的几天我也会写一些学习程式的文章,所以使用RSS订阅工作达人、或是用twitter来追踪我的文章更新。