笔者对于涉猎的语言都是草草了解,深入不敢谈。能用罢了。
即便是用过几种语言,得出的经验依然是片面的。
很多人得出一些结论,往往是样本就一个。比如说一个只用过 PHP 的人叫嚣 PHP 是最好的语言。
所以,我得出的结论,不过是一家之言罢了。
本文文章就是总结一下,我使用的一些语言的经验,我整理出一个大致的框架,方便我以后切换到其他编程语言可以更顺滑一些。
在我看来,一个人说他会且只精通一门编程语言是很让我不能理解的事情,在我看来,什么编程语言框架上手两三天就能去写,但是这严格意义上应该叫做能用,和精通相差甚远。那是不是说写的时间长的人经验就老道了呢?也不见得。下棋下了一辈子是烂棋篓子的人比比皆是。
那我认为什么样子的人才是懂写代码的人。
拥有良好的组织代码的能力的人。
恩,组织代码的能力,一个文件排布混乱的人,不太可能写出整齐严谨的代码,当然,人也可能是复杂的,比如,这个人写的代码挺好,但是生活住处一团糟。
当然这是题外话了,依个人经验而言,学习任何一个复杂的系统,也需要像组织一个东西一样,系统性的学习。
系统化的东西往往像《如何阅读一本书》里面描述一本书的复杂架构那样。
没有一种物质或产品是绝对简单的。所有的东西都是复杂的组合体。当你看一个整体组成复杂的东西的时候,如果只看它如何呈现一体的面貌,那是还没有掌握精髓,你还必须要明白它怎样呈现多个的面貌,但不是各自为政、互不相干的多个面貌,而是互相融合成有机体的多个面貌。如果组成的各个部分没有有机的关联,仅仅是一个集合体罢了。
这就像是一堆砖头跟一栋又砖头建造起来的房子是有区别的。而单一的房子与建造的房子也不相同。一本书就像是一栋单一的房子。一栋大厦,拥有许多房间,每层楼都有房间,有不同的尺寸和形状,不同的外观,不同的用途,这些房间是独立的,分离的,每个房间都有自己的架构和装潢设计,但却不是完全独立与分离的,这些房间使用普通门 / 拱门 / 走廊 / 楼梯串联起来的,即建筑师错位的动线架构,因为这些架构师彼此联结的,因此每一个部分在整体的使用功能上要贡献出自己的力量。否则这栋房子便是不适合居住的。
有的人认为所有的编程语言都是一样的。
依我看,所有的编程语言都是有特点的,也是有优缺点的。
举一个我朋友的爱说的很粗俗的例子:
虽然说关了灯全都一个样,但是每一个女孩子都有是独一无二的存在。
编程语言也是一样。
编程语言往往是上面这些因素的取舍。
有的语言生态好,比如 对于我定位于全栈工程师(其实是全干工程师)的程序员来说:
文能写虫爬数据
武能后端写网站
进能数据搞 AI
退能机器跑运维
十八般武艺武艺样样稀疏的 API 搬运工,那,那就 Python 好了。你还要啥自行车?
工欲善其事必先利其器
大学里有个老师喜欢用 Notepad 手撸 Pascal 代码,然后拖到 IDE 里面运行。
集成开发环境 (IDE) = 编辑器 + 编译器 + 构建系统 + 调试 + 其他编辑提升(补全,重构,格式化)
到底是 IDE 好,还是 Editor 好。其实你看到这里就差不多明白了。一般情况下,选择
JetBrain 的 IDE 总是没问题的。
那么什么情况下,会选择编辑器呢?
多个
对于,这个经典的问题,可以这么回答:抓到好猫的猫,你管他是黑猫还是白猫。
那么,这个问题就变成了另一个问题。编辑器或者 IDE 可以满足我当前的开发工作流么?
那么,我们从编辑器 + 集成环境
官网的文档是最应该反复查看的东西,这是我现在依然喜欢强调的。
而官网的文档也分为四种
注:把 StackOverFlow 中某个标签的 Most Votes 的答案,是除了大略看看 tutorial 之外的另一种快速熟悉入门时候的痛点的手段。
当然,其实代码写的足够好的话本身就是一种注释。
社区一般情况下都会有的,但有几个网站特别值得提出来
特别值得一提的是有一个持续不断阅读到有趣的文章的方法:
程序 = 算法 + 数据结构
这句话当然是不全面的,这句话经典就经典在高度概括了程序中算法和数据结构的重要性,但并不影响这句话在计算机世界里面的地位。
依我看来,对我的启发是:
我会把 API 的调用和数据结构以及算法想清楚,然后才动手把代码分解成伪代码。最后写成代码。
按照复杂性可划分为:
按照复杂性可划分为:
按照数据结构可划分为:
对于一些基本的数据类型,操作为 加减乘除取余数位运算等等
对于复杂的一些数据类型,则需要对数据结构多一些了解。
比如,对队列而言,增删改查在算法复杂度上意味着什么?对机器的性能会不会有很多影响呢?
比如,对 hash 而言,增删改查在算法复杂度上意味着什么?对机器的性能会不会有很多影响呢?
比如,对字典而言,增删改查在算法复杂度上意味着什么?对机器的性能会不会有很多影响呢?
比如,对字符串而言,增删改查在算法复杂度上意味着什么?对机器的性能会不会有很多影响呢?
那字符串来说,Java 推荐使用 StringBuilder 来合并多个字符串,Python 推荐 join 多个字符串等等。
声明语句
赋值语句
条件语句
循环语句
函数或者叫做方法,叫法不同。
函数,我有个很私人的称呼,称它为最小操作模块。
实际上,在编程的过程中,程序员用面向对象的思想进行编码的人可能真的不是很多。把一段长程序按照自己的需求进行切分成若干个函数的倒是比比皆是。
不过按照什么样子的标准来切分一段程序为多个函数,仁者见仁智者见智。
这里面需要注意的事情是:
对于不同的编程语言,传值(基本类型)和传引用(引用类型)基本上达成了共识。
但在实现函数重载的时候则是有所不同,
比如,Java 里面选择了多写几个函数,Python 则没有这个机制,不过,通过默认参数却可以曲线救国,实现这个机制。
递归
函数式编程
高阶函数 mapreduce/ filter / sorted / 返回函数 / 匿名函数 / 装饰器 / 偏函数
def outer():
a = 1
def inner():
a = 2
print(a)
outer()
# 1
def outer():
a = 1
def inner():
a = 2
print(a)
inner()
print(a)
outer()
# 1
# 1
def outer():
a = [1]
def inner():
a.append(2)
print(a)
inner()
print(a)
outer()
# [1]
# [1, 2]
var outer = function(){
var a = 1;
var inner = function(){
a = 2
};
console.log(a);
inner();
console.log(a);
}
outer()
# 1
# 2
var outer = function(){
var a = 1;
var inner = function(){
var a = 2
};
console.log(a);
inner();
console.log(a);
}
outer()
# 1
# 1
面向对象有三大概念:
模块,这个概念,可大可小,大的时候,把一个程序说成是模块,小的时候,可以把一个文件,甚至你说这一个函数是一个模块,也行。
这里的模块指的是一个包下的函数。
异常处理实际上可以考验一个程序员编写代码的健壮性。
事实上来说,代码写的健壮是一个程序员必备的素养。但其实在开发过程中,出于对项目进行赶工上线,需要对程序的健壮性做出一定的取舍。并且,在编写客户端,服务端,网页前端的时候基本上都会遇到这个问题。什么时候选择健壮的程序,什么时候选择是还可以的程序。需要自己的经验。
Spawn - 产卵,为什么叫做产卵呢,因为生出大量的 child process
Spawn = fork + exec
并行并不完全等同与多核并行
互斥
竞态条件
死锁
当若干个线程进行对某个变量进行一个非原子性的操作的时候,比如
(read-modify-write), 就吹出现竞态条件。解决方式就是进行对某个变量使用同步访问 (java 中的 synchronized)。
内存可见性
当一个线程使用了多把锁的时候,就可能出现死锁。简单避开死锁的方式就是总是按照一个
全局的固定思路获取多把锁
哲学家进餐:五个哲学家围绕着桌子,两边五双筷子,如果饿了,就拿起两边的筷子吃饭。则迟早会出现一个情
况,所有的哲学家在同一时刻决定吃饭。于是两边都拿不到筷子。
最终的解决方案就是按照全局的顺序来获取多把锁。
可以用 try lock 来和超时时间来避免无尽死锁。
交替锁,避免锁整个链表,而是锁上下结点。
hash 算法
rehash | redis 渐进式 rehash
ChangeLog: