0%

最近研发老大牵头组织了异常关于根因分析的讨论,目的在于让大家学会做根因分析,因为往往大家都是直接下结论(给答案),既容易发生矛盾也同时也没有解决根本问题。

现状

1.当有问题出现时,往往根据现象再加上以往的经验或者直接拍出一个结论,这种情况在短期内的效果是可以的,但是从长期来看会掩盖掉很多底层的问题。结果就是问题该出还出,不仅没有提升团队的效率反而降低了团队的效率。

2.当问题出现时就代表甩锅以及互怼的开始,没有经过根因分析,上来先下个结论,开始界定责任,然后开始扯皮。

根因分析

问题描述

(什么时间*-什么地点-什么产品-什么人物-发生什么故障现象-*造成什么影响)

示例

1
2
3
4
5
6
7
时间:2019-09-02
地点:XX现场
产品:XX产品/XX版本
发现人:XX现场交付人员
故障现象描述:客服在正常登陆系统提单的时候报错,并且提交不了工单
【帮助】如有多个故障现象,应分别描述;
结果影响:系统XX时间不可用,导致客户非常不满,造成XXX损失
过程还原

直接叙述工作过程,有问题的环节或阶段,什么人,做了什么事,当时是怎么考虑的,在这个动作后结果是什么。

问题定位

描述最终定位到的直接原因是什么。举个例子,比如某段代码编写存在XXX错误

技术根因分析

引入环节:

  1. 产品设计是否有问题?
  2. 需求分析是否有问题?
  3. 设计环节是否有问题?
  4. 代码编写是否有问题?
  5. 其他

流出环节:

  1. 各评审环节是否有遗漏?
  2. 是否进行研发自测?
  3. 测试场景、测试用例是否覆盖全?
  4. 是否进行了系统测试?
  5. 其他?

确定关键根因是什么

如果有多个根因在逻辑层次上相同,则取关键的原因,根因应该是具体的、客观的、在目前组织能力下可被改进的。

管理根因分析
  • 流程/制度原因:
  • 组织因素:
  • 执行原因:

【帮助】流程/制度方面:考虑组织管理上是否有合适的流程、指导书、管理Checklist;

组织因素方面:考虑人员分配、个人技能、培训、组织环境等原因;

执行方面:考虑计划、监控、沟通方面的原因。

纠正、预防措施
根本原因 措施类型 措施内容 责任人 预定完成日期
技术根因: 例如,XX特性,在大规格、灵活配置等方面需求设计不充分 纠正措施 例如:对XX特性组织进行重新设计,刷新XX方案 2018/11/1
预防措施 例如:更新××技术规范、工具、checklist等等
管理根因:组织管理、流程方面的原因,比如xx,没有按照流程,但是最终还是交付了。 纠正措施
预防措施

小结

上诉的内容,关键还是在于给一个框架,让问题发生人,根据框架的引导,能比较深刻的挖掘出问题的根因,按此框架填写后,往往会伴随着评审,最终判断分析的彻底性以及合理性。

当然这只是一种方式,一段时间实践下来,其实是有助于减少问题发生率以及增加个人问题的处理成本从而倒逼相关人员注意到质量的重要性。

本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。

最近个人成长KPI抓的严,为了能心安理得的继续IT事业,不管强迫自己多花时间在个人成长上。

刚好瞌睡遇到枕头,这两天经少数派,关注了B站的锦堂生活空间

看到他的一个视频**”我保持高效率奋斗的5大因素”**,个人感觉是对我有用的。

一个远大的理想

  1. 理想要可衡量
  2. 要足够大
  3. 分段立目标,逐个完成

将所在领域内的偶像贴在工作墙上

  1. 时刻提醒自己,不放松。

绝对不要进入自己不感兴趣的领域

  1. 没有所谓的能力不足,只有你对这件事感不感兴趣
  2. 一定要确保你你再做着你自己喜欢的事情

学习新知识的时候,必须要不断的停下来思考

  1. 思考自己的缺点,怎么应用到我得生活和工作中。
  2. 费曼学习法,怎么让自己和别人明白,复杂的知识简单化
  3. 将简单化的知识点以口语化写进笔记本

准备一个笔记本记录激励你的话或者成功人士的小视频

在开始奋斗之前花几分钟时间看激励自己的东西,让自己亢奋起来

源引:

据说再2016年我就开始接触git,当时还用台式机、笔记本作为两个用户进行git的一些实践和原理的了解,但是正儿八经在项目中用git还是现在,经过一年多的实践呢,入了一些坑所以觉得是时候展现真正的技术了,简单积累一下我比较常用的。

** git提交规范 **

这块是很重要很重要的,在代码评审、问题追溯、代码回滚、代码培训等的时候都需要用到这个东西,但是团队内暂时还没有对此做硬性要求。不过我个人是一直比较注重提交的内容,因为以前吃过亏,没有友好的commit内容某些场景下很难定位。虽然我比较注重但是还是比较游击队的打法,最近看到了个东西叫commitizen,它可以配置一套标准的提交规范,所以准备用起来。

配置commitizen

https://juejin.im/post/5cbd1fdf5188250a546f565f

  • 可借助工具使提交更加规范:安装cz-conventional-changelog,即使用第三方的提交模板,这儿表示用的AngularJS的提交模板

  • 用husky配合git hooks 进行预检查

package.json

{
1
2
3
4
5
6
7
8
9
"husky": {
"hooks": {
"commit-msg": "(echo HUSKY_GIT_PARAMS: %HUSKY_GIT_PARAMS%) && commitlint -E HUSKY_GIT_PARAMS"
}
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}

git 储藏

常用git stash命令:

(1)git stash save "save message"  : 执行存储时,添加备注,方便查找,只有git stash 也要可以的,但查找时不方便识别。

(2)git stash list  :查看stash了哪些存储

(3)git stash show :显示做了哪些改动,默认show第一个存储,如果要显示其他存贮,后面加stash@{$num},比如第二个 git stash show stash@{1}

(4)git stash show -p : 显示第一个存储的改动,如果想显示其他存存储,命令:git stash show  stash@{$num}  -p ,比如第二个:git stash show  stash@{1}  -p

(5)git stash apply :应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0},如果要使用其他个,git stash apply stash@{$num} , 比如第二个:git stash apply stash@{1} 

(6)git stash pop :命令恢复之前缓存的工作目录,将缓存堆栈中的对应stash删除,并将对应修改应用到当前的工作目录下,默认为第一个stash,即stash@{0},如果要应用并删除其他stash,命令:git stash pop stash@{$num} ,比如应用并删除第二个:git stash pop stash@{1}

(7)git stash drop stash@{$num} :丢弃stash@{$num}存储,从列表中删除这个存储

(8)git stash clear :删除所有缓存的stash

git 回滚

//回滚上一次提交
git reset HEAD~ 
// 修改最近一次提交的备注
git commit --amend
// 修改某一次提交的备注,最后的数字2指的是显示到倒数第几次
git rebase -i HEAD~2

git 合并

1
2
3
4
//是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中
git fetch
//是将远程主机的最新内容拉到本地并合并
git pull

git 切换分支

//对于已经拉取到本地的分支之间的切换
git checkout 分支名
//对于还没有拉取到本地的分支
git checkout -b remote分支名 本地分支名

git 撤销merge

1
2
3
4
5
6
7
8
9
//经常在切换分支时,一不小心就merge错了分支或者合并时遇到冲突想取消操作,这命令就好用了
git merge --abort

//撤销指定的merge
1.找到最后一次提交到master分支的版本号,即【merge前的版本号】
git log --pretty=oneline
2.回退到某个版本号
git reset --hard 【merge前的版本号】

git 撤销

1
2
3
4
5
git reset --soft: 将分支回退到指定提交,工作区维持现状不变,暂存区会在现有基础上增加该commit之后的提交。
git reset --mixed: (默认操作)将分支回退到指定提交,暂存区也被同步为该指定提交,工作区保持不变。
git reset --hard: 将分支回退到指定分支,暂存区和工作区都会被同步为该指定的提交。
git reset --hard 可以回退到某个提交
git revert可以撤销某个提交,撤销会产生一个新的提交

回退到某个版本并应用指定的几次提交

1
2
3
4
5
6
7
切换到目标分支上, 假如当前状态为新合并进了一条commit,只需执行 git reset --hard HEAD~1即可回退到合并前。
或者回退到任何你想要的状态中 git reset --hard commitId, 其中commitId为你想要处于的版本hash code。

示例:
git reset --hard 1d7444 #回退到某个版本
git cherry-pick 626335 #将某次commit的更改应用到当前版本
git push origin HEAD --force #强制提交

根据关键字搜索提交记录

1
2
3
4
5
6
7
git log --all-match --grep=登录

commit 9f3e61ad63626c3e2e7541430d4af9693e3357ccAuthor: caofu <[caofu@ruijie.com.cn](mailto:caofu@ruijie.com.cn)>Date: Fri Dec 7 13:09:55 2018 +0800 完成单点登录xxxx


#查看某次提交的内容
git show 9f3e61ad63626c3e2e7541430d4af9693e3357cc

话说2018.07.31的x安公司的谢XX和李XX,在摄像头下两人进行了比较随心所欲的肢体接触,网传是因为产品经理要求程序员实现APP主题根据手机壳变颜色的需求,程序员忍无可忍从而释放自我的过程。当然这是网传版本,据说完全不是那么回事。

但是为什么这个事件就那么红呢。我觉得有两方面的原因:

  1. 程序员一向是被整个社会调侃最多的职业之一(之一比较谦虚),热点够大。
  2. 网传的需求太他么奇葩,迎合了大多的吃瓜群众。

作为程序员其实我们为什么也觉得有趣,是因为产品和程序员多多少少都会有不对付(矛盾)的情况发生。这件事刚好映射了此情况。我个人觉得该矛盾的核心点还是在于同理心这一点上,双方好像都很难理解对方。其实主要就是很少站在对方的角度和位置上,客观的理解对象所说的事情。

讲的有点多了,为什么想说”吃力不讨好”,是因为本周周会复盘时,刚好遇到了一个同事出现了此情况,当事人肯定很难受也比较委屈,这位同事暂时起名小波,方便叙述。

当然这篇文章主要是站在技术人员的角度写的,其它职位的待我深入了解后再有资格叨叨。

为什么需要复盘一下呢,明面上的原因是小波任务delay了进而导致周目标delay了,在PO验收时结果有些不太理想。所以SM就拉着大家做了一下复盘,
流程是:

  • 首先小波先说明一下整个delay的原因
  • 分析根因
  • 大家发表一下看法和建议
  • 形成改进项或者规约之类的东西
  • 团队是否认同
  • 改进项的责任人进行跟进

大体的原因是在于,小波在研发时,鉴于程序员的伟大使命感,总想着抽象进而方便后人,但是在研发前期准备时不管是关键路径还是详设,都没能体现这块内容,关键是这块内容占用的时间还比较长,所以最终导致整个计划delay。这本身不是个问题,因为想法时好的,问题在于这是个”吃力不讨好”的事,因为这是过程产物,PO等人是看不到的,更大的问题是小波没有和任何人进行同步,一个人吭哧吭哧干了半天,那就大家都不知情,所以导致他很被动。

所以我给的建议是:

  1. 吃力不讨好的事一定得让干系人知道,好事不留名大多数情况下是扯淡的说法。
  2. 自己得有一定得心理准备或者做一定的心里建设,因为既然是吃力不讨好的事,那就不能指望所有人能念你的好。

当然最终团队形成了一些改进项

  1. 尽量提前在”关键路径“阶段列出所有研发内容,功能性的和非功能性的,使后面的工程计划能更加准确。
  2. 定义承载过程产物的文档格式以及标准,目的是为了体现研发过程。
  3. 周目标的check标准更加细化,能提升更早暴露风险的时间。
  4. 当在研发中遇到此类问题时,一定要马上同步到相关的人,评估计划方案之后再动手。

本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。

最近有个前辈大哥看我写的代码之后,温柔的推荐了我一本小书《编写可读性代码的艺术》

表明层次的改进

全局观注释

当某个类或者文件使用盖住是,比如是表示系统的入口点、数据如何在系统中流动等,具有全局意义的代码,写几句精心选择的话说明该代码的意义,不宜过大的篇幅。

总结性的注释

对函数做的事情进行总结,让读者在深入了解细节之前就能明白该函数的主旨。

写注释拆分成几件事:

  1. 不管你心里想什么,先把它写下来。
  2. 读一下注释,看看有没有什么地方可以改进的。
  3. 不断改进。

注释目的:

  1. 记录想法
    1. 为什么这样写(指导性)批注。
    2. 代码中的缺陷,使用像TODO或者XXX等这样的标记。

站在读者的立场上思考

  1. 预料哪些代码是读者会有疑问的,加上注释。
  2. 为普通读者意料之外的行为加上注释
  3. 用注释来总结代码块,使读者不至于迷失在细节中

怎样写出言简意赅的注释?

  1. 注释保持紧凑。不超过三行

  2. 避免使用不明确的代词,比如这、那。用有意义的名词代替,比如data、userList…

  3. 精确的描述函数的行为,比如“返回有效字符的个数”,哪些使有效字符哪些使无效字符?

  4. 某些涉及到比较复杂或者不太好用文字描述的函数,用输入输出的例子进行说明。比如“格式化字符串为下拉框格式”
    Example: listToOptionTags([{id:1,name:'a'},...]) returns [{$$typeof: Symbol(react.element), type: ƒ Option(), key: "daa7f2d8-bfd9-11e9-8...},...]

  5. 声明代码的意图,别描述字面上的意思。比如在一段for循环上写“遍历用户对象集合”,改成“以逗号分隔拼接所有用户的firstName属性”

  6. 具名函数参数,对难以理解的参数可以按照参数名对参数赋值,比如java中可以用嵌入注释的方式:

    connect(10,false); 改成 connect(/*timeout_ms=*/30,/*use_encryption=*/false)

什么地方不需要注释?

  1. 能从代码本身中迅速地推断的事实。
  2. 用来说明烂代码(比如函数名取得不明所以…),这时考虑的应该是吧代码改好。

简化循环和逻辑

把控制流变得易读

  1. 条件判断,比较的左侧通常是经常变化的值,右侧通常为不变化的值,比如:

    if(length>10)和if(10<=length),很明显前者更易读

  2. if/else的顺序,因为if/else的顺序可以自由变换,很多时候应该要考虑哪一种顺序更好,可以有以下准则:

    1. 通常情况下先处理正逻辑而不是负逻辑,比如if(haveUser)而不是if(!haveUser)
    2. 先处理简单的情况,这样的好处是可视范围内应该都能看到if/else
    3. 先处理有趣的或者更危险的情况,比如负逻辑 if not file…

所以有些规则是根据具体的情况而定的,需要我们自行判断该用哪一种形式,总之我们的目的是为了避免if/else顺序变得很别扭的情况。

  1. 三目运算符

    该表达式的可读性是存在争议的,三目表达式是一行书写,当比较内容比较简单时,使用三目会让代码看上去很紧凑和易读,不过当比较的内容比较长或者比较复杂的时候,所有代码挤在一行,这样就变得冗长了。

关键思想:相较于追求最小化代码行数,一个更好的度量方法是最小化人们理解它的时间。所以可以遵循以下原则:默认情况下都用if/else,三目表达式只有在最简单的情况下使用。

用自然语言描述代码

用自然语言描述程序,然后用这个描述写出更自然的代码。

比较适用于稍微复杂一些的场景,通过这种方式,能根据描述用的词语和过程,进而拆分出一些子问题,从而简化代码,使代码看起来更自然。

本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。

来自Quora上的一个关于个人成长的问答,先摘录在这儿,成长计划可参考之。

Travel
Wake up early
Wake up and go to bed at the same time as much as possible
Get rid of toxic people
Focus on networking and building your network
Exercise daily, even if it is 5–10 minutes of intense exercise
Eat a high protein/high fat breakfast within 30 minutes of waking
Drink plenty of water throughout the day
Focus on the 80/20 rule
Focus on compounding activities. Like giving up alcohol or dramatically reducing it leads to more money and energy, which could result in more money if you reinvest the surplus. Same thing with negotiation and spending habits - Why the wealthy spend less on luxury: the 70/30 rule in finance
Read, read and read. Read about personal health, sales, management, marketing and personal finance - Best investment books for beginners

  1. 旅行
  2. 起得很早
  3. 尽可能多地醒来上床睡觉
  4. 摆脱有毒的人
  5. 专注于网络和建立网络
  6. 即使每天剧烈运动5-10分钟,也要每天运动
  7. 醒来30分钟内吃高蛋白/高脂早餐
  8. 全天多喝水
  9. 专注于80/20规则
  10. 专注于复合活动。 就像放弃酒精或大幅度减少酒精含量一样,它可以带来更多的金钱和精力,如果您将剩余资金再投资,可能会产生更多的钱。 具有谈判和消费习惯的东西-富人为何减少在奢侈品上的消费:70/30的金融规则
  11. 阅读,阅读和阅读。 了解有关个人健康,销售,管理,市场营销和个人理财的信息-适用于初学者的最佳投资书

当自己都觉得代码看起来不爽,或者不好读懂时 ,这块代码一定写的有问题。

在《Clean Code》一书中Bob大叔认为在代码阅读过程中人们说脏话的频率是衡量代码质量的唯一标准。

最近再看浏览器方面的内容,对于渲染这块收集到的知识做个小结,我是大自然的搬运工。

By Ilya Grigorik

CSSOM 树和 DOM 树合并成渲染树,然后用于计算每个可见元素的布局,并输出给绘制流程,将像素渲染到屏幕上。优化上述每一个步骤对实现最佳渲染性能至关重要。

在前面介绍构建对象模型的章节中,我们根据 HTML 和 CSS 输入构建了 DOM 树和 CSSOM 树。 不过,它们都是独立的对象,分别网罗文档不同方面的信息:一个描述内容,另一个则是描述需要对文档应用的样式规则。我们该如何将两者合并,让浏览器在屏幕上渲染像素呢?

TL;DR

  • DOM 树与 CSSOM 树合并后形成渲染树。
  • 渲染树只包含渲染网页所需的节点。
  • 布局计算每个对象的精确位置和大小。
  • 最后一步是绘制,使用最终渲染树将像素渲染到屏幕上。

第一步是让浏览器将 DOM 和 CSSOM 合并成一个“渲染树”,网罗网页上所有可见的 DOM 内容,以及每个节点的所有 CSSOM 样式信息。

将 DOM 与 CSSOM 合并以形成渲染树

为构建渲染树,浏览器大体上完成了下列工作:

  1. 从 DOM 树的根节点开始遍历每个可见节点。
    • 某些节点不可见(例如脚本标记、元标记等),因为它们不会体现在渲染输出中,所以会被忽略。
    • 某些节点通过 CSS 隐藏,因此在渲染树中也会被忽略,例如,上例中的 span 节点—不会出现在渲染树中,—因为有一个显式规则在该节点上设置了“display: none”属性。
  2. 对于每个可见节点,为其找到适配的 CSSOM 规则并应用它们。
  3. 发射可见节点,连同其内容和计算的样式。

Note: 简单提一句,请注意 visibility: hiddendisplay: none 是不一样的。前者隐藏元素,但元素仍占据着布局空间(即将其渲染成一个空框),而后者 (display: none) 将元素从渲染树中完全移除,元素既不可见,也不是布局的组成部分。

最终输出的渲染同时包含了屏幕上的所有可见内容及其样式信息。有了渲染树,我们就可以进入“布局”阶段。

到目前为止,我们计算了哪些节点应该是可见的以及它们的计算样式,但我们尚未计算它们在设备视口内的确切位置和大小—这就是“布局”阶段,也称为“自动重排”。

为弄清每个对象在网页上的确切大小和位置,浏览器从渲染树的根节点开始进行遍历。让我们考虑下面这样一个简单的实例:

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Critial Path: Hello world!</title>
</head>
<body>
<div style="width: 50%">
<div style="width: 50%">Hello world!</div>
</div>
</body>
</html>

试一下

以上网页的正文包含两个嵌套 div:第一个(父)div 将节点的显示尺寸设置为视口宽度的 50%,—父 div 包含的第二个 div—将其宽度设置为其父项的 50%;即视口宽度的 25%。

计算布局信息

布局流程的输出是一个“盒模型”,它会精确地捕获每个元素在视口内的确切位置和尺寸:所有相对测量值都转换为屏幕上的绝对像素。

最后,既然我们知道了哪些节点可见、它们的计算样式以及几何信息,我们终于可以将这些信息传递给最后一个阶段:将渲染树中的每个节点转换成屏幕上的实际像素。这一步通常称为“绘制”或“栅格化”。

上述步骤都需要浏览器完成大量工作,所以相当耗时。不过,Chrome DevTools 可以帮助我们对上述所有三个阶段进行深入的了解。让我们看一下最初“hello world”示例的布局阶段:

在 DevTools 中评估布局

  • “Layout”事件在时间线中捕获渲染树构建以及位置和尺寸计算。
  • 布局完成后,浏览器会立即发出“Paint Setup”和“Paint”事件,将渲染树转换成屏幕上的像素。

执行渲染树构建、布局和绘制所需的时间将取决于文档大小、应用的样式,以及运行文档的设备:文档越大,浏览器需要完成的工作就越多;样式越复杂,绘制需要的时间就越长(例如,单色的绘制开销“较小”,而阴影的计算和渲染开销则要“大得多”)。

最后将在视口中看到下面的网页:

完成渲染的 Hello World 网页

下面简要概述了浏览器完成的步骤:

  1. 处理 HTML 标记并构建 DOM 树。
  2. 处理 CSS 标记并构建 CSSOM 树。
  3. 将 DOM 与 CSSOM 合并成一个渲染树。
  4. 根据渲染树来布局,以计算每个节点的几何信息。
  5. 将各个节点绘制到屏幕上。

我们的演示网页看起来可能很简单,实际上却需要完成相当多的工作。如果 DOM 或 CSSOM 被修改,您只能再执行一遍以上所有步骤,以确定哪些像素需要在屏幕上进行重新渲染。

*优化关键渲染路径*就是指最大限度缩短执行上述第 1 步至第 5 步耗费的总时间。 这样一来,就能尽快将内容渲染到屏幕上,此外还能缩短首次渲染后屏幕刷新的时间,即为交互式内容实现更高的刷新率。

来源:

圆桌派第四季中有一期《情绪:你心情好吗?心能管理吗?》中,窦文涛先生讲了一句话始于愤怒必终于羞愧。

真的建议大家挤出一些时间看看圆桌派,四剑客在一起时是最好看的,聊的东西真的挺有收获。

这一期我印象最深的就是这句话:始于愤怒必终于羞愧

因为我一回想当自己愤怒时候的样子和做的事说的话,大多数情况下等平静之后都会有一股愧疚感,会感到很羞愧。而你要知道这样的伤害特别是对他人可能是永久的,很多时候你根本找补不回来。

所以当你愤怒的时候,或者你觉得你情绪有问题的时候用下面的语录来一遍,可能这事就过去了。

语录:

  1. 有时候事情的沉重程度只是源于自己当时的情绪,当情绪改变了,对同一件事情的看法也就发生了改变。
  2. 出身不太好的人往往在人际交往中有很强的自我觉察,对自己的观点不够自信。
  3. 有些不良情绪在同相应的对象进行了表达之后会降低(对别人的嫉妒,说出来之后就会变好)。
  4. 王阳明心学:吾性自足。需要心胸足够开阔,装下自己,也要装下别人。
  5. 不快乐的原因是太过关注自己的情绪,所以快乐的方式是注意力向外,多关注生活,同时这也是将整个世界放到自己的心胸里,让自己变得开阔。
  6. 如果在情绪激动的时候,可以分离出一个自觉,能够看到自己正在愤怒中,就不会失控。
  7. 温度计测量温度的高低,但其本身没有温度的变化,所以才能测量温度。人的情绪也需要这样一个不会变化的量尺。
  8. 环境影响人对事情的接受程度
  9. 内在与外在的二元对立关系需要达到平衡。

小结

共勉吧,愤怒通常是瞬间发生的,先强制断一下节奏,不让愤怒和接下来的言行无缝衔接,不管用什么方式有意的断一下节奏之后,就算依然愤怒依然付诸言行也会合理很多。

我就是这样做的,大多数情况下…