阿里工程师的自我修养总结

以下内容均来自阿里工程师的自我修养,阿里工程的自我修养下载 密码 6x71
以下总结只是书中的一小部分,希望让更多的技术人看到这本书,提升自己的思维和眼界
自我总结:

  1. 不要盲从书本获取其他地方抄袭,要构建自己的知识树,习惯性总结。强烈推荐Xmind或者processon
  2. 多问一下为什么”,并一直“刨根问底
  3. 知识量是爆炸的,但是原理绝对是可控的,原理性的东西比直接的知识有更强的复用度
  4. 注重自己思考力的提升,考察方向:广度、深度、速度
  5. 学习需要系统化,看书或者官方文档,并非一篇文章
  6. 视频可以快速入门,快速开发,视频推荐Pluralsight
  7. 关注技术新闻,twitter 上技术大牛 & 参加技术大会
  8. 做项目,写 Demo,看源码
  9. 基础知识是决定你能否干到退休的关键因素
  10. 越是基础,越是几十年不变的基础越是重要;
  11. 一个人走得快,一群人走得远
  12. 当你不舒服,难受或陷于困境时,应该停下来思考
  13. 掌握搜索信息的有效方式

程序员成长、发展的常见问题:

  • 你自认为付出了跟别人同样的努力,但是你的成长确实更慢一些,比如学得比
    别人慢,排查问题比别人慢,出方案老是有漏洞等等;

  • 你觉得你只是在疲于应付需求,自己做的事情完全没有技术含量(很多人觉得
    自己做的业务开发就是没有技术含量,但我认为每个领域都有自己的技术含
    量,只是你有没有 get 到);

  • 你发现总是在犯同样的错误,或者做的事情不断地在同一个水平循环;

  • 每次要晋升的时候,你发现根本讲不出来(很多人会认为是表达能力问题,但
    是我认为不是);

  • 当你换到一个新的领域,你发现自己的经验好像用不上;

  • 你一直很难搞懂老鸟说的“认知升级”到底是什么概念?不同级别的技术思维
    能力到底有什么差别?为什么晋升的是他,而不是我?

  • 只要把事情搞定了,成长是自然而然的事情——可能过段时间,你发现之前犯
    过的错误,后来一个都没有避免;

  • 我只要努力,996 甚至 007,我就能够成长得比别人快——可能你发现你干
    得最多,但是并没有拿到最好的结果;

  • 我尽力了,还是比别人慢,应该是我智商确实差一些——恭喜你,其实大家的
    智商并不会有太大差别;

  • 别人表现好,或者晋升了,只不过是比我表达能力更强而已——我可以负责任
    地告诉你,这并不是仅仅是表达能力的问题。

“思考力”是程序员需要具备的一种至关重要的素质

 先抛一个非常重要的结论:“思考力”是程序员需要具备的一种至关重要的素质。
掌握了思考力,你就掌握了在互联网领域,这种高度“智力密集型”行业成长的钥
匙。上面这几个成长的问题和误区,跟没有掌握思考力有着非常重要的关系,而且我
发现所有发展比较顺畅的同学,他们的思考和学习能力是非常强悍的
 我个人在工作中,一直有意或者无意地锻炼自己和团队同学的思考力,包括哪些
是对我们最重要的思考力,如何去训练思考力,有一些心得,希望能够分享给大家

关于思考力
思考力是一门很深的学问,包括认知科学,心理学、教育学、逻辑学,如果要系
统化学习,是需要看很多书的,我推荐以下几本:
1.《金字塔原理:思考、表达和解决问题的逻辑》-[ 美 ] 芭芭拉·明托,这本书系
统阐述了思考、表达和解决问题的逻辑,也是麦肯锡的思维能力基础,算是一本比较
标准的思考力教材;
2.《麦肯锡教我的思考武器》- [ 日 ] 安宅和人,作者根据自己在麦肯锡公司工作
时积累的丰富经验以及脑神经学的专业背景,设计出一套极具逻辑性的问题解决思维
模式;
3.《思维的本质》-[ 美 ] 约翰·杜威 ,这本书是美国著名教育家约翰·杜威的代
表作,阐述了思维训练的基础理论和实践;

有哪些对程序员最重要的思考力

原理性思维:找出知识背后的原理

有的人会说,为什么要思考原理,而不是直接掌握知识就可以了?我只需要会用
就行了啊。
我们先来举一些技术方案设计的案例
什么订单创单要先 create,然后 enable ?
这其实是一种采用二阶段提交解决分布式事务的思路,只是从一般的事务框架
延展到交易领域;

  • 业务系统中为什么要使用消息?
    因为消息使用的是观察者模式,观察者模式的好处是可以实现多个消费事务与触发事务的解耦;
  • 为什么业务系统中会使用 DTS 来做补偿?
    这本质上是一种最终一致性 BASE 理论解决分布式事务的一种思路;
  • 为什么更新数据的时候一定要在 sql 中加上版本比对或者状态比对?
    这本质上是一种借助 DB 实现的乐观锁机制。
    进一步,你会发现再大到系统架构和顶层设计的案例:
  • 比如阿里系的技术框架 NBF、TMF、早期的 webx,各类框架设计理念,逃
    不脱设计模式,比如开闭原则,模板方法、责任链、工厂模式、开闭原则;
  • 不管是底层中间件,错综复杂的业务系统,在设计的时候永远无法离开核心的
    业务建模,比如实体与实体关系的构建;在分析这类系统的设计思想时,你会
    发现最好的工具就是 UML !

实际上除了软件领域的原理,还有商业设计的原理,比如案例:

  • 所有的售中退款前必须要先取消履约,所有的履约过程中发生缺货都需要退
    款,为什么?因为交易的基本原则是:“钱货平衡”,钱和货的变更必须是最终
    同步的(允许短期的不平衡),你掌握了钱货平衡的基本原理,交易中的很多复
    杂的流程设计就很好理解了;
  • 在设计财务系统、库存系统时候,业务流程、业务逻辑可能非常复杂,导致你
    晕头转向,这时候“有借必有贷,借贷必相等”的财务平衡性原理就发挥作用
    了,你只要知道这个原理,很快就能看懂各类财务流程、库存流转流程,以及
    各类数据对账逻辑;
  • 在我的领域“高可用线下收银系统”进行线下系统容灾的时候,有各种容灾方
    案的设计,会员容灾、商品容灾、交易容灾、支付容灾……不同的容灾手段看
    起来让你眼花缭乱,但是他们有没有共同遵循的原则呢?有,这就是“让消费
    者最快速度完成交易,但保持最后追溯的能力”。你只要 get 到这个基本原理,
    设计各类容灾策略就会得心应手了

此外,我们的工作流程、管理手段,同样也蕴含着深层的原理,非常有意思,大
家可以抽空仔细推敲一下,比如:

  1. 为什么团队机制要透明?沟通要透明?
  2. 为什么要有 owner 意识,都是在工作,owner 意识会有什么不同呢?
  3. 为什么管理者不能管得太细,也不能放羊?到底哪些该管,哪些不该管?

所以,掌握了知识背后的原理,带来的好处是:

  • 软件系统的复杂度越来越高,我们所面对的场景越来越多,掌握原理实际上
    可以大幅度降低我们对于知识的记忆量,知识量是爆炸的,但是原理绝对是
    可控的!
  • 原理性的东西比直接的知识有更强的复用度! 记住最核心的原理,当你面对
    新的场景时,你会惊喜地发现,你的理解速度大大加快!这个点大家应该有体
    会,比如可能之前我们都学习过 dubbo 等底层的 RPC 通信框架的基本原理,
    但是你如果仅了解了他的基本用法,你会发现对你现在做业务系统没有什么帮
    助!但是,当你了解的是 dubbo 如何寻址,如何做容灾,如何做扩展,你再
    去做业务系统,发现设计原理是一样的,并没有本质区别!这样你之前研究中
    间件的设计思想就可以快速用到业务系统上面。
  • 另外探求原理的过程,本身很有乐趣! 这是一个非常有价值的思维训练过程,
    不断对系统设计思想、业务设计思想、做事情的工作方式,追寻背后的原理,
    并找到他们之间的共性,在我看来非常有乐趣,一段时间训练以后,你会发现
    你看透本质的能力越来越强!

好,那么我们程序员的工作中, 究竟有哪些与原理性知识是需要我们掌握的呢?
按我们团队的实战经验来看:

  1. java,linux,数据结构和算法,数据库,网络通信与分布式计算的原理,这
    几类是比较重要的基础知识,我们在做方案设计、编码、问题排查中会运用
    得很多;
  2. 设计模式,UML 这个是对系统架构设计必要要掌握的知识,当你经历了很多
    大规模的软件系统设计,回到根本上,你会发现逃不出这一块的理论和工具;
  3. 领域性的基本原则,比如我们上面提到的“钱货平衡”,“财务平衡公式”,
    “线下收银让消费者最快速度走人”,这种逻辑需要大家 get 到这些领域性的
    设计原理,甚至自己去总结出这种原理;
  4. 关于管理学,人际沟通,心理学的一些基本原理,大家可以按照自己的实际
    需求去看一下。

如何在工作中学习和运用这些原理,我觉得有一个最佳实践

  1. 首先,对你可能用到的领域知识,建立一个基本的概念。 看书,看文章,找
    行业资深的人去聊,都可以得到。注意,这里需要有一个基本的概念就可
    以,这样你在有可能 touch 到这些原理的时候,你会有意识,也不至于花很
    多时间;
  2. 在实践中,有个意识是“多问一下为什么”,并一直“刨根问底”,最终肯定能
    够追查到背后的最终原理;这里面还要注意思考一下,为什么在这个地方会
    运用这个原理,也就是找到“场景” 和“原理” 的关联关系,这样你的理解
    会更加深刻;
  3. 了解了原理以后, 在实践中运用一下,这样你对这个原理的理解就会非常深
    刻,并且你知道如何去运用这原理;
  4. 如果这是一个非常重要的原理,建议大家如有余力去结合经典的书籍系统化
    学习

结构化思维:构建自己的知识树

知识树要解决的问题,我们看一些场景:

  1. 为什么我知道很多东西,但是当场景来的时候老是会记不起来使用;
  2. 完成一个方案你只能想到一些点状的手段,还有其他方案被漏掉了;
  3. 讲一件事情的时候逻辑非常混乱,前后没有逻辑性关联。

是很有可能你的知识都是知道的,为什么会出现这种悲剧?
这个就跟大脑中的知识结构有关,这是知识学习中“索引” 没有建立,也就是说,
你的知识只有点,没有线
! 大家想一想,把东西乱七八糟地丢在房间中,到用的
时候没有查找的线索和路径,怎么找得到呢?
来看一下我们工作场景的结构化的典型案例,大家体会一下:

项目中测试 MM 提了一个 bug,我总结出来的比较标准的问题定位步骤:

  1. 确认刚才是否有过代码变更和部署,因为有比较高的概率是刚才变更的代码
    又搞坏了……
  2. 追踪链路日志看链路是否有异常;
  3. 通过 RPC 的控制台调用看接口输入输出是否符合预期;
  4. 追踪关键方法的入参和出参,看是否有问题;
  5. 定位到方法细节后,推理逻辑是否有问题;
  6. 如果无法通过推理,那就最后一招,回放异常流量 debug,这样肯定能够找
    到原因。

某个链路耗时比较长,需要进行性能优化,我的分析步骤是

  1. 通过实际流量制造一个耗时较高的 trace;
  2. 进行 trace 分析,看清楚耗时最多的原因,然后按优先级进行排序;
  3. 针对对原因找解决方案,可能的方案有:
    i. 减 少 数 据 访 问 次 数 或 者 计 算 量, 常 见 手 段 是 增 加 cache: 线 程 内 的
    invokeCache;分布式缓存 tair;页面缓存……
    ii. 增强处理速度,比如多线程加速;
    iii. 减少循环调用次数,比如请求合并后再分发;
    iv. 减少数据处理范围,比如减少查询内容,异步加载分页;
    v. 逻辑简化,比如逻辑进行优化,或者非核心逻辑异步化等;
    vi. ……
  4. 改掉以后,回放同样的 case,看性能消耗是否满足预期,不满足预期继续
    优化;

如何熟悉一个新系统, 我的步骤是:

  1. 要一个测试账号,把相关功能走一遍,这样能非常快地了解一个系统的功能;
  2. 看关键的核心表结构,这样可以快速了解系统的领域模型;
  3. 根据功能步骤找到系统对外的接口列表,了解系统的 L0 业务流程;
  4. 下载系统工程,熟悉整个工程结构和模块职责;
  5. 以一个最重要的流程为入手点,阅读代码,看清楚核心的执行逻辑,可以变
    看边画时序图;
  6. 制造一个 debug 场景,以 debug 方式走一遍流程,这样可以实际加深一下
    对系统的理解;
  7. 做一个小需求,掌握相关的流程和权限

下单这里来了一个新的需求,出一个技术方案的步骤

  1. 看清楚之前的需求,把这个需求所在的场景和链路大致阅读一遍,搞懂;
  2. 找到需求的变化点;
  3. 分析变更的方案,涉及的内容可能会有:
    i. 数据结构会不会变,如何变;
    ii. 交互协议会不会变,如何变,交互协议分为:端和组件要不要变;和下游
    接口要不要变;
    iii. 执行逻辑会不会变,如何变,执行逻辑变更的细化考虑点:是否变更域服
    务;是否变更流程编排;是否变更主干逻辑;是否变更扩展点是否变更扩
    展点的内部逻辑,变更内部逻辑的时候,又可以进一步拆解:
    a. 重构原有的方法,覆盖之前的逻辑,那就需要进行回归;
    b. 通过逻辑路由到新的方法,这里需要增加路由逻辑;
  4. 稳定性方案;
  5. 发布方案;

可以看到,面对任何一个场景,不管多大多小,我们所需要掌握的知识或者技能
都可以构建成一个树结构,同类之间是顺序关系,上下之间是父子关系(或者粗细颗
粒度)。

当这个树在大脑中构建起来以后,你会发现你做什么事情都是有一个明确的分析
和执行逻辑
,不太可能产生遗漏和混乱!

那么如何训练出自己的知识树呢

  1. 一定要总结出自己的知识树,而不要盲从书本上的或者别人的,为什么呢?
    一是因为人的思维速度和习惯、技能有一定差异,不一定每个人都是一样
    的;二是如果没有内化别人的知识成为自己的知识,这棵树不太能够很熟练
    地运用;
  2. 习惯性总结, 做完任何一个事情,都习惯性地回顾一下,往自己的树上面挂
    新东西,这个是构建知识树的必备手段,这个总结不需要花很多时间,比如
    做完事情后花个几分钟回顾一下就可以,但是需要坚持;
  3. 推荐一个很常见的工具: xmind, 把自己的树记录下来;
  4. 训练自己的思维习惯和做事方式变得结构化, 当你做事情的时候,习惯性用
    树的方式推进,强迫自己按照这个方式来

扩展性思维:举一反三,拓展思维

扩展性思维的核心目标是提升我们思维的广度, 也就是让我们的知识树变得更加
开阔;
我在工作中总结出来的扩展性思维的两个关键的扩展方向:
(1)举一反三:解决同类型的 N 个问题
举一反三的好处是:“我们能否用同样的知识和手段去解决类似的相关联的几个
类似问题”,先举一些案例:
• 当发现某个系统的 jvm 参数配置存在一个错误配置,不是仅仅修复这个系统
的 jvm 配置,而是把负责的几个系统都检查一下是否需要统一修改;
• 系统中存在某个 bug 导致产生了脏数据,不是直接订正已发现的脏数据,而
是根据特征拉取出所有的脏数据,进行一次性处理;
这种思维方式的特征是举一反三,触类旁通,相当于产生批处理的效果,可以大
大提升解决问题的效率,避免重复处理

寻求更多的可能性:拓展解决问题的不同手段

拓展思维常见的手段是:是否能够换更多的理解方式,或者更多的解法,举一些
案例:
• 产生故障的时候,快速止血除了回滚以外,还有哪些方案?如果故障处理经验
丰富的人一定知道,除了回滚,其实还有系统降级,运营活动降级等多种方案;
• 除了写更加健壮的代码,还有哪些手段都可以提升系统的容错性?还有数据监
控,单据闭环等多种手段;
当解决问题的手段更多了,思维就开阔了

抓重点思维:提升效率,方便记忆和传递

当我们发现知识树构建起来以后,怎么样使得记忆和使用的效率变高?而且对外
传递的时候更加容易让人理解?抓重点思维要解决的场景是:

  1. 如果每件事情都按照知识树方式做,效率可能不会特别高,有更快的办法么?
  2. 在对外沟通表达的时候,要表达核心思想,否则别人会很难理解你的表达内
    容;比如大家再晋升答辩、项目汇报的时候一定会有体会。
    解决这两类困惑, 核心思路是要抓住重点和脉络
    但是抓住重点和知识结构化之间并不矛盾,而且我认为是有先后次序的, 一定要
    先建立知识结构化,然后才能从里面筛选出重点, 否则知识的体系是不完整的

反思性思维:思考哪里可以做得更好

思性思维是提升知识质量和深度的一个关键能力。 因为只有不断反思才能让下
一次在上一次基础上升级, 而不是重复循环。
常见的反思案例:
• 有个问题我查了 2 个小时,师兄只花了 10 分钟,这是为什么呢?是他的业务
比我熟悉?思路比我清晰?还是知道某个我不知道的工具?一定要找到关键的差异
点,然后弥补掉这个差距;
• 一个项目项目做完了,从方案设计,研发过程,质量保障上面,哪些地方下次
可以做得更好?找到不足,下次避免;
对于我们技术团队,哪些内容值得反思,我们团队的经验是:

  1. 这个项目商业价值 OK 吗?是否取得了预期的效果?
  2. 项目中我的能力有哪些问题,有哪些做得好的和不好的?
  3. 系统设计的优势和不足?
  4. 项目质量保障是否可以做得更好一些?
  5. 研发过程和项目管理是否有不足?

反思性思维的实践,注意有两个点比较关键:

  1. 反思性思维最重要的意识:做事情的过程总有优化的空间,每次都要有进步;
    如果没有这种心态,那么很难持续地进行反思;
  2. 反思是一种习惯和潜意识,可以在不经意之间经常进行, 其实不需要很形式
    化地花很多时间,有时候做完一个事情,习惯性思考一下就可以。

架构评审需要注意的事项

  1. 技术选型: 为什么选用 A 组件不选用 B、C 组件,A 是开源的,开源协议是
    啥?基于什么语言开发的,出了问题我们自身是否能够维护?性能方面有没
    有压测过?这些所有问题作为技术选型我们都需要考虑清楚,才能做最终决定
  2. 高性能: 产品对应的 TPS、QPS 和 RT 是多少?设计上会做到的 TPS、
    QPS 和 RT 是多少?而实际上我们整体随着数据量的增大系统性能会不会出
    现明显问题?随着业务量、数据量的上升,我们的系统的性能如何去进一步
    提高?系统哪个环节会是最大的瓶颈?是否有抗突发性能压力的能力,大概
    可以满足多少的 TPS 和 QPS,怎么去做来实现高性能,这些问题都需要我
    们去思考。
  3. 高可用: 是否有单点的组件,非单点的组件如何做故障转移?是否考虑过多活
    的方案?是否有数据丢失的可能性?数据丢失如何恢复?出现系统宕机情况,
    对业务会造成哪些影响?有无其他补救方案?这些问题需要想清楚,有相应
    的解决方案。
  4. 可扩展性: A 和 B 的业务策略相差无几,后面会不会继续衍生出 C 的业务策
    略,随着业务的发展哪些环节可以做扩展,如何做扩展?架构设计上需要考
    虑到业务的可扩展性。
  5. 可伸缩性: 每个环节的服务是不是无状态的?是否都是可以快速横向扩展的?
    扩容需要怎么做手动还是自动?扩展后是否可以提高响应速度?这所有的问
    题都需要我们去思考清楚,并有对应的解决方案。
  6. 弹性处理: 消息重复消费、接口重复调用对应的服务是否保证幂等?是否考虑
    了服务降级?哪些业务支持降级?支持自动降级还是手工降级?是否考虑了
    服务的超时熔断、异常熔断、限流熔断?触发熔断后对客户的影响?服务是
    否做了隔离,单一服务故障是否影响全局?这些问题统统需要我们想清楚对
    应的解决方案,才会进一步保证架构设计的合理性。
  7. 兼容性: 上下游依赖是否梳理过,影响范围多大?怎么进行新老系统替换?新
    老系统能否来回切换?数据存储是否兼容老的数据处理?如果对你的上下游
    系统有影响,是否通知到上下游业务方?上下游依赖方进行升级的方案成本
    如何最小化?这些问题需要有完美的解决方案,稍有不慎会导致故障。
  8. 安全性: 是否彻底避免 SQL 注入和 XSS ?是否有数据泄露的可能性?是否
    做了风控策略?接口服务是否有防刷保护机制?数据、功能权限是否做了控
    制?小二后台系统是否做了日志审计?数据传输是否加密验签?应用代码中
    是否有明文的 AK/SK、密码?这些安全细节问题需要我们统统考虑清楚,安
    全问题任何时候都不能轻视。
  9. 可测性: 测试环境和线上的差异多大?是否可以在线上做压测?线上压测怎
    么隔离测试数据?是否有测试白名单功能?是否支持部署多套隔离的测试环
    境?测试黑盒白盒工作量的比例是怎么样的?新的方案是否非常方便测试,
    在一定程度也需要考量。
  10. 可运维性: 系统是否有初始化或预热的环节?数据是否指数级别递增?业务
    数据是否需要定期归档处理?随着时间的推移如果压力保持不变的话系统需
    要怎么来巡检和维护?业务运维方面的设计也需要充分考虑到。
  11. 监控与报警: 对外部依赖的接口是否添加了监控与报警?应用层面系统内部
    是否有暴露了一些指标作监控和报警?系统层面使用的中间件和存储是否有
    监控报警?只有充分考虑到各个环节的监控、报警,任何问题会第一时间通
    知到研发,阻止故障进一步扩散。

代码评审注意事项

  1. 确认代码功能: 代码实现的功能满足产品需求,逻辑的严谨和合理性是最基本
    的要求。同时需要考虑适当的扩展性,在代码的可扩展性和过度设计做出权
    衡,不编写无用逻辑和一些与代码功能无关的附加代码。
  2. 编码规范: 以集团开发规约、静态代码规约为前提,是否遵守了编码规范,遵
    循了最佳实践。除了形式上的要求外,更重要的是命名规范。目标是提高代
    码的可读性,降低代码可维护性成本。
  3. 潜在的 BUG: 可能在最坏情况下出现问题的代码,包括常见的线程安全、业
    务逻辑准确性、系统边界范围、参数校验,以及存在安全漏洞 ( 业务鉴权、灰
    产可利用漏洞 ) 的代码。
  4. 文档和注释: 过少(缺少必要信息)、过多(没有信息量)、过时的文档或注释,
    总之文档和注释要与时俱进,与最新代码保持同步。其实很多时候个人觉得
    良好的变量、函数命名是最好的注释,好的代码胜过注释。
  5. 重复代码: 当一个项目在不断开发迭代、功能累加的过程中,重复代码的出现
    几乎是不可避免的,通常可以通过 PMD 工具进行检测。类型体系之外的重复
    代码处理通常可以封装到对应的 Util 类或者 Helper 类中,类体系之内的重复
    代码通常可以通过继承、模板模式等方法来解决。
  6. 复杂度: 代码结构太复杂(如圈复杂度高),难以理解、测试和维护。
  7. 监控与报警: 基于产品的需求逻辑,需要有些指标来证明业务是正常 work
    的,如果发生异常需要有监控、报警指标通知研发人员处理,review 业务需
    求对应的监控与报警指标也是 Code Review 的重点事项。
  8. 测试覆盖率: 编写单元测试,特别是针对复杂代码的测试覆盖是否足够。

发布计划评审

涉及到 10 人日以上的项目,必须有明确的发布计划,并组织项目成员统一参加
项目发布计划 review,发布计划主要包含如下几点:
1) 明确是否有外部依赖接口,如有请同步协调好业务方;
2) 发布前配置确认包括配置文件、数据库配置、中间件配置等各种配置,尤其
各种环境下的差异化配置项;
3) 二方库发布顺序,是否有依赖;
4) 应用发布顺序;
5) 数据库是否有数据变更和订正,以及表结构调整;
6) 回滚计划,必须要有回滚计划,发布出现问题要有紧急回滚策略;
7) 生产环境回归测试重点 Case。

你可能感兴趣的:(阿里工程师的自我修养总结)