三阶段进化:调试,编写与运行代码
阶段一:调试代码 Debugging
逐渐降低使用Debug 功能的频率
阶段二:编写代码 Coding
“信、达、雅”
信,指不违背原文,不偏离原文,不篡改,不增不减,要求准确可信地表达原文描述的事实。
程序员需要深刻地理解用户的原始需求。虽然需求很多时候来自于需求(产品)文档,但需求(产品)文档上写的并不一定真正体现了用户的原始需求。
只有真正挖掘并理解了用户的原始需求,最后通过编程实现的程序系统才是符合 “信” 的标准的。
达,指不拘泥于原文的形式,表达通顺明白,让读者对所述内容明达。
在编程上就是在说程序的可读性、可理解性和可维护性。
代码规范和风格的编程约束都是在约定 “达” 的标准。
雅,指选用的词语要得体,追求文章本身的古雅,简明优雅。
雅的标准,应用在编程上已经从技艺上升到了艺术的追求,只有先满足于 “信” 和 “达” 的要求,才有余力来追求 “雅” 。
阶段三:运行代码 Running
基准测试和测试人员做的性能测试不同。
测试人员做的性能测试都是针对真实业务综合场景的模拟,测试的是整体系统的运行;
基准测试是开发人员自己做来帮助准确理解程序运行效率和效果的方式,当测试人员在性能测试发现了系统的性能问题时,开发人员才可能一步步拆解根据基准测试的标尺效果找到真正的瓶颈点,否则大部分的性能优化都是在靠猜测。
Bug的空间属性:环境依赖与过敏反应===程序对运行环境的依赖、反应及应对。
经常被测试或产品经理要求修改和返工的 Bug,属于沟通理解问题,并非真正的技术性 Bug。
提高沟通理解能力,凡事多想一步,多琢磨,多反思
从 Bug 出现的 “时空” 特征角度可以分为两类:
空间:环境过敏
时间:周期规律
环境过敏
环境,即程序运行时的空间与依赖。
运行环境发生变化,程序就出现异常的现象,我称其为 “程序过敏反应”。
都是局部的小问题,引发程序过敏反应,再到连锁效应。
写日志阻塞,进程挂起【程序的编写未考虑硬盘 I/O 阻塞导致的挂起异常问题】,然后引发调用链路处理上的连锁雪崩效应,其影响效果就是整个链路上的系统都在报警。
应对之道:
1. 了解环境
通常服务端可控,客户端不可控
必须关心与程序运行直接相关联的那一层环境
比如后端 Java 程序,Java 运行在 JVM 中,则JVM 提供的运行时配置和特性就是必须要关心的一层环境
对环境的理解是渐进式的,不可能一下子就完整掌握,全方位,无死角。
当出现了因为环境产生的过敏反应时,收集足够多相关的信息才能帮助快速定位和解决问题,这是“运维” 类代码需要提供的服务。
2. 收集信息
收集信息,不仅仅局限于相关直接依赖环境的配置和参数,也包括用户输入的一些数据。
针对客户端编,对运行环境进行的自检测和自适应代码。
服务端相对可控,但面临“三高” 要求,即:高可用、高性能、高扩展。面向失败设计和编码(Design For Failure)则是服务端的要求。
总结:空间即环境,包括了程序的运行和依赖环境;
环境是多维度、多层次的,你对环境的理解越全面、越深入,那么出现空间类 Bug 的几率也就越低;
对环境的掌控有广度和深度两个方向,更有效的方法是先广度全面了解,再同步与程序直接相连的一层去深度理解,最后逐层深入,“各个击破”。
Bug的时间属性:周期特点与非规律性
周期特点
周期特点,是一定频率出现的 Bug 的特征。比如OutOfMemory,内存泄露。
Bug 因为会周期性地复现,相对还是容易捕捉和解决。
非规律性
解决麻烦,采用工具,直接引入代码 Profiler 等性能剖析工具,就可以准确地找到有性能问题的代码段
神出鬼没
能称得上神出鬼没的 Bug 只有一种:海森堡 Bug(Heisenbug)。
“海森堡不确定性原理”认为观测者观测粒子的行为会最终影响观测结果。
海森堡效应来指代那些无法进行观测的 Bug,在生产环境下不经意出现,费尽心力却无法重现的 Bug。
海森堡 Bug 的出现场景通常都是和分布式的并发编程有关。
所有 Bug 的解决之道只有两类:事后和事前。
事前预防与埋伏===运维代码
事后,就是指 Bug 出现后容易捕捉现场并定位解决的
Bug的反复出现:重蹈覆辙与吸取教训
1. 重蹈覆辙
重蹈覆辙型错误,总结下来大概都可以归为以下三类原因:
a. 粗心大意
自己检查自己的代码会更难发现这些缺陷
b. 认知偏差
认知偏差,是重蹈覆辙类错误的最大来源。
比如 Java 自带线程池有三个重要参数:核心线程数(core)、最大线程数(max)和队列长度(queues)
类库的实现是核心线程(core)满了就会进队列(queues)等待,直到队列也满了再创建新线程直至达到最大线程数(max)的限制。
数据库连接池就是先创建连接到max,如果没有可用连接时,就等待maxWait时间直到有空闲连接或抛出异常。
【惯性思维也容易导致犯错】
c. 熵【shāng】增问题
程序规模变大,复杂度变高之后,再去修改程序或添加功能就更容易引发未知的 Bug。
2. 吸取教训
a. 优化方法
粗心大意,可以通过开发规范、代码风格、流程约束,代码评审和工具检查,单元测试等工程手段来加以避免。
认知偏差,一般没什么太好的自我发现机制,但可以依赖团队和技术手段来纠偏。经验教训总结和团队内部分享
熵增问题,业界不断迭代更新架构模式
微服务本质上就是将一个大系统的熵增问题,局部化在一个又一个的小服务中。
b. 塑造环境====大韩航空===帮助下级员工克服权利距离,建立下级敢于在上级面前维护自己的意见的环境【塑造一个正视错误,改正错误的环境 】
需要更深刻地认识问题的本质
亚马逊(Amazon),严重的故障需要写一个 COE(Correction of Errors)的文档,这是一种帮助去总结经验教训,加深印象避免再犯的形式。其目的也是为了帮助认识问题的本质,修正真正的错误。
需要建立和维护有利于程序员及时暴露并修正错误,挑战权威和主动改善系统的低权力距离文化氛围,
即推崇扁平化管理和 “工程师文化” 的关键所在。
一旦系统出了故障非技术背景的管理者通常喜欢用流程、制度甚至价值观来应对问题,
而技术背景的管理者则喜欢从技术本身的角度去解决当下的问题。
我觉着两者需要结合,站在更高的维度去考虑问题:规则、流程或评价体系的制定所造成的文化氛围,对于错误是否以及何时被暴露,如何被修正有着决定性的影响。
允许犯错,强调每个人应反思错误,不容许一错再错。建立了一个“错误日志”,用来记录每人犯过的错误和造成的不良后果,在错误中成长。
人固有缺陷,程序固有 Bug;吸取教训避免重蹈覆辙,除了不断提升方法,也要创造环境。
根源:计划的愿景——仰望星空
我们做系统应用服务时总是需要考虑各种意外和异常事件发生,一般至少提供主备方案。
于人生而言,保持持续学习,与时俱进,追求成长,这其实也是一种主备方案:主,指当前支撑生活的工作;备,是通过持续学习,同步成长,保持核心能力的不断积累与时间的付出来获得一份备份保障,以避免 “主” 出现意外时,“备” 的能力已被时代淘汰。
生涯发展
生涯的四个维度:高度、宽度、深度和温度。
高度:背后的价值观是影响与权力。代表性关键词有:追逐竞争、改变世界。
深度:背后的价值观是卓越与智慧。代表性关键词有:专业主义、工匠精神。
宽度:背后的价值观是博爱与和谐。代表性关键词有:多种角色、丰富平衡。
温度:背后的价值观是自由与快乐。代表性关键词有:自我认同、精彩程度。
计划就是在系统地探索生涯,甚至人生的无限可能性。
回首无悔
“我们最后悔的是没做什么,而不是做过什么。”
“理想的自己” 就是你想要成为什么人。
“义务的自己” 就是你应该干什么。
人生的征程中,先是恐惧驱动,地狱震颤了你,想要逃离黑暗深渊;后来才是愿望驱动,星空吸引了你,想要征服星辰大海。
“你内心肯定有着某种火焰,能把你和其他人区别开来”
方式:计划的方法——脚踏实地
如何确定目标、制定计划,以达成愿景
目标:
Heartfelt 衷心的,源自内心的【兴趣、偏好与心灵深处的内核。】
Animated 活生生,有画面感的【目标形成的愿景是否足够清晰,在头脑中是否直接就能视觉化、具象化。】
Required 必须的,需求明确的【一种成长性的自我实现需求在激发】
Difficult 困难的,有难度的【太难或太易不合适,选择舒适圈外的一两步】
假如我不做现在的事情,那么你最想做的是什么?通常你当前最想做的可能并不能解决你的谋生问题,那么在这两者之间的鸿沟,如何去搭建一条桥梁,可能就是一个值得考虑的目标。
Easy choices, hard life. Hard choices, easy life.【容易的选择,艰难的生活;艰难的选择,轻松的生活。】
方法
从时间维度,可以拟定 “短、中、长” 三阶段的计划:
短期:拟定一年内的几个主要事项、行动周期和检查标准。
中期:近 2~3 年内的规划,对一年内不足以取得最终成果的事项,可以分成每年的阶段性结果。
长期:我的长期一般也就在 5~7 年周期,属于我的 “一辈子” 的概念范围了,而 “一辈子” 当有一个愿景。
从路径维度,要求每一个员工把自己的年度目标、实现方法及标准写信告诉自己的上级。上级也会根据这个年度目标来考核员工【SMART原则】。
SMART 也是 5 个英文词的首字母缩写:
Specific 具体的
Measurable 可衡量的
Achievable 可实现的
Relevant 相关的
Time-bound 有时限的
按 SMART 原则方法使用计划跟踪表的优点是:简单、直接、清晰。缺点是:即使百分百完成了所有的计划,也都是预期内的,会缺乏一些惊喜感。
制定目标和计划会有意识地选择有一定难度的来挑战,所以实际还很难达成百分百。
【年初按照50周排列计划,一年值得放进计划表的就那么几件事,每件事又可以分解为具体的几个可量化的任务,再分解到一年 50 周】
计划的本质,是盘点当下,了解自己,审视自己。
【补充】建议每天辅助以重要和紧急为二维坐标,建立计划管理。
紧急且重要的事情,马上做
紧急而不重要的事情,少做
重要而不紧急的事情,重点做
不重要也不紧急的事情,不做
变化
计划是准备,变化才是永恒,而计划就是为了应对变化。
变化来了,就把它装进计划表中,看这样的变化会排在哪个位置,和之前计划表前列的事情相比又如何。
如果变化的事总能排在顶上,那么说明你的人生实际就在不断变得更精彩,做的事情也会让你更激动。
而如果变化老是那些并不重要却还总是紧急的事情,老打断当下的计划,那么也许你就要重新审视下你当前的环境和自身的问题了。
计划表就成了变化表,人生无法机械执行,只有准备应对。
检视:计划的可行——时间与承诺
个人年度计划完成情况,完成70% 算作“完成”,另外的30%留给变化
时间与周期
做计划不能靠模糊的感觉,而是需要精确理性的计算。
短期:完成事项,获取结果,得到即时反馈与成就感(比如:写这个专栏)。
中期:学习技能,实践经验,积累能力(比如:学一门语言)。
长期:建立信念,达成愿景(比如:成长为一名架构师)。
【选择合适的事项,匹配正确的周期,建立合理的预期,得到不断进步的反馈。】
兴趣与承诺
凡事从 0 分做到 50 分,靠的是直觉和经验;从 50 分到 90 分,就要靠技艺了。
要坚持长期的刻意练习,唯一可靠的办法就是对其做出郑重的承诺。
通过兴趣来启动,但要靠承诺才能有效地执行下去。
感兴趣和做承诺的差别在于,只是感兴趣的事,到了执行的时候,总可以给自己找出各种各样的原因、借口或外部因素的影响去延期执行;
而承诺就是这件事是每天的最高优先级,除非不可抗力的因素,都应该优先执行。
兴趣让计划更容易启动,而承诺让计划得以完成。
人是有惰性的,单靠兴趣很难支撑计划执行。可以建立承诺,倒逼完成计划。
一年下来,重要的不是开启了多少计划,而是完成了几个计划。
【总结】
可行的计划应该是:有限的时间,适合的周期,兴趣的选择,郑重的承诺。
评估:计划的收获——成本与收益
计划:
做计划自是为了有收获,实现愿景也好,获得成长也罢,每一份计划背后都有付出与收获的关系。
如果计划的收益不能高于执行它付出的成本,那么其实这种的计划就几乎没有执行价值。
成本与机会
计划即选择,而但凡选择就有成本。
从经济学思维的角度,做计划就是做选择,选择了某些事情;
选择了这些事情,就意味着放弃了另外可能做的事情,这里面的成本就是机会成本。
机会成本是放弃的代价,选择这些事情从而放弃的其他可能选项中拥有最高价值的事情。
真正的自由,是在所有时候都能控制自己。
计划才能给你真正的自由,你对计划的控制力越强,离自由也就更近了。
结果与收益
计划得到了执行,产生了预期的结果,才会有期望的收益。
障碍:从计划到坚持,再到坚持不下去的时候
设定一个计划并不困难,真正的困难在于执行计划。若你能够坚持把计划执行下去,想必就能超越绝大部分人,因为大部分人的计划最终都半途而废了。
酝酿
计划的目标是源自内心的,但也是有难度的,若是轻而易举的事情,也就不用计划了。
人是有惰性的,内心里其实并不愿意去做,这是我们感性的部分。但理性告诉我们,去完成这些计划,对自己是有长远好处的。这,就是冲突的地方。
启动
启动期,是计划从静止到运动的早期阶段;这阶段的最大障碍是所谓的“最大静摩擦力”
“最大静摩擦力”:要让一个物体动起来所需要的推力,比它开始运动后要大一些。“万事开头难”。
执行
执行期,是计划实现过程中最漫长的阶段;这阶段的最大障碍就是容易困倦与乏味。
坚持,特别是长期的坚持,是需要动力的,而动力来自目标和意义。而获得目标与意义的最好方式是讲好一个故事。
如果计划实行不下去,可以尝试把计划切割再小一些,如把登山的计划切割成登台阶。
成功的企业家会把未来的愿景包进一个美好的故事里,让自己深信不疑;
然后再把这个故事传播出去,把所有相信这个故事的人聚在一起去追寻这个故事;最后,这个关于未来的故事就这样在现实中发生了。
我要成为什么样的人,我想要怎么样,我打算怎么写我自己的故事。
挫败
挫败,不是一个阶段,而是坚持路上的一些点;正是在这些点上你遭遇了巨大的挫败感。
遭遇挫败,你会进入一种心情与情绪的低谷,这个时候有很高的概率做出放弃的决策。
不要在挫败的情绪低谷期进行任何的选择与决策。可以暂时放下这件事,等待情绪回归到正常,再重新理性地评估计划还是否该坚持。
每经历一次挫败之后,你还选择坚持,那么就已经收获了成长。
要想想清楚,哪些是真正客观的障碍?哪些是主观的退却?
执行:从坚持到持续,再到形成自己的节奏
在执行过程中,容易半途而废的一个很可能的原因在于节奏出了问题。
计划的节奏
计划的节奏总是会被现实的“意外”打断,每次计划的节奏被打断后,都会陷入一种内疚的挫败感中;
然后就强迫自己去完成每日计划列表中的每一项,否则不休息,最终也许是获得了数量,但失去了质量
喜欢 = 熟悉 + 意外
计划更多是给予预期和方向,去锚定现实的走向,但在行进的过程中,“意外” 难免会出现。所以,你要从心理上接受它,并从行为上合理地应对它。
按程序员的思考方式,我会为所有计划中的事情创建了一个优先级队列,每次都只取一件最高优先级的事情来做。
不要尝试去清空队列,以免精疲力竭
第二天,这件事依然会进入队列中,并不会因为中断过就放弃了。只要在队列里,没有其他事情干扰,到了对应的时间段就会去执行。
他人的节奏
每个人都会有自己不同的节奏,这需要自己去摸索、练习,并慢慢提升。
有时太急迫地“追赶”,最后反而阻挡了你稳步前进的步伐和节奏。
匀速奔跑的人是那些可以耐住寂寞的人,试想当你按照自己的节奏持之以恒默默努力地去做一件事情时,是极少会有伙伴同行的,
因为大家的节奏各不一样,即便偶尔会有也只是陪你走过一段。
自己的节奏
找到并控制好自己的节奏,才能长期匀速地奔跑,才能更高效地利用好自己的时间和注意力。
把自己的时间安排成一段一段的,高度集中【可以处理或思考一些比较难的事情】和高度分心交叉分布。
如果感觉是比较疲惫,不要马上开始了,这种状态下立刻去小憩片刻或者闭目养神一段时间(20 ~ 30 分钟),进入一种浅睡眠状态再恢复过来,精力的恢复感会比较好。
我们要找到自己的节奏。节奏是我们能长期持续奔跑的很重要的因素。
【OK留言】
自己10公里跑步的时候的感受是,当自己因为疲惫身体难受想放弃的时候,放慢脚步慢慢跑用心体会想放弃的感受和身体的难受,然后慢慢的跑,想着再坚持会儿,慢慢适应这感觉,5分钟后就没事。主要是这个体会的感觉。当你没有放弃并坚持完成了这个10公里的跑步计划后,你会有一种巨大的成就感。有了这一次的重大体会后,你的身体里就埋下了对抗放弃这种想法的种子。多跑几次10公里以后,你这个想法逐渐成熟后,当面对生活的各种挑战有巨大的帮助。