下面是我抽出来的一些问题:
1、只会像高中一样跟着课程学习
2、怎么可以脱离课本和教学视频自己编写一个小项目?
3、停于理论,不知道如何实战
4、就算跟着教程安装软件,搭配环境几乎每一步都会有这样那样的错误
5、知识遗忘得快,理论没有形成体系,自己计算机的学习只局限在刷了一些慕课上的题,做了学校要求的实验
6、学完一门课程不知道能干什么
7、畏难情绪严重
8、焦虑、担心找不到工作
首先,看似抽出了很多条的问题,但是我把所有问题都归为一个,那就是 「如何提高编程能力」。
只要编程能力、实战能力提高,上面一长串的问题自然也就不成问题了,更不用担心找工作的问题。
所以今天就来聊聊如何提高编程能力这个话题。
要说提高,总得先明确下什么是 「编程能力」 吧~
到底什么是编程能力
经常能看到大V、前辈们说,你要多写,要多练,提高自己的“编程能力”,但是编程能力到底是什么呢?
在我看来啊,所谓的编程能力其实说到底就是用代码解决问题的能力,无论是 Leetcode 上的还是现实世界的问题。
能够从问题本身或是业务逻辑提炼出解决方案,并且用代码去实现,编程就是在干这样一件事:
现实世界的问题 -> 抽象出解决方案/建模 -> 计算机语言表达
可以看到,写代码只是最后一步,而我们常常说自己不会写,真的是不会写代码吗?
这让我想起了以前英语老师说的:
“很多同学说英语作文说写不了几句就写不下去了,但是真的是英语学得差吗?我看未必,大概让你用中文写,也写不上几句”
是啊,英语作文写得不好,很多同学下意识的觉得是自己英语本身没学好,确实有这个原因。
但是更本质的原因或许是你语言表达和组织能力的问题,也就是让你用母语写,也不一定能有条理的写上一段文字。
那回到编程这里,不会写代码,也许是你连解决问题的思路都没想明白,就是说你的脑海里没有形成「第一步该做什么,第二步该做什么」这样的流程。
这其实是最重要的,编码实现反而是相对简单的事情。
很多大厂,一般都是高级工程师或者架构师进行领域设计、架构设计,初级工程师进行编码实现各种接口。
说到这,我又想起了最近工作上的事情。
由于时间紧迫,我被 leader 安排去了支援隔壁部门开发,但是他们那里的很多业务背景我一点都不知道。
对方对接的人让我去模仿 xxx 模块写,我看了 xxx 模块两天,愣是没写出个啥来。
事后,我在想,为啥会这样呢?是我编程能力太差吗?
也许是吧,但是更重要的原因是,我不理解业务背景,所以我的脑海里没有要实现这个需求的流程图.
检查参数、鉴权、认证、签名… 这些流程不清晰,表现出来的形式就是,我不知道代码到底该先调哪个接口,再做什么。
心中没思路,自然无从下手。
所以其实编程的核心就是,你需要在心中对整个实现流程有一个大致的思路,然后用代码去一步步的实现。
在实现过程中,你会遇到很多细节问题,比如数据结构的选择,用 set 还是 list,存储结构的选型,以及如何 bug free的实现。
更进一步,怎样写出高性能、易读、易维护、易扩展高质量的代码,当然这都属于编码能力了。
如何提高编程能力
嗯,我回过去看了自己上面的一翻分析之后,我觉得…分析了个寂寞,说的太尼玛抽象了,我 TM 就想知道到底怎么提高编程能力!
好,接下来我就具体一点,不搞这些虚头巴脑的东西了。
提高编程能力,我自己总结了以下几点:
多实战,做项目,用需求倒逼输入
善用工具,尤其是搜索引擎
看优质资料,特别是经典的计算机书籍
养成自学习惯,提高自学能力
看一些小而美的源码
来,先上第一点,关于做项目,这也是学妹的痛,不知道如何去开始一个项目。
谈到这点,对不起,我又想讲自己的经历了,有点长。。。
一、实践
learning by doing
是的,我们都知道编程是一门实践的学科,不动手永远学不会,看懂了和学会了之间差了上万行代码。
或者说:看懂了 + 上万行代码 = 学会(此公式未经证明,纯碎自己拍脑袋想的
刚学完一门语言,想必大家都想做点有用的东西,而不是天天写练习题,但是呢,又不知道从何下手,尤其是 C 语言。
我大一上完 C 语言课,就处于这种状态,但是我隔壁一个室友就不一样的。
他在学习 C 语言的过程中,刚学到动态内存分配(malloc),就去摸索着写贪吃蛇、坦克大战,而且完成度都挺高的,那时候是我们眼里妥妥的大神。
但是大神和我上的课,学的东西都完全一样呀,况且都是上了大学才开始接触编程,为什么差别这么大呢?
以至于那时候,我和学妹一样,常常怀疑自己没有编程天赋,觉得别人天生就是这么强。
这种状态一直持续到大一下,那时候刚学完 Java,而 Java 也比 C 友好了不少,所以总想写点什么。
于是自己就选择写一个类似 QQ 的聊天工具,其实功能就很简陋,就是一个简单的 GUI + Socket 编程,然后在加上用户信息管理就完了。
但是,当我用这个简陋的软件,分别在室友和我的电脑上跑起来并且成功发送消息的那瞬间,我觉得我的编程世界被点亮了。
原来编程这么好玩,原来我也能做一些有趣的东西!似乎找到了一丝编程的感觉,但还说不上到底是什么感觉,毕竟这个程序总共也就几百行。
紧接着,趁热打铁,我又写了一个联机五子棋,实现上依然是 GUI + Socket 传输数据。
但是写这个又遇到了不同的问题,比如棋盘在我的实现里是一个 NN 的数组,棋子是用对象表示,对象里有坐标、颜色这些属性。
当时我就疑惑了,当一方落子后,该怎么把棋子对象通过网络传输给对方呢,再从网络接收的数据恢复到对象?
起初自己的想法是手动的把对象转换成字符串,然后像聊天工具一样发送给对方,比如:
{x: 12, y: 13, color: black …}。
这种做法没问题,但是总感觉不够优雅完美,于是上网一番搜索之后发现,原来我想的这个就叫「序列化」和「反序列化」。
并且在 Java 里直接实现 Serializable接口就好了,甚至可以直接使用ObjectOutputStream类就能完成序列化和反序列化对象。
这些问题在现在看来,根本就不是问题,更像是“常识”。甚至序列化这块,还会选择一些兼容性更好、性能更高的协议,比如 Protobuf、Thrift、Avro 等等。
但是对大一时的我来说,在这个过程中不断的遇到问题并且去解决,就是实打实的编程能力上的提高啊。
在我解决掉一系列问题之后,顺利的和隔壁室友用自己写的联机五子棋对战了几局,这个五子棋还支持不少诸如悔棋、暂停、自动判断输赢等功能。
在这里插入图片描述
Java版五子棋
但是由于当时没有存 Github 的习惯,代码在换电脑之后没能留下来。通过写这些项目,我像打通了任督二脉一样,不是学了什么厉害的算法、也不是高深的设计模式、更没有分布式这样高级的东西。那是什么呢?我感觉到编程就好像搭积木一样,基本的函数、库、组件就是一个个的积木块,写的代码就是胶水。只要我们心中有设计图纸,那就能通过胶水把这些积木搭建成想象的模样,缺少什么积木块,用到的时候再去搜索就行了。在程序的世界,只要你想,你就能。这段时间大概是我编程能力提升最快的一个阶段之一。关于这个五子棋,还有个小插曲:我写的不是联机五子棋嘛,然后启动的时候输入对方的 IP 和 Port 就能连上对战。后来,我找了一个在其它城市上大学的高中同学,让他和我一起玩五子棋,但是呢,我傻乎乎的让他用 ifconfig 查看自己 IP 后告诉我,然后我在这边连接。那个 ip 呢,大概长得像 192.168.1.xxx,熟悉的同学都知道,这个就是局域网内使用的 IP 了,并非公网上的 IP。局域网内的 IP 只能在内网才能使用,所以我用这个 IP 是永远连不上的他的电脑的。但是那时候我才大一,没学过计网,根本不懂这里面的原理。为啥我和室友能连上呢(因为在一个局域网)?为啥和其它学校的同学就不行?别看现在这个东西在我看来是常识,但我那时候是一点计网知识都没,就是硬着头皮学的 Socket 编程,去理解 IP 和 Port。那是怎么解决的呢?当然是找谷歌呀!在网上一番查询后,大概明白了,如果想让不同局域网内的主机进行 P2P 通信,需要一个公网中转服务器辅助进行 NAT 打洞。。。后来,我就又去尝试 NAT 打洞了,其中细节就不再描述了。其实把我个人编程经历上写这么多,就是想展现我是如何一步步去实践的,遇到了什么问题,又是怎么解决的,把这个过程展现出来。你看我没学任何计网知识,还不是通过边学边用,完成了网络相关的项目。所以你离项目只差一个开始。说到这里,不少同学又会说,我知道要多实践、多动手,道理我都懂。可我还是不知道如何开始去写一个五子棋、贪吃蛇之类的东西。好,那我就要问问你了dani:为什么你学了 C 语言还是不会写贪吃蛇呢?学妹:老师没教我贪吃蛇如何在 C 语言中表示,也没教我如何让画面动起来,更没教我如何绘制 GUI ,所以我不知道怎么做。这应该是大多数同学最典型的问题吧?那我们以贪吃蛇为例拆解一下,看看是如何从问题到代码的。首先,贪吃蛇是一个个的节点组成的,节点肯定有横纵坐标吧?一个个的节点组成了一条蛇,那自然应该想到链表吧?蛇还有什么属性?当前移动的方向还要食物位置吧?那这些属性在 C 语言中用结构体表达出来就是这样:
typedef struct node{
int x; int y; struct node next;// 单向链表} SnakeNode;typedef struct snake { SnakeNode *pHead; // 蛇头 SnakeNode *pFood; // 食物 int direction; // 方向 0-3 依次表示:上、下左、右 …}
接下要考虑的就是如何去绘制蛇,这个简单呀,就把整个链表从头开始把每个节点打印出来。