How-to-be-a-good-programmer

实例驱动学习

在知识爆炸的年代, 想成为一个好的程序员, 要具备这样一个精神:

开发者精神

开发者精神是指, 从学习编程第一天起, 你的目标, 你所做的事, 永远不是以要学会XX为目标, 而是以开发出XX为目标, 深刻意识到你学习的一切, 最终是为了你的开发而服务的。

而开发者精神的反面则是学生气:

学生气

从学习编程的第一天起, 就把自己当学生, 上课听讲记笔记为第一位, 记忆知识点为第一位, 买教材读教材为第一位, 追求学会XX, 而不是用它开发出XX

我们举个例子, 假如你要学习Java,学生气的学生行为模式:

读教材, 听课, 记笔记, 追求把这个语言的每个知识点都记得很清楚, 追求一种"内功"的修炼, 在这个过程中, 从来不想着用它去"创造"什么. 在学习的第一天起, 他给自己定下了一个目标:

"我这个学期一定要把这个语言的基础打牢, 最后在考试中取得高分, 并且为以后的学习提供更坚实的基础."

那么具有开发者精神的人会这样做:

先大体了解一下Java语言在哪些领域比较强势, 做一个简单的调研, 得出了Java在Web领域很强势这一个信号, 于是在学习Java的第一天起, 他就给自己定下了一个目标: 

"我要在半年内通过学习Java, 运用Java做出一个中小型的, 基于Web的企业管理后台"

这两种人, 起点都一样, 都是完全不会Java, 但是最后的结果往往是, 后者无论是知识熟练度还是实用性都会超过前者, 而且整个学习过程会有源源不断地动力.

夯实基础这个目标, 其实是空洞的, 什么叫做夯实? 什么叫做基础? 而且就算你真的夯实了基础, 你也极有可能陷入一种虚无感中, 因为你的所有知识, 都会遗忘.

这就是为什么很多计算机专业学生很爱问的一个问题:

"学了这么多知识, 忘了怎么办?"

如果你具备开发者精神, 那么你根本不会理会这个问题, 因为, 你开发出的东西, 你做出的产品, 它就是永久存在在这个世界上的, 你的成就感来源于真实的, 具体的, 可持久延续的项目中, 而不是来源于”我学会了什么”.

我们一定要明白:

一切不谈成就感, 不谈反馈的学习劝导, 都是在耍流氓

既然我们想获得反馈, 那么一个很现实的建议就是, 在Github上创建你的第一个开源代码仓库, 长期地, 稳定地commit, 当然, 至于这个仓库到底是干啥的, 这个因人而异, 有可能是你自己开发的一个VScode插件, 有可能是你自己写的读书笔记, 在这个不断地commit的过程中, 感受你的代码仓库不断增长不断完善的过程中, 你会获得一个比较持久的反馈和成就感, 一旦有了反馈和成就感, 那么你的学习动力就会一直保持, 也可以从学习中获得快乐.

记住, 你不是学生, 你是开发者.

知识输入与输出

当你学习一个东西的时候, 如果学完马上用语言讲给别人听, 你会学的更好, 而且会发现新问题.

很多学习理论都指出, 知识的学习, 输入固然重要, 输出更为重要.

输入就是学习别人的知识, 输出就是把自己学会的知识用文字, 语言的形式表达出来, 很多人的学习, 只有输入, 没有输出, 这样的学习肯定是不行的.

几乎所有优秀的程序员, 都有撰写技术文章的习惯, 很多时候, 并不是他们什么都懂, 而是他们刚学会了什么, 然后就围绕着这个刚学会的东西, 用自己的语言讲出来, 久而久之, 就会被别人觉得是大牛, 但是他和你的区别, 有可能仅仅是是否输出的区别.

建议所有计算机学习者, 都要有写技术文章/读书笔记的习惯, 可以发表在自己的个人主页, 其他平台上, 攥写技术文章也可以很好地增加面试官对你的好感.

写技术文章的时候, 最好用MarkDown哦, 程序员是不需要用Word这种东西的, 我们的内容是要方便发表在网站上, Word不能直接在网站里显示, 而MarkDown可以轻易地转换成html格式文件, 在浏览器中显示.

代码风格篇

现在几乎所有主流语言都有相应的代码风格检查工具, 一般已IDE或Editor的插件或扩展形式给出

设计模式

设计模式并不是针对任何一种语言, 而是一种用编程语言描述现实世界问题广泛采用的各种模式, 比如, 观察者模式, 工厂模式, 依赖注入模式等.

好的设计模式, 是好代码的保证, 只有先学会了设计模式, 才能在软件设计中游刃有余, 而且更现实的问题是, 现在很多框架, 比如Spring, Angular等, 都充斥了大量的设计模式, 比如Factory Pattern, Dependency Injection Pattern, 你必须理解这些设计模式, 你才能理解这个框架.

个人认为设计模式没有必要买本教材, 结合视频和技术文章, 就足以理解和运用.

小习惯

  1. 不要嫌变量名长, 最好可以直接通过变量名推测变量的作用.
  2. 重复出现的代码, 封装成独立的类或函数.
  3. 提前降低代码的耦合度, 不同作用, 不同类别的代码, 不要混在一起, 最好分成独立的文件
  4. 将代码进行业务分层, 比如在Web开发中, 有数据层, 服务层, DTO层, Controller层, 渲染层等, 只有将层次分开了, 才能获得足够的可拓展性, 不然代码多了你就全乱了.
  5. 用良好的设计模式去”设计”软件, 在执行一些算法的时候, 可以想一想它的时空复杂度, 想一想怎么可以让它执行地更快.

如何管理自己的电脑

包管理工具

为了更好的管理我们的各种应用包,最好使用包管理工具来进行各种包,软件的安装和使用, 方便进行卸载, 更新, 安装, 无需打开浏览器即可完成一系列操作.

linux : apt-get (ubuntu distro)
osx : brew
windows: Chocolatey

另外, windows平台上的包管理工具, 在国内的网络环境下经常慢的感人, 所以Chocolatey可能使用体验并不好. 推荐使用今年微软新发布的 WSL2, 这个东西不是那种传统的虚拟机, 有了它你可以像操作linux系统那样操作windows系统, 而且支持 docker, 甚至我推荐以后大家所有命令都可以在WSL2里执行.

容器 - Docker

为了更方便的进行开发环境配置,我推荐所有计算机学生尽早了解和使用Docker。

Docker 就是为了解决复杂的环境配置问题而生的。

它将你的软件和软件所依赖的所有环境打包成一个镜像(Image), 该镜像可以在任何一台装有docker 的电脑上运行, 和操作系统无关, 也就是docker 把运行环境和你的操作系统隔离开来了,中间隔了一层docker engine 。

写过不少代码的你一定见过这种现象:你的代码在自己电脑上能运行,但是在别人电脑上就会报错,无法运行,原因很简单,任何软件的运行都需要环境。

比如,jar包的运行需要jre ,python脚本的运行需要python 解释器安装在电脑上,以后你可能还需要运行一些服务,比如数据库mysql server , redis , rabbitmq , 随着软件运行环境复杂度的增加, 你的软件运行条件也变得苛刻,如果你想把本地的应用部署到服务器上,那事更多,需要的环境得一个个地装到你的linux服务器上,如何彻底解决这个问题?

只需在你的电脑中安装docker , 你就可以毫无后顾之忧。

所有的环境,服务,软件都是以Image 的形式打包的,Image 中包含了运行你软件的所有东西,比如你的软件是个python 脚本, 并且使用了第三方库flask,那这个Image 中就包含了python ,也就是它的base image , 也同时包含了flask, 这样的话任何一个装有docker的电脑都可以运行你的image。