本书是程序员大牛陈皓的文章汇总,内容包括技术、沟通、工程师文化等,通读之后摘录其中精华部分。开卷有益,能读到摘录部分也会收益,当然最好是去读原文,知识转化效率更高。除本书之外,还有一些他的文章也非常值得阅读,包括程序员如何变现,如何学习英语主题等。
05 有竞争力的程序员
好的程序员不一定是技术最强的程序员,但一定是能够在不完美的工作环境下确保软件质量和工作效率
的程序员
真正的和谐不是只有一种声音,而是百家争鸣
英语对于程序员的价值永远不会被高估,甚至可以被视为超越别人的捷径
在做决定时,多关注自己能得到的东西
,而不是可能会失去的东西
四步实现竞争力跃迁
一、认知:掌握优质的信息源。关注信息渠道、信息质量、信息密度
二、知识:
- 知识树:想要系统地学习,就需要将其总结归纳成知识树或知识图。知识由多个知识板块组成,一个知识板块又包含各种知识点,一个知识点会引出相关的知识点,各知识点彼此交叉和依赖。
- 知识缘由
- 方法套路
三、技能
- 精益求精:用相同的方法重复训练无异于搬砖,是无法拥有最专业的技能的。要在每一次训练中寻找更好的方法,并且总结经验,从而使下一次训练更加完美和更有效率。
- 让自己犯错
- 找高手切磋
四、领导力
- 识别自己的特长和天赋
- 识别自己的兴趣和事业
- 让自己的习惯和方法变高级
06 成长中的问题
如何保证工程进度?
尽量将长线任务拆分为在一周内完成的多个子任务,因为越容易实现的任务越能调动执行力。可以在一周内完成的任务是最合适的。
08 高效学习
主动学习和被动学习
人的学习分为被动学习
和主动学习
两个层次。被动学习中听讲、阅读、视觉感受、观看演示这几种形式的学习内容平均留存率为5%,10%,20%,30%。主动学习中通过讨论、实践、教授给他人,分别能将学习的留存率提高到50%、75%、90%。
不要盲目追求阅读的速度和数量,这只会让人产生错觉,误以为这就是勤奋和成长。要思辨,要践行,要总结和归纳,机械的重复不会带来质的飞跃
。
学习的终极目的
一、学习是为了找到方法
学习的目的与其说是找到答案,不如说是找到方法。只有掌握思路和方法,才能真正拥有解决问题的能力。
二、学习是为了找到原理
学习不仅仅是为了知道,更是为了思考和理解。学习者不能停留于知识的表象,而是要通过表象去探索知识的本质与原理。一旦理解了某一个关键之处,你就会恍然大悟,因为所有的知识点已经融会贯通。
三、学习是为了了解自己
学习不仅仅是为了开阔眼界,更是为了通过探寻未知世界来了解自己。因此你需要多于不同的人交流,多于比自己聪明的人共事,多走出去了解外面的世界。这样你才会发现自己的短板和盲区,才会有动力审视和分析自己,从而明白如何提升自己。
四、学习是为了改变自己
很多时候,成长是通过改变来实现的。学习是改变我们的思考方式,改变我们的思维惯性,改变我们对与生俱来的直觉的依赖。总之,用于改变自己,才能持续成长。
高效学习的八种方法
一、挑选知识和信息源
二、注重基础和原理
三、使用知识地图 顺藤摸瓜,从知识树的主干开始做广度或深度遍历,就能得到整颗知识树。
四、系统学习
五、举一反三 举一反三包括:联想能力、抽象能力、自身能力。
六、总结和归纳
对看到和学习到的信息进行归纳、排列、关联,实现碎片信息的结构化,从中找到规律和相通之处,然后进行简化和提炼,最终形成一种套路、模式和通用方法。
七、实践出真知
成长的痛苦很大程度上来自实践,但只有痛苦才会让人反思,而反思最终决定了成长的高度
八、坚持不懈
坚持不懈的两个窍门:一是主动建立正向反馈,比如随时把成果晒出来让别人点赞,二是尽快把坚持编程习惯,让生物钟来参与管理
想做到高效学习,个人要有正确的认知、正确的态度、正确的观念和正确的方法,满足这几点要求似乎颇为不易。但程序员的日常工作正好是追求效率,代码如是,学习亦如是。
09 高效沟通
克服六种常见沟通障碍
系统的分析沟通中的主要的障碍:
- 信息不准确:信息本身是错误的,无论有多么高超的沟通技巧都无法准确表达。
- 信息过量:信息过多等于没有信息
- 没有交互:没有交互会影响主动沟通一方的积极性
- 表达方式:相同的沟通内容,采用不同的表达方式会产生截然不同的效果
- 二手信息:信息在传递过程中会自然损失,很多二手信息的准确度也不够
- 信息不对称:信息在网络通信过程中被恶意篡改后,就会造成信息不对称
无往不利的沟通技巧
- 引起对方的兴趣:找到对方的关注点,尽可能让沟通向其靠拢
- 围绕主题强化观点:表达之前要明白自己表达的目的,组织好要表达的内容,还要多中筛选有用的信息,进一步思考四否有更加简明、易懂的表达方式
- 基于数据和事实:沟通时应尽量弱化主观色彩,多用数据、例证、权威引用和客观经验来强调观点的权威性。
12 编程范式
编程范式是一套指导编程方法和风格的规则和约定。以下是一些常见的编程范式:
- 面相过程编程(Procedural Programming):
- 以过程或函数为基础,强调可执行语句的改变状态。
- 面向对象编程(Object-Oriented Programming, OOP):
- 以类和对象为中心,强调数据和处理数据的方法的封装。
- 函数式编程(Functional Programming, FP):
- 以数学函数为基础,强调无副作用的函数和不可变数据。
- 逻辑编程(Logic Programming):
- 以逻辑推理为基础,使用事实和规则来解决问题。
- 声明式编程(Declarative Programming):
- 强调“做什么”而不是“怎么做”,常见于SQL和HTML。
- 命令式编程(Imperative Programming):
- 强调“怎么做”,通过编写一步一步的指令来控制程序状态。
- 结构化编程(Structured Programming):
- 强调使用控制结构(如循环和条件语句)来编写清晰、可维护的代码。
- 并发编程(Concurrent Programming):
- 强调编写能够同时执行多个任务的程序。
- 并行编程(Parallel Programming):
- 强调利用多个处理器或核心来同时执行多个计算任务。
- 事件驱动编程(Event-Driven Programming):
- 程序的执行流程由外部事件(如用户输入、消息、信号等)触发。
- 元编程(Metaprogramming):
- 程序能够生成或修改其他程序或自身代码。
- 响应式编程(Reactive Programming):
- 强调异步数据流和变化的传播,常见于用户界面编程。
- 组件化编程(Component-Based Programming):
- 强调将程序分解为独立的、可重用的组件。
- 面向切面编程(Aspect-Oriented Programming, AOP):
- 允许将横切关注点(如日志记录、事务管理)与业务逻辑分离。
每种编程范式都有其适用场景和优势,开发者可以根据项目需求和个人偏好选择合适的范式。
函数式编程(Functional Programming,简称FP)是一种编程范式,它将计算视为数学函数的评估,并避免使用程序状态以及易变对象。与面向对象编程相比,函数式编程强调的是无副作用的函数和不可变性。
以下是函数式编程的一些核心概念:
- 纯函数:函数的输出只依赖于输入的参数,不依赖于任何外部状态或数据。纯函数不会产生副作用。
- 不可变性:在函数式编程中,数据是不可变的。一旦数据被创建,它就不能被改变。任何修改都会产生新的数据结构。
- 高阶函数:函数可以作为参数传递给其他函数,或者作为结果返回。这允许创建更抽象和灵活的代码。
- 函数组合:通过组合简单的函数来构建更复杂的函数。
- 递归:由于函数式编程语言通常不支持循环结构,递归是实现循环逻辑的主要方式。
- 模式匹配:许多函数式编程语言支持模式匹配,这使得处理数据结构(如列表、元组等)更加直观和简洁。
- 惰性评估:表达式不会立即求值,直到它们被需要时才会计算。这可以提高性能,尤其是在处理大型数据结构时。
- 类型系统:许多函数式编程语言具有强大的类型系统,可以帮助开发者避免错误,并提供更好的代码可读性。
函数式编程语言的例子包括 Haskell、Erlang、Clojure、Scala、F# 等。函数式编程范式在并发和并行计算中特别有用,因为它减少了由于共享状态和副作用引起的复杂性和错误。
13 软件开发与架构设计的原则
原则1:关注收益而不是技术
对于软件架构来说,最重要的是收益。以下几种收益很重要:
- 降低技术门槛,加快整个团队的开发流程
- 让整个系统运行得更加稳定
- 通过简化和自动化来降低成本
原则3:选择主流和成熟的技术
- 尽可能使用成熟和工业化的技术栈
- 选择全球流行的技术。只有具备普适性才有更强的生命力
- 尽可能不要自己造轮子,更不要魔改
原则4:完备性比性能更重要
系统的完备性和可扩展性在比支持多大的流量更重要
- 优先使用科学、严谨的技术模型
- 对于性能问题,解决方案和可采取的措施有很多。
原则5:制定并遵循标准规范
- paypal api 风格指南 https://www.infoq.cn/article/2017/09/paypal-api-guide
- 微软api指南 https://learn.microsoft.com/zh-cn/azure/architecture/best-practices/api-design
原则8:不要迁就技术债务
许多公司都存在大量的技术债务,具体表现如下:
- 使用老旧的技术
- 不合理的设计:如在网关中写大量业务逻辑、业务逻辑深度耦合
- 缺少配套设施:例如自动化测试,良好的软件文档
千万不要指望把一辆拖拉机改装成法拉利跑车
原则9:不要依赖经验
重复过去不可能进步,更新知识才能带来成长。因此不要依赖经验做决策,我建议正确的决策路径如下:
- 用足够的时间查找相关资料,如技术博客、文章、论文等
- 收集、对比各家公司和开源世界的做法
- 比较各种方案的优缺点后形成自己的决策
进步永远来自探索,套索的确要付出代价,但收益也更大。原则是软件开发和架构探索之旅的路线图,尊重与依赖原则让我们有可能在冒险中不犯大错,在抓住机会的同时不止于失去太多。
15 时间管理
时间的价值投资
- 把时间投资在打牢基础、熟读文档上是值得的
- 把时间花在解放生产力的事情上
- 提升自己在整个行业内的影响力
规划自己的时间
- 对于优先级相同的事情,建议采用最短作业优先的调度算法
- 代办清单中的任务不断减少才会给人以正向反馈
16 研发效率
关于研发效率的重要结论
- 软件工程师分工越细,团队就越没有效率。改善团队间的服务才是重中之重,服务不是我帮你做事,而是我让你做起事来更容易
- 如果非要在一个环节上较真,要么在设计和编码时认真,要么在测试上认真。否则,等到运维阶段处理故障,效率会大幅度下滑
- 小而精的团队+条件或资源受限是高效率的根本。团队小内耗才会小,条件或资源受限才会用最经济的手段做最有价值的事情,才会追求简单和简化
- 技术债是不能欠的,要果断地偿还技术债
- 软件架构上要送耦合,团队组织上要紧耦合
- 工程师文化是关键,重视过程就是重视结果
17 技术领导力
如何成为一个拥有技术领导力的少数人呢?
- 吃透基础技术
- 提高学习能力
- 坚持做正确的事情
- 高标准要求自己
提高学习能力
一、重视信息来源
通过优质的信息来源,可以更快地获取有价值的信息,从而提高学习效率。
二、学会关联思考
技术存在通用性和关联性,例如了解操作系统的网页的缓存后,需要思考他们之间的相同点和不同点。在遇到故障时,尽量把同类问题一次处理完成。
三、与高手交流
与高手交流不仅有助于了解热门技术方向和关键技术点,还可以让他们通过观察,揣摩高手的技术思维和解决问题的方式,提高自己技术的前瞻性和技术决策力。
19 绩效考核
对于劳动密集型公司适合KPI,对于知识密集型公司使用OKR
绩效沟通一定要放在平常的工作中,避免秋后算账
一个有价值的员工需要的能力包括:
- 学习新技能
- 提高专业水平
- 参加培训课程
- 与同事建立良好合作关系
- 积极参与团队合作
- 不断挑战自我
绩效考核不是最终目标,考核结果及其改进方法才是有价值的信息。通过结果不断改善并完善自我,这才是真正正确的绩效打开方式。
21 工程师文化
在软件工程领域提升效率有如下发力方向:
- 简化:简单意味着更容易被用户理解,也更易于维护和运维。
- 坚决推行自动化:编写程序的根本目的就是用自动化消除重复劳动。而且,很多事情本身更适合由机器来完成,人再多也无法像机器那样既好又快的完成任务。
- 以高效决策为原则:具体措施包括采用扁平化管理、用自动化工具取代支撑工作、采用不超过十人的全栈小团队、不按技能而是按负责的产品或功能进行人员分工、用开会表决提案、通过产品的目标和信条来减少沟通和决策的过程。
高质量的分享:
- 用问题吸引受众,带着受众一起思考
- 用问题模型框柱受众的思考范围,让受众聚焦
- 给出几种不同的解决方案,比较它们的优缺点,让受众参与解决问题的过程
- 提供最佳实践,方法论或套路。有前面的铺垫,受众更容易接受这些内容
- 整个过程能让受众体会到强烈的成长感和收获感