Categories:
给程序员的第一门课 by 乐码范(云淡风轻)
如期完成项目
在实际的工作中,对于编程功底扎实的人,新的编程语言都是学几天就直接拿过来用的,从来没见过编程高手会因为不熟悉新语言而导致项目延误、失败的情况发生。
Six days you shall labor and do all your work, Remember the Sabbath day by keeping it holy
6天内完成你所有的工作。
项目延误、失败 是最可怕的。
动手,动手,再动手
只看不画,永远成不了画家
_ 硅谷创业之父Paul Graham《黑客与画家》
硅谷创业之父Paul Graham在他的著名的《黑客与画家》书中的一篇文章里,把程序员的编码工作和画家的工作相比。
程序员也是创造者,与画家、建筑师、作家一样。他们所做的工作都是创造性的活动,而不是简单的机械的性的重复。
程序员的职责是用程序满足人类的各种需求。一堆不能满足需求的语句,是算不上程序的。
通过自己大量练习编程、读别人的代码学习,不断总结编程思路、设计模式。
当面对一个软件需求,能够在头脑中快速形成设计思路,清楚知道应该分成哪些模块时,那就是程序员了。
如同学习画画,美感和技巧是一步步练出来的,写程序也是写出来的,书本只是辅导而已。任何一本几天速成的编程书,都是忽悠人的,否则编程大师现在就可以像抓豆子一样,街上一抓一大把了
程序员吃的是青春饭吗?
不过话说回来,在国内年轻劳动力比较充裕的年代,除了一些事业单位如公务员、老师、医生等职位比较稳定,还有哪些行业不是吃青春饭呢?现在大红大紫的歌星,演员,还是连锁餐厅里的服务员?
很多人会考虑,干几年就转技术管理岗位吧。但管理岗位属于职位金字塔的上层,最终只有少数人可以实现。那么吃青春饭是不是没有出路?其实完全不必担心太多,车到山前必有路。
年轻人的优点就是能学敢拼,只要不荒废工作的前10年,在前10年里积累足够的专业经验和行业经验,到时候你自然发现有很多新的机会在你面前等你。
做一个多邻国。
勤于提问,怠于思考
勤学好问,是一个很好的学习习惯。但是要注意,“勤学”是第一位的。学不光指看书、看视频,也包括自己去思考、钻研,花了一定的时间自己实在解决不了,再去问。
学编程,常见的基本方法有这些:
- 自己编程做实验
- 查书
- 英语差的话,查百度;英语好的话,查Bing;还会翻墙的话,就用Google吧
你喜欢旅游吗?
- 反正旅游都是到个景点看风景,为啥不直接看别人拍的图片和视频呢?
- 学编程也一样,问别人直接要答案,跟旅游直接看别人拍的图片一样无趣。
- 可以向别人请教方法和思路,但是回到具体某个问题上,还是要先自己去尝试解决。
- 问了别人,只会知道答案,但若是自己亲自去找解决办法,那么在寻找的过程中,却可以领略更多相关的知识和思路。
- 自己努力解决问题,虽然苦,但看到的更多,成长也更快。
贪玩游戏,半途而废
对于大部分的时候,如果你决定学编程,我个人建议是完全停掉游戏。虽然我相信你可以定个完美的学习计划,每天玩几个小时游戏,再学一个小时编程,相信坚持就可以胜利。但是,人的精力是有限的,你所认为好玩的游戏一定是非常耗费精力的,如果玩过了游戏就学编程,基本是学不下去的;反过来,先学编程,再玩游戏,那么也还是证明游戏比编程好玩,学习效果也不会好。
不恰当的“勤奋”
有些人在刚开始学写程序的时候,总是担心自己知道的不够多,于是不能写出好程序。因此,表现得过于“好学”,具体表现在:
- 尝试去记住所有的语法
- 尝试把书或视频看完才开始动手练习写程序
- 尝试把编程语言的细节都弄明白
- 写代码遇到一点点不熟的地方,都要重新看半天书
- 等等
这是一个很大的误区。
对于初学者来说,最重要的是能够快速上手写程序,把编程思维训练起来,为后面的学习打下更坚实的基础。
就如人说话一样,平时用到的词汇量比词典少多了,但丝毫不影响一个人的表达能力。写程序也一样,程序里绝大多数的代码都是每种编程语言前几章的基础内容,复杂深奥的语法用的地方很有限。
编程关键是对思维的训练,而不是知道多少编程知识。这种训练过程,是通过不断地持续地练习,才能掌握的。
别人所传授的通常是一种技巧或固定的知识,但这些东西自己该什么时候用,如何用,还要看自己对程序设计的理解。
代码能跑出结果就算完
衡量一个人的编程能力,对初学者,看其写过多少程序,可以作为衡量其水平的一个关键指标。
A:写过2个2000行以上的程序,但平时的小程序都不超过300行
B:没写过超1000行的程序,平时写过很多500行左右的程序
学习写程序,不能把完成了多少程序作为一个基本目标。
- 代码可以写很长,但长代码不代表质量好,高手追求的是代码要简洁精练。同样的功能,能用最简单的语句,最少的行数实现,才是最好的。
- 代码也可以写很多年,但编码水平并不一定会随着时间的增长而持续增长。
- 天天做“搬砖”一样重复的劳动,做一个月和十年,是没太大区别的。
当写了一定量代码之后,编码水平的提高,在于从重构、改进代码的过程中,理解了如何才能写出好的代码。
- 《重构》
- 《code complete 2》
- 《Clean Code》
- 《Pragmatic Programmer, The: From Journeyman to Master》
初学编程,有哪些现实的问题我可以用编程来解决?
对初学者来说,用那些功能强大、用户体验良好的软件,感觉很好的同时,但对这些软件是如何做出来的,完全一头雾水。虽然自己也要开始学习编程,但要自己有能力能做出这些软件,那距离似乎比月亮还远。
眼前的那些软件无从模仿,但又似乎没有发现身边有哪些问题,可以让自己刚学的编程能力显示一下威力,时间久了,就会对编程很迷茫,很有挫败感。
其实,仔细观察一下,身边能够用简单程序解决的问题有很多,比如:
- 你有几百张照片,图片名字都是照相机默认生成的,你想把这些图片都统一改成自己需要的某个格式,自己用程序可以做吗?
- 准备考试,从网上找了几千道选择题,但题目格式虽然规范,但排版不好阅读,想自己排一下版,能用程序做吗?
真正好的程序员,应该也是一个“懒人”。
什么时候学习数据结构和算法?
学习数据结构,必须有一定的编程基础才可以,才能理解不同的数据结构和算法应用的场景、如何使用及解决的问题。
国内大学计算机专业也是等到学生学完一两门编程语言之后,才开始讲授数据结构,因此对于编程初学者,也是建议等学了一两门编程语言之后,有一定量的编程经验之后再开始学。
编程误区
-
数学
- 只学习需要的数学 (具体数学、离散数学、线性代数、概率论、数论、拓扑学、微积分、其他数学主题)
- 《什么是数学》- 微积分、数论、拓扑学
- 《具体数学》
- 《离散数学及其应用》
- 《Linear Algebra Do Right》
- 《Statistics 110: Probability 概率论》
- 松本行弘:我的编程人生
-
为什么存在这么多语言?
- 不同的语言面对不同的领域会有不同的表现(下面的概念会让你明白)
- 参加过 LeetCode 就可以明白,
- 文本处理的题目 Python 只需要 10 分钟就写完,但换 C++ 1小时都不一定写出来。
- 搭建一个 CNN 模型,使用 Pytorch 明显比 C++ 更快。
-
投入产出比 1: 你现在掌握的解决方案就是最好的方案。
-
要相信当前的问题一定有更好的解决方案。
-
如果明天就是 Deadline 了,那么现在你能做的方案就是最好的方案。
-
因为学习新的方案往往需要花更多的时间。
-
先做出一个 Prototype ,验证之后,再花时间推翻重构。
-
开发的时候时刻记住 “投入产出比”
-
-
投入产出比 2: “开发效率”,“泛化性”,“运行效率”
-
你需要写一个程序,只需要运行一次得到结果。你现在有 A 、B、C 语言。
-
A 语言需要花 2 天写成程序,但是更具有 “泛化性”,“运行效率” 。类似 API ,下次很容易修改、调用。
-
B 语言需要花 2 小时写成程序,但是换别的问题下次要重写,运行起来还贼慢。
-
开发的时候时刻记住 “投入产出比”
-
-
性能好的语言速度一定快吗?
- 不是,算法的才能从本质上提升速度。
- 与其 Rewrite everything in Rust ,不如好好专注算法。
- 可以看看 算法 在工程上的应用,比如 【硬件科普】ECC内存是如何发现错误并纠正的? - YouTube
- 所以在选择语言上,不要被公众号的文章迷惑。比如 C# 貌似是门很旧的语言,现在 Go 很流行啊。Ruby 都快死了,不值得学习啊。旧的语言往往更加值得研究。
- No, No, No。C# 有很成熟的 Rest API 方案和架构,但学的东西比 Java 少。Ruby on Rails 的框架比你去看八股更好,而且 Ruby 的虚拟机比 Java 更值得研究 (因为更简单)。Rust 虽然没有工程上的应用,但是 Rust 的编程语言设计十分优秀,而且是 LLVM 基建的好例子。学到这些优秀的设计原理,如果工作上需要 Python/Go ,学起来反而就非常轻松了。
C语言
C语言是非常重要的语言,即使要学C++也要先学C才行。对于国内计算机专业的学生来说,C语言基本上都是必修课,可见大家对其认可。
不过由于其语法细节太繁琐,尤其是指针部分内容不太容易理解,因此不少学生容易陷入各种死扣语法细节的误区。一个学期下来,大部分学生只掌握了一些基本的语法细节,却对如何编程缺乏一个宏观的认识,导致很多人学了C也不知道自己能用来干啥,更不知道如何写一个有用的程序。遇到不少同学,不少课程成绩都挺优秀的,却大学四年最长的程序都没有超过50行,不免让人唏嘘。
https://www.lema.fun/classroom/d0f4f5d64fdfc329/d2a40c780fbf96f9
C#语言
我个人更加倾向于 C# ,因为 C, C++, C# 看起来都是同一个家族出来的。
C#看起来与Java有着惊人的相似;它包括了诸如单一继承、接口、与Java几乎同样的语法和编译成中间代码再运行的过程。
C#是一种安全的、稳定的、简单的、优雅的,由C和C++衍生出来的面向对象的编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性(例如没有宏以及不允许多重继承)
…
当然,也有人嫌 Java可选择的库和框架太多让人头疼,C#这方面直接用微软官方的就比较省事。
…
但2016年,.Net Core的出现,让之前使用.Net framework的程序运行在Linux或其他操作系统上成为了可能。
Go语言
学习资料太少。可以先学 C# 语言 再学 Go 语言。
…
国内知名的例子主要是七牛,阿里也有少部分产品在用。
如果你是C爱好者,建议你学习和使用Go。Go可以调用C/C++程序,又提供了太多的便利,速度上稍有牺牲,但并不大。在绝大部分场景下Go能给你带来媲美C的性能,而对于某些确实性能过于关键的场合,也可以通过cgo让Go和C搭配。
JavaScript语言
JavaScript语言在本身设计上,相比其他语言,存在更多不完善的地方,因此才有《JavaScript: The Good Parts》这样专门教人如何用语言好的部分而避免用坏的部分去设计这样的书。最开始,JavaScript是不支持class关键字的,程序员需要通过对象原型(object prototype)来实现,直到2015年ECMAScript 第六版 (简称ES6)出来之后,才引入了class关键字等更现代的语法特性。
Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。但同时由于JavaScript程序用户代码只能运行在单线程上,因此对CPU计算密集型的程序,不适合使用Node.js做开发,否则容易极大地降低系统处理并发请求的能力。
很多时候,开发者也会选择用JavaScript语言结合某些移动端框架,就可以用一份代码编写出能够同时支持安卓和IOS等多个平台的App。在对App性能要求不高的场景下,为了节省跨平台的开发成本,这种方案还是有极大的吸引力的。
…
TypeScript 被设计来开发大型应用,然后转译成JavaScript。由于 TypeScript 是 JavaScript 的严格超集,任何现有的JavaScript程序都是合法的TypeScript程序。
Python
Python虚拟机本身几乎可以在所有的操作系统中运行。
…
2017年,估计是人工智能最火热的年份了,懂人工智能的工程师成了香饽饽,不光国内,整个世界都是如此。
AI 需要大量的研究,因此没有必要写大量的 Java 代码去测试新的假说。 测试 ProtoType。
Python中几乎每一个 Idea 都可以迅速通过 20-30 行代码来实现。因此,它对于人工智能是一门非常有用的语言。
人生苦短,就用Python。
…
- 由于全局解释器锁(GIL) 的限制,单个Python 程序无法在多核上并发执行;
Ruby
Ruby 虽然正在凋亡,但其编译器确实最值得研究的。
因为 Ruby是一个动态的、反射性的,面向对象的通用编程语言。
Ruby 是松本行弘 93 年开始编写,95年发布的一个动态的、反射性的,面向对象的通用编程语言。支持多种编程范式,包括函数式、面向对象式和命令式。它还具有动态类型系统和自动内存管理。
- 一个50岁的程序员在2016年用2个月写出了2万行的数据库,然后创业得到5000千万美元融资
- 松本行弘 93 年开始编写,2年后就发布了编程语言。
实际上,要完成任何事情,1年绝对够了。
Rails框架首次提出是在2004年7月,它的研发者是26岁的丹麦人David Heinemeier Hansson。不同于已有复杂的Web开发框架,Rails是一个更符合实际需要而且更高效的Web开发框架。
编程语言
- 类型 Typing
- 常见数据类型
- “静态类型” 和 “动态类型”
- “强类型” 和 “弱类型”: C++是弱类型(casting), Python是强类型(自动转换)
- 运行方式
- Compiler: source -> compile-time -> assembly code -> binary code -> run-time (C/C++)
- JVM: source code -> compile-time -> byte code -> JVM -> run-time (C#)
- Interpreter: source code -> interpreter -> run-time
面对大项目时, C++ 的编译速度十分慢,即使 Library 编写很合理。而 Python 只需要编译需要的部分就可以了。
一种合理的设计就是 Engine 和 Peripheral 设计,把 Core 部分使用 C++ 重构。
或者把一些常见的库、模块预先编译并加载到内存中当成 dynamic linked library ,这样可以免去大部分的编译时间。
面向过程/面向对象/函数式编程
- 面向过程
- 说白了就是写模拟,理解业务逻辑就可以了,写流水账。
- 面向对象
- 封装、继承、类
- 控制暴露程度,能够模块化程序。
- 配合 “设计模式” 也能尽可能避免 Side-effect
- 函数式编程
- 完全避免 Side-effect , 进一步控制复杂度。
把程序当成一个犯人。面向过程就是自由度最高,面向对象就是控制在监狱内,函数式编程就是控制在笼子内。
好处就是 Debug 特别容易。
网页客户端软件
- 瘦客户端
- 由于整个网页的体积比较大,需要较长的网络传输时间。
- 胖客户端
- 用的通常是AJAX技术,网络通讯传输数据很少,因此界面响应会比较快,用户体验好
- 参与基于React组件库编写工作;
后端/服务器端开发
小付姐是美术转CS专业,在ANU研究生入学之前,就进了网易后端开发(Java)。之后还发过 Parallel Computing 的课件。
数据库
鉴于数据的无可置疑的重要性,需要专门的人来管理数据库,负责数据库的日常备份、优化、解决数据库出现的各种问题,这样的职位就是数据库管理员(Database Administrator)。
由于DBA的职责的重要性,因此需要是数据库专家级别的人才能够胜任上规模的公司的DBA的岗位。中小型的公司,由于用人成本问题,会略微放低一点招聘的要求。
移动端开发
典型职位案例(游戏)
Unity3D开发工程师
岗位职责:
- 负责基于Android、iOS等智能终端平台的网络游戏客户端开发;
- 负责手游版本现有功能的维护以及新功能的开发。
任职要求:
- 1年以上的手机游戏客户端开发经验,有手机网络游戏开发经验优先;
- 具备扎实的C++语言基础和算法分析能力、数据结构及算法基础,熟悉常用设计模式、多线程、网络、界面开发;
- 深刻理解客户端框架和核心模块的实现,有主导过相关核心模块的开发经验;
- 熟练应用流行的开发引擎,有Unity3D开发经验优先;
- 熟悉3D图形学原理,熟悉DX或者OpenGL图形接口,掌握基础Shader开发技术优先。
典型职位案例(iOS)
iOS开发工程师
岗位职责:
- 负责公司新产品APP在IOS平台下的设计和开发工作,根据产品需求进行详细设计、编码实现和单位测试,确保性能、安全和可靠;
- 不断学习IOS新版本的API和新技术,跟踪技术发展方向,根据项目需要快速学习并掌握新技术;
- 编写设计开发及实现文档。
任职要求:
- 具有3年以上IOS应用开发经验,至少有一个完整应用开发经验;
- 精通Objective-C,熟练使用Xcode开发环境,熟悉iOS SDK ;
- 熟悉iOS应用开发框架及iOS平台下的GUI设计和实现,能独立开发高性能的iOS应用;
- 熟悉JSON/XML、HTTP、TCP/IP协议,熟悉面向接口开发;
- 具有高度的团队协作精神,良好的沟通能力,有较强的责任心;
- 有App Store上架经验,有已上架作品或相关作品优先。
人工智能
正态分布能不能同时出现两个最高点,还是还是有且只有一个最高?
mixed gaussian model可以有多个modes
现实生活sample size肯定是近似gaussian的,但是网上的sample是服从啥distribution是unknown的,这时候需要介绍一个hidden variable然后用smc,abc等方法找到这个hidden variable的近似distribution
网上sample你的用non informative prior
而且男女双方在博弈的时候又是多目标优化,复杂度更上一层. 不知道是否存在一个博弈双方都能达到的pareto front
网上本质上提高的是先验概率