下面是总结这本书的一些重要点
行业地图
特质:简单务实,机制创新
简单、喜欢偷懒、严谨、创新
普世低调的创新精神,理想主义的工匠精神。
底层:一个成就感驱动的职业
软件工程师关心的是,自己做的事是不是能对社会产生真正的影响,是不是真的改变了这个世界,改变了人们的生活。很多软件工程师心中向往的,是林纳斯·托瓦兹这样的人。
选择:一线和次一线城市,机会更大
如果你已经准备好成为一名软件工程师,建议你去大城市。首先看工作机会,其次看薪酬,最后看流动性。
现实:为什么会有996
首先看发展阶段,在国内,互联网行业正处于原始积累阶段,或者叫圈地运动阶段。国内绝大多数公司是流量驱动型的,大家都是在玩营销,抢流量,很怕自己的流量跑到竞争对手那里去,觉得一旦丢了流量,无论自己做得再好都没人用了,但其实不是这样。另一个原因是很多公司的组织管理能力不足,国内很多公司的组织效率有问题,导致软件工程师白天不停地被打断,杂事一大堆,只能晚上加班。
进阶:软件工程师的四大台阶
新手阶段:新手阶段强调执行力,上级会明确地告诉你任务是什么,用什么样的方法达成什么样的目标,你按照方法一步步去做,保质保量完成就行了。
进阶阶段:进阶阶段强调设计能力,上级布置给你问题,你需要自己把具体的问题抽象、拆解,并独立设计解决方案。
高手阶段:高手阶段强调融会贯通能力,我们通常讲的架构师,也就是软件项目的总设计师,你需要把技术的演进、需求的变化、系统的发展等多个维度综合起来考虑。
大神阶段:大神阶段强调沉淀方法论,在这个阶段,大家公认你是这方面的权威,你对这个方向的判断是非常准确地,同时还能开创新领域,这些新领域的开创都是革命性的。
周期:是否存在35岁的坎儿
“35岁危机”更多和能力、水平相关。如果能力达到了,年龄就不是问题,但如果能力不到,到35岁就可能面临被淘汰的风险。为什么35岁是一个节点呢?因为一般来说,硕士毕业后工作也有10年了,如果工作10年还达不到资深工程师的水平,某种意义上被淘汰也会不可避免的。所有行业都不存在真正年龄的坎儿,只存在能力的坎儿。
挑战:持续学习是刚性要求
互联网和计算机领域的变化太快了,要想跟上这种节奏,软件工程师只能持续学习,必须与时俱进。
机会:工种多,且新工种频繁出现
软件工程师只是一个统称,其包含各种各样的工种。大致分为六个方向:交互、系统、算法、数据分析、测试、运维。知识积累促进技术进步,技术进步又不断催生出新的工种。
新手上路
选择平台:去面向未来、技术驱动的公司
计算机和互联网的发展太快,如果要选择,一定要选择走在未来航道上的快速发展的公司。因为高速成长的公司需要人才,它需要解决的问题也是新的,你会跟着公司一起去解决这些问题,你的能力会越来越强。要选择技术驱动,以技术文化为主导的公司。职业生涯的初期,把自己的基础打好,培养起扎实的编程能力和良好的职业素养。
认识自己:找到适合自己的路线
一个人要想认识自己,就得看清自己的特长、兴趣、热情等。
特长:找到你DNA中比别人强的东西,拿你的DNA和别人竞争。你要找到自己可以干成的事,找到别人找你请教的事。找到特长后,扬长避短就好。
兴趣:如果你没找到自己的特长,就找自己有兴趣的东西。什么叫兴趣?兴趣是再难再累都不会放弃的事,不怕困难,痴迷其中。
方法:如果你没有特长,也没有兴趣和热情,就要学方法。比如学习时间管理,学习做计划,学习统筹,学习总结犯过的错误,举一反三,学习探究事物之间的因果关系,等等。这是一些方法,你可以自己总结套路。
勤奋:如果你前三者都没有,你还能做的事就是勤奋勤奋注定会让你成为一个比较劳累的人,也是很有可能被淘汰的人。随着你的年纪越来越大,你的勤奋也会变得越来越不值钱。因为年轻人会比你更勤奋,比你斗志更强,比你要钱更少。勤奋虽然不值钱,但是只要你勤奋,至少能够自食其力。
知识都是死的,只要不怕困难总有一天会懂的。最可怕的是畏难,为自己找借口。
编码规范:不要逆着规范做事
为什么要有规范:为了提高效率。一家公司有很多软件工程师,以及日益增长的代码库,如果大家遵循同一套规范,你只需要花很少的时间就看懂,这对提升团队效率的影响是巨大的。作为新人,你在编码之前先熟悉这些规范,开发时严格遵守就好了,没必要逆着规范做事。
公司差异:即使没有规范,也得自我要求
要么花时间在写代码上,把代码质量提上去,要么花时间在后期修理上,靠运维去修补代码质量差的问题。
整洁代码:不是写出来的,而是读出来的
整洁代码不是写出来的,而是读出来的。不是写的人说自己的代码整洁就算整洁,而是读的人觉得整洁才算整洁。整洁代码的核心在于,你心里要装着将来要阅读这段代码的人,从方便阅读的角度去布局、设计。
代码注释:像说明书一样清晰
注释可以为读者提供足够的信息,让读者知道什么时候,怎么样使用这个类(方法),以及正确使用这个类(方法)的注意事项,而不是只是说明这个类(方法)是什么。
编码原则:教科书没有告诉你的”为什么”
避免重复原则:既能降低程序的复杂度,又能减少维护的工作量。单一职责原则:指的是一个类或者模块应该有且只有一个职责,简单来说就是各司其职,可以把复杂的问题简单化、模块化,从而降低问题的复杂度。高内聚、低耦合原则:内聚指的是一个模块内各个元素彼此结合的紧密程度,耦合指的是不同模块之间的依赖程度。高内聚,低耦合(也叫解耦)简单来说,是让每一个模块做到独立,做到精益求精,同时把模块间的耦合度降到最低,不会因为动了一个模块,而导致其他模块出现问题。开闭原则:对修改是关闭的,对扩展(协议)是开放的。因为同一个事情、同一个原因改变的东西放在一起,把会因不同原因改变的东西扔到外面去,最终保证稳定性和重用性。这些原则看上去或许不难理解,要用好却不那么容易。你可以先了解这些原则,不必急着马上使用,先在工作、学习中观察和总结别人的设计,再回过头来看看这些原则,然后适度地去实现。
解决问题:别把原则当教条
编码的原则很多,但有一些原则,不必拿它当教条,毕竟编码的最终目的不是符合哪项原则,而是解决实际问题。程序就是一个解决问题的手段,核心问题是:这个程序真正要解决的问题是什么。
全面思考:做测试比写代码难
一般来说,程序测试包括单元测试、功能测试、集成测试、非功能测试、回归测试等。
单元测试:一般是白盒测试,单元测试是离问题最近的地方,离问题越近,解决问题的成本越低。功能测试:一般是黑盒测试,一个功能是由很多个单元模块组装起来的,如果这些单元模块没有很好地配合在一起,相互矛盾,那整个功能也就不能正常实现了。功能测试并不关系具体实现是什么,而是把软件当成一个黑盒(不知道里面是什么)来进行测试。集成测试:集成测试其实是模块和模块之间或者系统和系统之间的测试,比如“订单”模块和“支付”模块之间的测试。集成测试的难点有两个,一个是怎么把众多系统组织搭建起来,另一个是怎么定位测试过程中遇到的问题。非功能测试:非功能测试主要用来检查软件应用程序的非功能性方面(性能、可用性、可靠性等),帮助降低与产品非功能性方面相关的生产风险和成本,优化产品的安装、配置、执行、管理和监控方式。回归测试:把之前做过的测试以及犯过的错误再测一遍,确保代码或配置的修改、需求的增加不会影响现有的功能。
程序测试:对软件工程师的基本要求
测试要自己做,不能让用户成为你测试工程师。除了测试基本输入以外,还要努力构想更多的边界条件。测试接口定义的程序语意,而不是当前实现的具体行为。对重要模块,编写的时候就要做到基本性能测试。对程序交付以后出现的问题和bug,要构建响应的测试程序并提交代码库,保证以后回归测试可以自动运行这个测试。
执行任务:从改bug开始
不要小看改bug,你只有学会在海量的数据里找到bug,学会修补,避免出错,才能知道代码在真实环境里是怎么运行的,才能找到一名软件工程师的工作体感。
定位bug:像侦探一样发现问题
模拟bug场景:想象一些怎样的代码才会实现bug导致的现象,然后顺着这个思路去找。二分法:先把代码一分为二,判断bug可能在前面一半还是后面一半,然后再分,再分,不断缩小范围。调试工具:针对某些bug使用调试辅助工具。比如IDE里的单步跟踪、多线程调试工具、性能调试工具、内存检测工具等。极限测试:用足够多的测试机,设置不同的极限条件进行测试,观察测试结果有什么规律。
修复bug:务必小心谨慎
正式修复前,要梳理整体设计、理解代码,保证你的操作不会影响到其他部分,不然很容易制造新的bug。
拆分任务:动手工作前,先做任务分解
当你碰到一个大的任务,有时甚至是难以完成的任务时,先去拆解,拆分成子任务,然后聚焦于每个子任务怎么完成和实现。将大目标拆分成小目标,大任务拆解成小任务,是软件工程师非常重要的工作能力。
阅读代码:重要的不是写代码,而是读代码
在阅读别人的代码的时候,有几类代码值得重点关注
被反复使用的代码:如果你读了很多代码,发现不同项目都在调用用一个函数,就要重点研究,看看它好在哪里——大家都在用的东西往往是标杆。
穿越时间的代码:如果一段代码用了10年、15年都没被淘汰,说明它的设计思想很棒。建议你关注这类代码的演进过程,尤其是它最旧的版本,最旧的版本往往反映了最核心的设计思想。
好调试的代码:调试代码也是观察、学习、长经验的过程,如果这些代码你调起来非常顺手,大概率是因为写代码的人为你准备好了基础工具。这时候你就要抓紧机会学习,看别人是怎么在早期搭建这些工具的,为以后自己写代码积累经验。
找到捷径:通读牛人代码
牛人的代码会非常清晰、明确、易用,自带使用说明。牛人写的代码会非常高效。牛人代码的通用型很高,可扩展。牛人的代码都是自带风格的。
追本溯源:多读文档,多读书
代码告诉你怎么做,文档告诉你为什么。书和文档是人对人说的话,代码是人对机器说的话。所以,如果你想知道人为什么要这么写,你就应该去看书,看文档。如果你想知道让机器干了什么,那你应该看代码。
重在过程:学习牛人的方法,别抄答案
跟高手学习是提升自己的捷径,但不意味着高手做一件事,你就照着抄。问题总会变,技术也在变,但优秀的解题思路不变。
在高手帮你review代码的过程中学习。接受批评,重点关注他指出了哪些问题,以及下次如何改进。跟高手一起解决难题。在遇到难题的时候,高手才会把最好的水平拿出来。
潜移默化:和优秀的人一起工作
要想方设法和公司里非常优秀的同事一起工作,长此以往,别人身上解决问题的方法和能力,会潜移默化地成为你的一部分。
亦师亦友:和身边的人搭档学
软件工程师有些时候是单枪匹马去战斗,难免有自己发现不了的问题,也会有陷入迷茫、难以抉择的时刻,如果你身边有一个值得信懒的伙伴,作为胖过这帮你指出问题、理清思路,就能免去很多烦恼。你也可以通过同样的方式帮助对方,两个人搭档学,双方都能有进步。
行业术语
接口( Interface ):
一种用来定义程序的协议,通过衔接软件系统中的不同组成部分,实现计算机软件之间的相互通信。
软件框架(Software Framework):
软件框架是一种抽象,它提供了构建和部署应用程序的标准方法,并且是一个通用的、可重用的软件环境;它提供了大型软件平台的一部分特定功能,以促进软件应用程序、产品和解决方案的开发。软件框架可能包括支持程序、编译器、代码库、工具集和应用程序接口(API),将所有不同的组件组合在一起,以实现项目或系统的开发。
库(Library):
又叫函数库,用于开发软件的子程序集合。它类似于一些已经开发的模块,就像积木模块一样,是构建整个软件的一些通用零件仓库,这些程序模块或零件可以让编程变得更为容易和有效率。库和可执行文件的区别是,它不是独立的计算机程序,而是向其他程序提供服务的代码。
API ( Application Programming Interface):
应用程序接口,它是一种计算接口,用来定义软件之间的交互、可以进行的调用(call)或请求(request)的种类,以及如何进行调用或发出请求,应使用的数据格式,应遵循的惯例等。
UI/UX:
UI(User Interface)指的是用户界面,也就是计算机软件或系统和用户进行交互的接口,比如命令行接口、图形界面、鼠标、触摸屏等。UX ( User Experience)指的是用户使用特定产品、系统或服务时的行为、情绪与态度。
协议(Protocol ):
网络协议的简称。网络协议是通信计算机双方必须共同遵守的一组约定,比如怎么建立连接、怎么互相识别等。只有遵守这些约定,计算机之间才能相互通信交流。代表协议有TCP协议、HTTP协议等。
日志(Log):
记录软件运行中发生的事件,或通信软件中不同用户之间的消息。日志有助于软件工程师了解系统运行的情况,并为调查或审计提供相应的数据支持。
Cookie:
HTTP协议中需要保存在用户端的非常小的数据,一般是用户的登录状态、用户的基本信息,或是一个访问令牌。
指针(Pointer):
编程语言中用来表示或存储一类数据类型及其对象或变量的内存地址,这个地址直接指向( pointsto)存储在该地址的对象。
输人输出(IO):
IO是 Input和Output的缩写,也就是输入输出。1/O设备就是输入输出设备。软件和系统的1/O指忙闲状态,如硬盘IO、网络I/O等。
封装(Encapsulation):
在面向对象编程方法中,封装是指一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。同时它也是一种防止外界调用端,去访问对象内部实现细节的手段,这个手段是由编程语言本身来提供的。
继承( Inheritance):
如果一个类别B“继承自”另一个类别A,我们就把B称为“A的子类”,而把A称为“B的父类别”,也可以说“A是B的超类”。继承可以使得子类具有父类别的各种属性和方法,而不需要再次编写相同的代码。
多态(Polymorphism):
指相同的定义在面对不同的实例时会有不同的执行行为。
递归(Recursion):
在数学与计算机科学中,指在函数的定义中使用函数自身的方法,也就是在运行的过程中调用自己。打个比方:从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚对小和尚说,从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚对小和尚说……这就是递归。
闭包( Closure ):
也称函数闭包,是一种在支持头等函数的编程语言中实现词法绑定的技术。在操作上,闭包是将函数与其环境一起存储的方式。也就是说,闭包是一个持久作用域,即使代码执行已经离开该语句块,它也保留了局部变量,支持闭包的语言有JavaScript,Swift 和 Ruby 。
垃圾回收( Garbage Collection):
一种自动的内存管理机制。当某个程序占用的一部分内存空间不再被这个程序访问时,这个程序会借助垃圾回收算法向操作系统归还这部分内存空间。垃圾回收器可以减轻软件工程师的负担,也减少程序中的错误。垃圾回收最早起源于LISP语言,目前许多语言如Smalltalk 、Java、C#和Go语言都支持垃圾回收器。
MVC模式( Model-View-Controller ):
软件工程中的一种软件架构模式,目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。这种模式把软件系统分为三个基本部分:
·模型(Model ):软件工程师编写程序应有的功能(实现算法等)、数据库专家进行数据管理和数据库设计(可以实现具 体的功能)。
·视图( View ):界面设计人员进行图形界面设计。
·控制器( Controller ):负责转发请求,对请求进行处理。
进程(Process):
程序被加载到内存里运行的实例,是系统进行资源分配和调度的一个独立单位,就是程序的一次执行过程。
线程(Thread):
进程中的一部分,是操作系统能够调度的最小单位,一个进程中可以包括多个线程。
同步( Synchronous):
在编程中,调用一个程序指令后必须等到这个指令返回后,才能往下执行后续的指令。这个程序指令可能是在操作一个外部设备,或是正在进行一次网络请求,需要很长的时间才能返回。于是,整个程序都需要停转——直到这个同步指令返回。
异步(Asynchronous ):
与同步相反。异步指的是不需要等待当前指令返回,就可以继续进行后续指令的执行。异步与同步各有各的好与不好。一般来说,同步在编程复杂度的处理上表现好,但在系统性能上表现不好;异步在系统性能上表现很好,但在程序的控制逻辑上会使复杂度提升。
主键(Primary Key ):
数据库中的一个概念,比如录人学生信息时,有姓名、性别、学号。以上三个信息可以组成一个数据列,这个数据列里唯一的标识是学号,那么学号就是这个数据列的主键。所以主键是一种唯一关键,一个数据列只能有一个主键且主键不能为空值。
外键( Foreign Key):
用于建立数据库表与表之间的链接,比如在一个班级中,学生的学号是主键,学生里有班长,“班长”就是外键——“班长”表示某个班级的班长的学号,它引用了“学号”属性。
事务(Transaction):
访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单元。
NULL指针:
空指针,指的是一个已宣告但并未指向一个有效对象的指针。许多程序利用空指针来表示某些特定条件,例如未知长度数组的结尾或某些无法运行的操作。空指针错误是一种常见的程序错误,一旦尝试访问空指针所指向之对象的情况发生,就会出现 NullPointerException(空指针异常)。
死循环(Infinit Loop):
又称无限循环,是指程序的控制流程一直在重复运行某一段代码,无法结束的情形。其原因可能是程序中的循环没有设结束循环条件,或是结束循环的条件不可能成立等。
CPU:
中央处理器,是计算机的主要设备之一,功能主要是解释计算机指令以及处理计算机软件中的数据。计算机的可编程性主要是指对中央处理器的编程。
GPU:
图形处理器,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上运行绘图运算工作的微处理器。
迭代( Iteration):
一种敏捷软件开发的方式,倡导用“小步快跑”的方式,把一个复杂的系统分解成一块一块很小的任务,然后快速地开发这些小任务,最终形成一个大的软件系统。迭代开发把传统上一次完整的交付,变成了若干次不完整的交付,这样一来,可以让用户看到整个开发过程,可以及时得到用户的反馈,从而可以让最终的交付物更接近用户的需求。
白盒测试( White-Box Testing ):
软件测试的主要方法之一,也称结构测试、逻辑驱动测试或基于程序本身的测试。测试应用程序的内部结构或运作,而不是测试应用程序的功能。
黑盒测试(Black-Box Testing):
软件测试的主要方法之一。测试者不了解程序的内部情况,不需具备应用程序的代码、内部结构和编程语言的专门知识。只知道程序的输人、输出和系统的功能,这是从用户的角度针对软件界面、功能及外部结构进行测试,而不考虑程序内部逻辑结构。
黑客(Hacker ):
真实的黑客主要是指技术高超的软件工程师。除了精通编程、操作系统的人可以被视作黑客,对硬件设备做创新的工程师通常也被认为是黑客,另外现在精通网络人侵的人也被看作是黑客。黑客分为白帽子、灰帽子和黑帽子:
白帽子描述的是正面的黑客,他可以识别计算机系统或网络系统中的安全漏洞,但并不会恶意去利用,而是公布其漏洞。这样系统将可以在被其他人(例如黑帽子)利用之前来修补漏洞。
灰帽子擅长攻击技术,但不轻易造成破坏,他们精通攻击与防御,同时头脑里具有信息安全体系的宏观意识。
黑帽子研究攻击技术非法获取利益,通常有着黑色产业链。