0%

《凤凰架构 - 技术方法论 - 治理》 引用 Gartner 技术咨询公司的对治理的定义:“治理就是让产品能够符合预期地稳定运行,并能够持续保持在一定的质量水平上”。
余额宝《服务治理架构》提到一点:度量是治理的前提,只有看的到,才能管的到,如果不能度量,就无法改进。
余额宝在工程实践中积累出的经验,和 “治理” 定义相契合:
符合预期:需要定义预期并量化,明确指标和阈值。要求我们根据度量数据描述治理对象的 “健康” 状态。
持续保持:持续监测指标,对超出阈值的指标,根据治理决策,进行治理动作。

治理三板斧

定义健康指标

量化描述被治理对象的健康状态,在此过程中会产生评价标准或规范,启动阶段输出 Draft 版即可,后续根据治理过程中的实际效果和反馈进行迭代。
初始阶段不需要奢望定义完整的指标项,聚焦重点,识别出最普遍的问题(通常具有高价值),作为切入点进行治理。

收集健康数据

根据定义的指标,进行埋点数据采集,配置告警阈值。这不仅量化描述了治理成果,同时也做了防腐,能够维持健康状态。

复盘总结

从实际的治理活动中总结经验,再次归纳、改进健康指标和规范。整个过程类似于 PDCA 工作法,也符合敏捷的思想,逐步达成治理目标。

一直关注 蔡学镛 老师的微博,可惜老师把微博全部清空了,还好我很早之前在笔记中记录了老师的微博内容,早知道应该全部爬取下来的。这是我整理了蔡老师关于程序员在职场中一些处事技巧和经验,我看了之后非常有共鸣,这里分享给大家。

主管篇

  • 当主管的人必须意识到:「下属」只是职级在你之下,不代表他们能力或各方面比你差,也不代表他们没有人格尊严。现在社会,好的主管必须善待下属,否者团队就会出现「逆淘汰」。毕竟能力好的下属不需要接受你的羞辱,他有其他更好的去处。公司不是军队,人才是可以出走的。

  • 领导人脾气坏的话,多数的员工本来就已经在跨出公司的临界边缘。这时候来个大的变革,就会导致通常是比较好的员工主动离开,留下的通常比较差。逆向淘汰,越弄越糟糕。

  • 推荐领导们阅读这本书《Persuadable: How Great Leaders Change Their Minds to Change the World》,作者 AlPittampalli。有简体中文版《允许被说服》。我读的是繁体中文版《被说服的勇气》

  • 任何公司想让软件工程师有幸福感,不想离职,就需要建立工程师文化。工程师文化是:阶级不明显、人与人之间简单、沟通高效、会议和饭局少、分享与学习的氛围强、不会让外行领导内行、部门间不存在明显壁垒、政治任务型的项目少、愿意投资比较长期的项目、让工程师有一定的冗馀时间自我学习新知识。

  • 一个领导如果知道事情具体的做法,就可以教导下属、委派下属、监督下属去做事情,但绝对不应该亲自跳下去做,否则不但让下属没有进步的空间,还把自己的工作重点放错,甚至格局做小了。
    PS: 可惜有些领导不太信任下属的能力,亲自上阵,还强制下属按照自己的意志行事,往往让下属成为一颗不会思考的棋子,然而这些领导非但没有意识到这个问题,还自称是“处女座”。

  • 有些领导要求下属对他做出提议之前,把一切都调研清楚,让领导只要拍板定案或否决就好,以节省领导的时间。我不是这样的领导,也不觉得这节省了领导多少时间,我反而觉得这可能会浪费了下属的许多时间,相当于浪费了部门的时间。我希望先简单聊聊,如果觉得值得花时间让下属投入调研时再去调研。

  • 当一个技术团队的主管,如果完全不懂技术,一切都会很单纯。让下属出技术方案,简单听取一下,拍板定案,然后通过绩效考核来促使下属照着规划走,自己更多的时间在想着如何美化这一切,在上层领导面前显得好看。 但如果是懂技术的主管,因为真懂,看得出下属的技术方案不好,而下属又显然没有能力做得好时,就会很想跳下去自己设计方案。这个时候一定要忍住,不然会累死(事必躬亲不是好事),还会耽搁其他的管理任务。比较好的方式是指导下属,试图让他们进步,真不行只好换人。

  • 我希望自己做到:

    • 用人所长、非用人所短。
    • 少用棍棒和胡萝卜,多用发自内在的动力。
    • 在某些方面下属比你懂时,就跟他学习,不要瞎指挥。
  • 「你说这需要几年?」「很难说,这要看我们的投入有多少,还有整个公司的制度配合等因素」「不要跟我说这些,你就说几年」… 当领导喜欢简单的答案,简单到连前提条件和客观环境都不顾的时候,你基本可以判断这不是一个合格的领导。

下属篇

  • 你认为你在为别人工作?这大错特错。工作(Job)保障已经不复存在,职业生涯(Career)的驱动力必须来自于个人。一定要记得:工作(Job)是公司所拥有的,职业生涯(Career)是你所拥有的。每个阶段选择 Job 的考虑因素,都应该是为了整体的 Career。

  • 当你上班时,你是在为这家公司打工,不要认为你是在为你的领导打工。就好像当你信仰宗教时,你信任的是此宗教的核心思想,而不是寺庙的师父或教会的牧师。知道这样的差别很重要,可以帮助你更好地判断事情,避免被人错误地引导。

  • 正常的情况下,我们可能每五年就会遇到一次职业生涯转型的困惑。或许是需要技术升级,或许是需要技能汰换,或许是需要转换跑道,或许需要甚至更大的转变。

  • 工作之外,为了把工作做得更好,在技术、业务、管理方面,我们都必须再学习,一堆事情都在争夺我们的资源(注意力、时间、脑力)。但别人(同事或领导)会基于他们各自的利益,给我们派任务或请求协助,这个时候一定要衡量自己的状况,凡是对我们利益不大,且耗费太多资源的事情就必须坚定拒绝。不要为了当好人,维系办公室内所谓的人际关系,浪费掉自己大量的资源。

  • 正常的情况下是先说存在的问题,再说解决方案。但领导可能常常听到各种问题,听烦了,没有耐心听你讲问题,认为你是在抱怨,立刻打断你,劈头盖脸开始批评你的「负面思想」,使得你连熬到说方案的机会都没有。遇到这类领导,比较好的做法可能是先说方案,再说为什么有这个方案。

  • 在正职的工作以外,有个长期的私人的研究项目,对于职业生涯后续的发展,或许会有极大的助益。在应聘某些工作岗位上,可能派上用场。

  • 领导阴阳怪气,比 C++ 还复杂,导致你开始怀疑人生?日子太平淡,不甘心导致的悸动正在吸引你接受一个新的挑战?小鲜肉纷纷进入职场,让你对未来没了安全感,觉得需要转型干点别的? 对于职业生涯感到迷茫者,我推荐阅读《Pivot: the only move that matters is your next one》。

  • 写报告的时候,前面三分之一让领导轻易看得懂,中间三分之一让领导勉强看得懂,最后三分之一让领导看不懂。「虽然后面那部分我看不懂,但显然这是个很专业的团队,他们知道自己在干什么。」

  • 一件事情本身是否「重要」,这是虚的;它能被配置多少资源,这才是实的。如果某件事被领导认为重要,但同时还有二十件事也被领导认为重要,以至于这件事最终只能拿到百分之一的资源时,你会发现:「重要不重要」根本不重要。

  • 30 岁左右,对于传统金融的软件开发人员来说往往是一个瓶颈。因为通常已经上升到一个小组长或技术经理的职位,手下带了几个人。但想要再往上到中级干部的职位,更需要的是「其他能力」,这是技术人目前不具备的,且上面的中级干部职位变得很少。在中级干部的「屏蔽」下,真正干活的小组长也比较难出头,也无法培养出升迁需要的「其他能力」。经过几年的停滞,小组长终于发现升迁渺茫,加上家里的经济压力,于是陷入一种恐慌的心理状态。这时候需要的是痛定思痛,离开目前的岗位,找一个相对扁平的单位(如果是新成立的单位更好),并找一个作风开明,不会阻碍下属成长,甚至会帮助下属成长的领导。这时候需要的是聪明的选择,不是无谓的坚持。

最长上升子序列 是一个经典的动态规划题目:

1
2
3
4
5
6
7
8
9
给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:
可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

解决 DP 问题在之前的 文章 提过,我们可以先通过最简单的例子(实例)找到规律,在将规律范化(抽象),因为我们的大脑习惯思考具体的东西。

以题目中的示例来分析:

无序整数数组 上升子序列 最大上升子序长度
10 10 1
10, 9 10

9
1
10, 9, 2 10
9

2
1
10, 9, 2, 5 10
9
2

2, 5
2
10, 9, 2, 5, 3 10
9
2
2, 5

2, 3
2
10, 9, 2, 5, 3, 7 10
9
2
2, 5
2, 3

2, 7
2, 5, 7
2, 3, 7
3
10, 9, 2, 5, 3, 7, 101 10
9
2
2, 5
2, 3
2, 7
2, 5, 7
2, 3, 7

10, 101
9, 101
2, 101
2, 5, 101
2, 3, 101
2, 7, 101
2, 5, 7, 101
2, 3, 7, 101
4
10, 9, 2, 5, 3, 7, 101, 18 10
9
2
2, 5
2, 3
2, 7
2, 5, 7
2, 3, 7
10, 101
9, 101
2, 101
2, 5, 101
2, 3, 101
2, 7, 101
2, 5, 7, 101
2, 3, 7, 101

10, 18
9, 18
2, 18
2, 5, 18
2, 3, 18
2, 7, 18
2, 5, 7, 18
2, 3, 7, 18
4

根据上述的穷举,我们发现在 “无序整数数组” 中每添加一个元素,就是根据上一次的 “上升子序列” 结果中找出结尾比当前元素小的情况,追加当前元素。 10, 9, 2, 5, 3, 7 的 “上升子序列” 就是在 10, 9, 2, 5, 3 的子序结果中找到结尾比 7 小的子序结果 [2][2,5][2,3] 追加上 7 的结果 [2,7][2,5,7][2,3,7]

根据这个规律,我可以定义状态,d(i) 表示以第 i 个数组结尾的最长递增子序列的长度。 最长递增子序列长度需要根据[d(0), d(i - 1)] 的结果计算,状态方程是:dp[i] = max(dp[j])+1 (0 ≤ j < i & num[j] < num[i]) ,最终结果是 max(dp[i])

这个题目的特点是,计算当前层的 DP 结果需要遍历之前所有的 DP 结果找到最值,才能确定当前层的结果。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public int lengthOfLIS(int[] nums) {
if (null == nums || nums.length == 0) {
return 0;
}
int[] d = new int[nums.length];
d[0] = 1;
int max = 1;
for (int i = 1; i < nums.length; i++) {
int cur = 0;
// 计算 0 ~ i 中子序最长
for (int j = 0; j < i; j++) {
// nums[i] > nums[j], 则 nums[i] 可追加到原来 d[j] 的结果中
if (nums[i] > nums[j]) {
cur = Math.max(cur, d[j] + 1);
} else { // 否则, nums[i] 自成一个序列
cur = Math.max(cur, 1);
}
}
d[i] = cur;
max = Math.max(max, d[i]);
}
return max;
}