《不止代码》读书笔记
2021-04-24 11:08:44 0 举报
AI智能生成
工程师的世界,不止代码,还应有对未来的洞察与从容
作者其他创作
大纲/内容
技术变化那么快,程序员如何做到不被淘汰?
难道在技术领域内不断紧跟新潮,不断提升技能就是我的价值所在?那么我是技术的主人还是技术的奴隶?
如果不清楚自己的行为、目标、价值三者的关系,那么又何来重心?又如何能分得清重要性与优先级呢?
很多时候业务在我们脑海中存留的只是逻辑和流程,我们丢失的是对业务场景的感受,对用户痛点的体会,对业务发展的思考
业务、技术与软件系统的价值链
业务的目的就是解决人类社会与吃喝住行息息相关的领域问题,包括物质的需求和精神的需求,使开展业务活动的主体和受众都能得到利益。
技术则是解决问题的工具和手段。
软件系统,它的价值何在呢?说白了就是为了解决业务问题
业务领域与功能
服务能力
系统正确性( 程序能够正确表述业务流程,没有Bug)
可用性(可以7* 24 小时* 365不间歇工作)
大规模(高并发,高吞吐量)
价值链条:公司依靠软件系统提供业务服务而创造价值,程序员则是通过构建并持续演进软件系统服务能力以及业务功能以支撑公司业务发展从而创造价值。
正确的学习方式应该是将学习与具体业务场景结合起来,和公司通过软件系统开展业务服务而创造价值,程序员通过提升软件系统服务能力创造价值这一链条串接起来,从对这些价值产生帮助的程度去思考优先级。学习本身没有错,错的往往就是那颗初心。
价值驱动的架构
软件架构就是将人员、技术等资源组织起来以解决业务问题,支撑业务增长的一种活动。
架构师的一些具体工作任务
组织业务:架构师通过探索和研究业务领域的知识,构建自身看待业务的”世界观”。他会基于这种认识拆分业务生命周期,确立业务边界,构建出了一套解决特定业务问题的领域模型,并且确认模型之间、领域之间的关系与协作方式,完成了对业务领域内的要素的组织工作。
组织技术:为了能在计算机世界中运作人类社会的业务模型,架构师需要选用计算机世界中合适的框架、中间件、编程语言、网络协议等技术工具依据之前设计方案组织起来形成一套软件系统方案,在我看来软件系统就像是一种技术组织,即技术组件、技术手段依据某种逻辑被组织起来了,这些技术工具被确定了职责,有了明确分工,并以实现业务功能为目标集合在了一起。
组织人员:为了能够实现利用软件系统解决业务问题的目标,架构师还需要关注软件系统的构建过程,他以实现软件系统为号召,从公司组织中聚集一批软件工程师,并将这些人员按不同工种、不同职责、不同系统进行组织,确定这些人员之间的协作方式,并关注这个组织系统是否运作良好比如沟通是否顺畅、产出是否达到要求、能否按时间完成等。
组织全局,对外输出:架构师的首要目标是解决业务问题,推动业务增长。他非常关心软件的运行状况。因为只有在软件系统运行起来后,才能对外提供服务,才能在用户访问的过程中,解决业务问题。架构师需要关注运行过程中产生的数据比如业务成功率,系统运行资源占用数据、用户反馈信息、业务增长情况等,这些信息将会帮助架构师制定下一步架构目标和方向。
成本与收益
软件系统只有在运行的时候才能创造价值,也就是说软件系统能否7*24 小时* 365 天稳定的工作关系到公司的收益水平
软件系统的成本则体现在软件构建过程,这时候我们就能理解那些工程技术如项目管理、敏捷开发、 单元测试、持续集成、持续构建,版本管理等的价值了,他们有的是保证软件系统正确性,有的是为了降低沟通成本,有的是为了提升开发效率等但总的来说就是为了降低软件的构建成本
我们往往处在软件构建过程体系中的某个环节,我们可以基于成本与收益的关系去思考自己每一项技能的价值,学习新的有价值的技能,甚至在工作中基于成本与收益的考量选择合适的技术。
在逻辑不大发生变化的地方,没有必要去做过多的设计,应用各种花俏的设计模式等浪费时间
架构目标需要适应业务的发展
为了支撑业务增长,就是提升软件系统的服务能力
架构师需要审时度势,仔细衡量正确性、大规模、可用性三者的关系
没有确立架构目标导致浪费了组织很多资源,比如在之前的创业团队中,由于本人有一定的代码洁癖,经常会花费很多时间和同事计较代码质量,这样本可以更快上线的功能却需要被延迟,当时过度追求正确性的行为是与创业团队快速验证想法的业务需求不匹配的。
程序员想要工作出业绩,必须认清楚系统背后的业务价值,按价值去梳理工作优先级,而不是像我一般过度纠结细节,追求技术理想化。
成也分工,败也分工
程序员的迷茫因为长期埋没于软件世界的浩大的分工体系中,无法看清从业务到软件架构的价值链条,无法清楚定位自己在分工体系的位置,处理不好自身与技术、业务的关系所致,所以在这里我想谈谈分工。
软件系统生命周期
开发生命周期
测试生命周期
用户访问生命周期
软件运维生命周期
我的朋友吐槽我说你写了那么多代码然后并没有怎么样是非常有道理的,那是因为我只关注着做为流水工人的价值要求,看不到生态链最顶端的价值。
从价值出发-找寻学习与工作的新思路
明确自身的业务相关主体
找出你工作的协作关系网内的业务方和客户方,这样你就可以从客户方中找到离你最近的业务价值点,从你的业务方中挖掘更多的资源。
向前一步,为更大的价值负责
转变思维,从架构师的角度思考价值问题,看看能否将技术贯穿到业务、到用户、到最终的价值去
要把产品经理踢到运营位置去,把程序员踢到产品经理位置去,这样才是正确做事方式
像架构师一样思考,用价值找寻重心
人的迷茫是因为找不到重心,而价值的意义在于引导我们思考做哪些事情才能实现价值,先做哪些事情会比后做哪些事情更能创造收益
全局性思考,把遇到问题进行拆分,把学习到的事物串联起来,努力构成完整的价值链条。
学会连接,构建体系
互联网将我们连接至广袤的世界,却也把我们封闭在独属于自己的小世界里
人最终想理解这个世界还是需要依靠自身的行动与不同人之间建立联系,这也是一种摆脱流水线限制的有效方式
比如架构师,他是业务、技术、管理连接在一起的一种产物
应当树立自身的知识体系以吸收融合新知识,将孤立的概念连接起来,形成自身的价值链条
如何在阿里技术面试中脱颖而出?
招聘的目的
当今社会,技术已经成为影响商业成功的关键因素,工程师成为了这些公司最宝贵的财富,没有优秀的人组成团队来完成商业目标,公司根本不可能有今天的成就。
招聘,就是选择最优秀的人。
招什么样的人?
技能
工作项目经验,以及解决疑难问题的能力
必须很好的完成工作,这是最基本的要求,注意,是很好的完成,不是仅仅完成。
潜力
看潜力主要是基于候选人的之前的成长经历实事求是来看,过去的优秀经历才能给未来背书。
软实力
包含了性格,执行力,领导力等方方面面,它代表了候选人是否能快速融入团队,拿到结果,带领团队攻城拔寨,激励和影响身边的人变得更加优秀等等
招人上有一个对比的标杆,就是你招的人是不是比团队中同一等级中50% 的同学优秀,如果你觉得没有他们优秀,那不用纠结
面试的方法
面试不要做的事
问一些知道性的问题比如问知不知道这个API 干什么的,怎么调用,这个命令怎么用的,知道性的知识,google 一下或者认真看下文档就应该知道。
问一些特别复杂的问题比如问一个特别复杂的算法,问一个很抽象的大问题,短时间内很难给予回答。
问一些假设性的问题假设你参与了这个项目,你觉得哪几个地方需要优化。
面试应该做的事
问已经发生的事情
问题解决思路
少问多听
STAR 原则
处境(situation) - 在什么样的环境下
任务(task) - 接到了什么样的任务
行动(action) - 然后具体怎么落地的
结果(result) - 拿到了什么结果
假的STAR
描述含糊不清
只表达态度和看法
假设式描述
鉴别方式
更多的关心What/How/Why
细节!细节!细节!
其他Tips
你在面试别人,别人也在选择你
为未来招聘而不是现在
面试是一面镜子
技术人如何不断成长?
经验丰富,知识体系完整
经验能解决实际的问题,另外知识体系可以让你在遇到新的问题时举一反三,当然大公司和小公司要求的知识体系又不太一样,大公司更偏向一专多能的T 型人才,小公司更喜欢全栈
保持良好的习惯,不忘总结和提升
当我还是一个菜鸟的时候,当时的老板问了我一个问题,每周写周报的时候,想想自己这一周到底收获了什么,这给我留下了很深的印象
既然我每次面试别人都问你最近有研究什么新的技术或者看到什么有趣的文章没有的,那我自己是不是能这样要求自己呢?
不积跬步无以至千里,贵在坚持积累
使用开源项目的正确姿势,血和泪的总结
DRY,Don’t repeat yourself
选:如何选择一个开源项目?
聚焦是否满足业务?
案例:当时尝试一个社交类业务时,我们发现了TT(Tokyo Tyrant)这个开源方案,觉得既能够做缓存取代Memcached,又有持久化存储功能,可以取代MySQL,很牛逼,很高大上,于是就在业务里面大量使用了。
表现:
1. 不能完全取代MySQL,因此有两份存储,设计的时候每次都要讨论和决策
2. 功能上看起来很高大上,但相应的bug 也不少,而且有的bug 是致命的,例如所有数据不可读,后来是自己研究源码写了一个工具才恢复了部分数据。
3. 功能确实牛逼,但需要花费较长时间熟悉各种细节
后来我们反思和总结,其实当时的业务Memcached + MySQL 完全能够满足,且大家都熟悉,当时的业务完全不需要引入TT。
记住:不要过早优化,过早优化是万恶之源 ——《 UNIX 编程哲学》
聚焦是否成熟
很多新的开源项目往往都会声称自己比以前的项目更加牛逼:性能更高、功能更强、引入更多新概念。看起来都很诱人,但实际上都有意无意的隐藏了一个负面的问题:都更加不成熟!
不成熟的开源项目应用到生产环境,风险极大。轻则宕机,重则宕机后重启都恢复不了,更严重的是数据丢失都找不回了
考察是否成熟
1)版本号:一般建议除非特殊情况,否则不要选0.X 版本的,至少选1.X 版本的,版本号越高越好。
2)使用的公司数量:一般开源项目都会把采用了自己项目的公司列在主页上,公司越大越好,数量越多越好
3)社区活跃度:看看社区是否活跃,发帖数、回复数、问题处理速度等
聚焦运维能力
考察运维能力
1)开源方案日志是否齐全:有的开源方案日志只有寥寥启动停止几行,出了问题根本无法排查
2)开源方案是否有命令行、管理控制台等维护工具,能够看到系统运行时的情况
3)开源方案是否有故障检测和恢复的能力,例如告警、倒换等
用:如何使用开源方案?
深入研究,仔细测试
很多人用开源项目,其实是完完全全的“拿来主义”,看了几个Demo,把程序跑起来就开始部署到线上应用了
案例:我们有团队使用了elasticsearch,基本上是拿来就用,倒排索引是什么不太清楚,配置都是用默认值,跑起来就上线了,结果就遇到节点ping 时间太长,剔除异常节点太慢,导致整站访问挂掉。
可以从如下几方面进行研究和测试
1)通读开源项目的设计文档或者白皮书,了解其设计原理
2)核对每个配置项的作用和影响,识别出关键配置项
3)进行多种场景的性能测试
4)进行压力测试,连续跑几天,观察cpu、内存、磁盘io 等指标波动
5)进行故障测试:kill,断电、拔网线、重启100 次以上、倒换等
小心应用,灰度发布
案例:还是以TT 为例吧,其实我们在应用之前专门安排一个大牛看源码、做测试,做了大约1 个月,但最后上线还是遇到各种问题。线上生产环境的复杂度,真的不是测试能够覆盖的,必须小心谨慎。
不管研究多深入、测试多仔细、自信心多爆棚,时刻对线上要有敬畏之心,小心驶的万年船
先在非核心的业务上用,然后有经验后慢慢扩展
做好应急,以防万一
案例(此案例是听说的):某个业务使用了MongoDB,结果宕机后部分数据丢失,无法恢复,也没有其它备份,人工恢复都没办法,只能接一个用户投诉处理一个,导致DBA 和运维从此以后都反对我们用MongoDB,即使是尝试性的。
因为一次故障就完全反对尝试是有点反应过度了,但确实故障也给我们提了一个醒:对于重要的业务或者数据,使用开源项目时,最好有另外一个比较成熟的方案做备份,尤其是数据存储。
改:如何基于开源项目做二次开发?
保持纯洁,加以包装
从内到外全部改一遍,将其改造成完全符合我们业务需求。但这样做有几个比较严重的问题:
1)投入太大,一般来说,redis 这种级别的开源方案,真要自己改,至少要投入2 个人,搞个1 个月以上
2)失去了跟随原方案演进的能力:改的太多的话,即使原有开源项目继续演进,我们也无法合并了,因为差异太大。
建议是不要改动原系统,而是要开发辅助系统: 监控,报警,负载均衡,管理等
发明你要的轮子
其实选与不选开源项目,核心还是一个成本和收益的问题,并不是说选择开源项目就一定是最优的方案,最主要的问题是:没有完全适合你的轮子!
软件领域和硬件领域最大的不同就是软件领域没有绝对的工业标准,大家都很尽兴,想怎么玩怎么玩,不像硬件领域,你造一个尺寸与众不同的轮子,其它车都用不上,你的轮子工艺再高,质量再好也是白费;软件领域可以造很多相似的轮子,也基本上能到处用,例如你把缓存从Memcached 换成Redis,不会有太大的问题
不止代码
如何快速成长为技术大牛?
梦想总是要有的,万一实现了呢
几个典型的误区
拜大牛为师
大牛很忙,不太可能单独给你开小灶,更不可能每天都给你开1 个小时的小灶。建议多给团队培训,一个月一次的频率
一般要找大牛,都是带着问题去请教或者探讨。影响力是大牛的一个重要指标
大牛不多,不太可能每个团队都有技术大牛
明白“主要靠自己”这个道理,通过请教大牛或者和大牛探讨来提升自己,但大部分时间还是自己系统性、有针对性的提升
业务代码一样很牛逼
技巧
使用封装和抽象使得业务代码更具可扩展性
通过和产品多交流以便更好的理解和实现业务
日志记录好了问题定位效率可以提升10 倍
写业务代码类似于游戏打怪升级
业务代码都写不好的程序员肯定无法成为技术大牛,但只把业务代码写好的程序员也还不能成为技术大牛
上班太忙没时间自己学习
认为自已不够聪明,自已不够努力。在中国的环境下,技术人员加班多,导致没有额外的时间可以进行学习。
误区的看法
上班做的都是重复工作,要想提升必须自己额外去学习
学习需要大段的连续时间
首先我们应该在工作中学习和提升,因为学以致用或者有实例参考,学习的效果是最好的;其次工作后学习不需要大段时间,而是要挤出时间,利用时间碎片来学习。
正确的做法
Do more
场景示例:工作中去了解与之相关的内容,等待机会的出现。
要想有机会,首先你得从人群中冒出来,要想冒出来,你就必须做到与众不同,要做到与众不同,你就要做得更多!
改变方法
熟悉更多业务,不管是不是你负责的;熟悉更多代码,不管是不是你写的
需求分析的时候更加准确,能够在需求阶段就识别风险、影响、难点
问题处理的时候更加快速,因为相关的业务和代码都熟悉,能够快速的判断问题可能的原因并进行排查处理
方案设计的时候考虑更加周全,由于有对全局业务的理解,能够设计出更好的方案
熟悉端到端
示例:了解整个系统、业务整体运行脉络
自学
示例:成熟的公司,框架和组件进行大量封装,写业务代码所用技术甚少。但我们要明白“唯一不变的只有变化”,框架有可能要改进,组件可能要替换,或者新公司没有框架和组件的时候,要你从头开始来做。
Do better
世界上没有完美的东西,你负责的系统和业务,总有不合理和可以改进的地方。
示例
重复代码太多,是否可以引入设计模式?
系统性能一般,可否进行优化?
目前是单机,如果做成双机是否更好?
版本开发质量不高,是否引入高效的单元测试和集成测试方案?
目前的系统太庞大,是否可以通过重构和解耦改为3 个系统?
阿里中间件有一些系统感觉我们也可以用,是否可以引入 ?
Do exercise
光看不用效果很差,怎么办?
学习了jvm 的垃圾回收,但是线上比较少出现FGC 导致的卡顿问题,就算出现了,恢复业务也是第一位的,不太可能线上出现问题然后让每个同学都去练一下手,那怎么去实践这些jvm 的知识和技能呢?
Netty 我也看了,也了解了Reactor 的原理,但是我不可能参与Netty 开发,怎么去让自己真正掌握Reactor 异步模式呢?
看了《高性能MySQL》,但是线上的数据库都是DBA 管理的,测试环境的数据库感觉又是随便配置的,我怎么去验证这些技术呢?
框架封装了DAL 层,数据库的访问我们都不需要操心,我们怎么去了解分库分表实现?
方法
Learning
看书、google、看视频、看别人的博客都可以,但要注意一点是“系统化”,特别是一些基础性的东西
Trying
解答前面提到的很多同学的疑惑的关键点,形象来说就是“自己动手丰衣足食”,也就是自己去尝试搭建一些模拟环境,自己写一些测试程序
Jvm 垃圾回收
Reactor 原理
MySQL
框架封装了DAL 层
用浏览器的工具查看HTTP 缓存实现
Teaching
经过Learning 和Trying,能掌握70% 左右,但要真正掌握,我觉得一定要做到能够跟别人讲清楚。
前面我讲的都是一些方法论的东西,但真正起决定作用的,其实还是我们对技术的热情和兴趣
毕业3 年,为何技术能力相差越来越大?
如何避免让战术上的勤奋掩盖战略上的懒惰,使得真正掌握好的知识点慢慢生长,连接,最终组成一张大网。
关键问题点
为什么你的知识积累不了?
知识的积累出了问题,没有深入理解好,自然就不能灵活运用,也就谈不上解决问题
每个人的理解能力不一样(智商),绝大多数人对知识的理解要靠不断地实践(做题)来巩固
同样实践,效果不一样?
假如碰到一个问题,身边的同事解决了,而我解决不了。那么我就去想这个问题他是怎么解决的,他看到这个问题后的逻辑和思考是怎么样的?
知识+ 逻辑就基本等于你的能力,知识让你知道那个东西,逻辑让你把东西和问题联系起来。
这里的问题你可以理解成方案、架构、设计等。
系统化的知识哪里来?
知识之间是可以联系起来的并且像一颗大树一样自我生长,但是当你都没理解透彻,自然没法产生联系,也就不能够自我生长了
好的逻辑又怎么来?
实践
复盘
讲个前同事的故事
最佩服的是解决问题的能力,好多问题其实他也不一定擅长,但是他就是有本事通过Help、Google 不停地验证、尝试就把一个不熟悉的问题给解决了
应用刚启动连接到数据库的时候比较慢,但又不是慢查询
通过tcpdump 来分析网络通讯包
专业的DBA 可能会通过show processlist 看具体连接在做什么
MySQL 的老司机,一上来就知道skip-name-resolve 这个参数要改改默认值
这三种方式都解决了问题,最后一种最快但是纯靠积累和经验,换个问题也许就不灵了;第一种方式是最牛逼和通用,只需要最少的业务知识
复盘别人的操作,之后寻找背后思考的逻辑
空洞的口号
举一反三、灵活运用、活学活用、多做多练。但是只有这些口号是没法落地的,落地的基本原则就是前面提到的,却总是被忽视了
什么是工程效率,什么是知识效率
有些人纯看理论就能掌握好一门技能,还能举一反三,这是知识效率,这种人非常少。
大多数普通人都是看点知识,然后结合实践来强化理论,要经过反反复复才能比较好地掌握一个知识,这就是工程效率,讲究技巧、工具来达到目的
学霸都还能触类旁通非常快地掌握一个新知识,非常气人。剩下的绝大部分只能拼时间+ 方法+ 总结等,也能掌握一些知识。
知识分两种
一种是通用知识(不是说对所有人通用,而是说在一个专业领域去到哪个公司都能通用),另外一种是跟业务公司绑定的特定知识。
程序员吃的是青春饭?本质上取决于……
我与团队同学探讨了职业发展规划的问题
有些同学表示希望后续能进一步在技术领域(或管理方向)有进一步的积累
有的同学表示希望在新的一年能具有更好的技术影响力,自己能做一些技术决定,去影响其他人,这样自己会很有成就感。
问题
你希望技术能进一步积累,那你积累的方向和期望达到的结果分别是啥?
你希望能有技术决策,希望有影响力,你觉得应该如何做到?是希望通过岗位任命的方式吗?
你觉得是否成功的标志,就是今年或明年得到晋升吗?
职业发展的两个阶段
大学毕业3 到5 年
基础的Java 知识
高质量代码进阶知识
常用的主流框架
系统设计与算法知识
其他知识
快速地完成这些基础知识的学习,并能在项目中快速地学以致用。自身能获得比较高的成就感
大学毕业5 到10 年
年龄并不是问题的真正原因。真正的原因还是在于自身“竞争力”是否符合这个年龄所应该具备的
需要的技能
能对所负责领域的业务特点、发展趋势、友商竞争分析有很好的洞察?
《咨询的奥秘》、《探索需求》、《系统化思维导论》
《成为技术领导者:掌握全面解决问题的方法》
服务于特定领域的客户,我们需要能了解我们的客户企业架构、业务知识。
TOGAF、NGOSS、ITIL 等业务理论以及业务知识
是否有必要能将自己对于市场的洞察转换成业务规划,并能向自己的老板(或者投资人)说清楚、讲明白?
《金字塔原理》、《博弈论》、《影响力》
你看我们是否需要能将业务趋势、客户痛点进行业务建模好让团队的PD、技术都能理解?
《领域驱动设计: 软件核心复杂性应对之道》、《实现领域驱动设计》、《企业应用架构模式》、《恰如其分的软件架构》
做完业务设计后,开始要带着团队做技术方案设计、接口设计以及编码实现等
《PMBOK 指南》、《敏捷软件开发》、《人月神话》、《程序开发心理学》
有国际化要求的公司,还需要再学习英语
需要有个好的身体,还需要经常锻炼,学习科学的健身
团队磨合的挑战、技术方案上的争执、平台优先 or 业务优先的博弈、低落的团队氛围、个人的低谷等等
0 条评论
回复 删除
下一页