This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
<audio id="audio" title="28 | 沟通中的冲突:什么时候应该妥协,什么时候应该坚持?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ce/6c/ce518112b1edb7fdb79c16e108241b6c.mp3"></audio>
你好,我是臧萌。本专栏进入到加餐模块啦,第一篇加餐,我们又来谈沟通了。
按照我们之前谈沟通的顺序,先是从工作的基本素质上,我们要重视沟通,主动沟通。然后从职场情商的角度,我们要重视沟通的方式方法,重视沟通的效果,尊重沟通的对象。从这两个方面来看的话,沟通还是正面与合作为主。但是我们在日常沟通里,面对的远不止这些和谐画面。
很多时候,我们还会遇到很多观念观点的冲突。如果冲突可以通过短时间的讨论达成一致,那就不能算有冲突。当然,也有可能大家心里的想法都不是很明晰,讨论下来也没有一个明确的结果,这也不能算冲突。我们这里说的冲突,是双方或者多方的想法都非常明确,然后经过反反复复的讨论,大家的想法也无法达成一致的情况。
接下来在这一节里,我们就从处理冲突的角度来聊聊沟通。
## 有些冲突,程序员要主动退到一边
发生冲突的一个很大的原因,是有直接的利益冲突。比如谈地盘、谈系统归属、谈责任等等。这些情况是经理等管理者的主要战场,我们程序员打好辅助就可以,一般不需要主动露面谈。如果遇到这些相关的讨论找上自己,可以先简单应付,但是真正到了讨论核心问题的时候,一定要记得把自己的经理拉进来。
需要强调的一个点,千万不要做超出自己权利范围的承诺。大白话就是,自己说了不算的话,不要跟自己组之外的人说。
一般来说,大家都是会找对等的人来交流。比如说,如果这个会议上有对方的经理,那么自己组的经理也是要出面的。这不是排场面子的原因,而是对等的人,才能聊得下去,把事情敲定。举个简单的例子,一个国家的总统,和另一个国家的经济部长,是没办法聊的,因为很多事情经济部长无法拍板。
## 如何应对沟通中的冲突
属于我们程序员相关的冲突和争论,一般都是与技术和架构相关的。那么我们程序员应该如何应对沟通中冲突呢?我下面举几个例子,我们一块来看一下。
### 代码方面的个人偏好
每个人都有自己的偏好比如说有人喜欢用Lambda有人喜欢用for循环有人喜欢这样去命名方法和变量有人喜欢另外一种风格。从我个人的建议来说谁负责写code谁就有权利决定用自己喜欢的风格写代码。只要功能可以完成代码足够鲁棒那外人就没权利多加干涉。毕竟我们不是流水线上的工人不可能生产出一样的代码。
当然不是说代码就没有标准。就Java来说Java编译器有warning还有Sonar、PMD、Findbugs、Checkstyle等工具。这些工具里有很多检查代码的规则这些都是业内实际的标准和共识。从这个角度来说你没必要用自己的个人偏好去指点别人。当然如果被人指点你也可以拿这个反击。毕竟行业内的标准都没说什么你有什么资格说我
### 接口的设计
接口的设计其实非常考验一个人的能力。它比具体的实现代码更抽象,但是比架构设计更具体,是连接两者的桥梁。
简单来说接口就是程序世界的标准。标准的规定有一个公认的原则就是要足够的包容。比如Iterator、Collection和List作为参数兼容性逐渐降低。当然这个例子没什么大问题大不了调用方自己转一下。但是如果用了File做参数而实际上只需要InputStream读取数据那调用方如果没有把数据存在File里就不好弄了。
从参数的角度说开去,接口就是这样一个越包容,越优秀的东西。如何能用最少的约束,把事情描述清楚,就是接口的一大目的。面临接口设计的争论时,大家可以就这个点展开,各抒己见。最终得出结论,也不是难事儿。
### 系统架构
系统架构上的争论,则更是因人而异。因为做系统架构的过程,其实是每个人对一件事情理解和建模的过程。就好像扔给两个人一堆积木,让他们每人搭一个大楼,肯定俩人搭建的大楼不会一样。即使你指出方向,比如一个商业摩天大楼,外表也会不一样。即便是再规定得详细一点,比如要有广场、要有裙楼等等,细节部分也不会一样。那就更别说软件架构设计了,俩人架构的系统肯定不一样。
如果在软件架构上有冲突,应该怎么处理呢?软件架构结果的冲突只是表象。根源是大家对问题的理解,对系统如何应对问题的方式理解不同。这时候,如果只是纠结于架构的不同,是无法得出一个结论的。所以,为了解决冲突,应该大家都回退一步,先从问题入手,让大家对问题的理解能够统一,对解决问题的方式能够统一。这样,即使架构上有所不同,也是容易解决的。
当然,我在前面也提到过:令出多门,兵家大忌。如果就是不能统一呢?这种情况下,就得有一个总的架构师,能够维护整体解决方案的统一性,避免因为彼此的认识不同,导致系统无法统一。其实很多时候,系统架构很难说谁对谁错。但是如果各个子系统的风格不统一,那大概率就会有问题。
### 功能现在就要
很多时候,需求方会提出很多现在架构下不支持的功能。这时候我们就有两个选择,一个以快糙猛的方式,放弃遵循现在的架构,把功能怼出来。一个呢,是从长计议,深入理解需求、升级架构,然后支持新的功能。
我来打个比方,系统架构就像是一张交通图。普通的需求就像是走高架,不需要绕路,没有红绿灯,可以用最短的时间到达。特殊的需求就像是走地面,甚至是走单行道,需要走走停停,甚至需要绕路,虽然费点劲,但是也能到,而且不和架构冲突。
架构不支持的需求,则是交通图上根本没有路的情况,就好比需要跨过一条河,但是河上并没有桥。这时候,第一种选择就是硬怼,比如放下车、找条船、甚至直接游泳过去。
第二种选择是先深入了解用户过河的需求,包括过河干什么、频次是多少、运载量是多少、能够接受的交通时间是多少等等。然后再根据需要来选择是修建码头、修建跨河大桥、还是修建隧道。
看似第一种选择是客户至上。但其实很多时候第一种选择是短视的表现。一方面你快糙猛做出来的东西很可能无法完成用户接下来的需求。比如说随着需求的发展用户要求一天来回1000趟每趟不能超过3分钟游泳自然不可能。坐船的话你去哪里找这么多的快船呢换句话说违背现有架构快糙猛地实现客户的需求是对客户的溺爱而非真的的客户至上。
另一方面,没有深入理解用户的需求,其实会错过和客户一起深入理解系统和业务的机会。系统架构不支持,确实是系统本身的限制。但是如何让系统更完美呢?就是你要通过这样的机会,深入思索业务模型的限制,通过升级系统来让系统建模更加通用,可以应对客户以后的新需求。
## 方式方法可以妥协,原则和目标必须坚持
上面的几个例子中一个共性是大家先后退寻找共识common ground然后以此为基础把事情向前推进。这里我总结一下上面几个例子里所说的共识。
1. 代码偏好findbugs等业内标准。
1. 接口设计:接口设计应该包容。
1. 系统架构:大家对问题的理解要统一。
1. 新功能:理解新需求,升级架构,以支持新功能。
回到我们标题上提出的问题,我们在交流中遇到冲突时,什么时候应该妥协,什么时候应该坚持呢?这里我给出一个自己的标准,那就是做事情的方式方法可以妥协,但是目标本身必须坚持。
对比上面的四个例子你就能发现,所谓的标准,越来越模糊。什么是包容、什么是对问题的理解、什么又是新功能的本质,越来越没有绝对的正确。每个人,在自己不同的阶段,都会有不同的理解,更不用说在不同的人之间。
这就带来一个实际的问题,就是冲突的情况不可避免。这时候我们程序员千万不要怕冲突,只要你是冲着做事情去,而不是冲着搞事情去,就一定要将自己心中的疑惑说出来。
说出来的好处,首先是可以互相切磋,提升彼此的认识。正所谓不打不相识,很多时候大家的认识都不够全面,通过冲突的方式,可以让彼此都拓展自己的认识。
其次,要说出来可以逼迫自己深入思考。想和别人刚,自己得先把自己的想法理清楚。很多时候,自己的想法是想当然的,当这种想当然和别人发生冲突的时候,就需要自己深入思考,或者找出自己的理由,或者放弃自己的成见,接受别人的观点。无论是哪种,对自己来说都是成长。
最后,有疑惑就说出来,可以让彼此合作更默契。我们经常说一个团队有默契,其实默契就是这样磨合出来的。不磨合,只是表面的迎合,并不能让一个团队里的成员配合无间。
## 总结
我想特别强调的一点是,程序员不要一味地逃避冲突。你如果用妥协来避免冲突,这绝对不能很好地解决问题。当然,我不是说要做一个“杠精”,而是要在做事情的基础上,充分表达自己的观点和认识。
如果自己明知道别人的做法有问题,但是你选择不表达自己的看法,长久下来,只会让别人觉得你没想法。和自己有关的东西,更要在自己不认同的时候发声。如果你只是一味地委屈自己,成全别人,其实只会让人觉得你软弱。
很多程序员不喜欢交流,不喜欢拒绝别人,更不要说和人争论、冲突。说实话,我也非常不喜欢和人冲突。但是正是自己这种避免冲突的倾向,让我吃了不少亏。举个例子,我之前觉得架构设计有问题,我也不会说什么,觉得只要能做出来,实现功能就可以。后来发现,这些架构设计的问题,会慢慢变成坑,变成阻碍一个组发展的绊脚石。
现在我只要在工作中遇到觉得有问题的事情,马上就会要求展开细聊。如果其他人时间不够,就另外找时间聊。我从原来逃避冲突的人,变成了主动制造冲突的人。
根据我的观察,这种冲突,往往都能够让事情得到更好的结果。如果一味地为了避免冲突而保持缄默,其实长期来看,是无法融入到一个团体的。当然,如果一个团体里经常就相同的事情冲突来冲突去,那很可能说明大家就是无法磨合得很好。在这种情况下,如果你不打算离开这个团体,在面对冲突的时候千万别打退堂鼓。
<img src="https://static001.geekbang.org/resource/image/33/ab/331fd86e302702ee867c195564abb7ab.png" alt="">
## 思考题
你在工作中,有遇到过哪些让你记忆深刻的冲突?这些冲突是以双方都满意结束,还是以双方不欢而散结束呢?你有哪些处理冲突的经验和教训?
好了,今天的课到这里就结束了。欢迎你在评论区和我交流。也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。

View File

@@ -0,0 +1,97 @@
<audio id="audio" title="29 | 加班:加班逃不过,如何用正确姿势加班?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/94/82/94c34033bceac63205700fa7c520d682.mp3"></audio>
你好,我是臧萌。咱们程序员,尤其是互联网行业的程序员,都基本逃不过加班这件事。加班的原因,我总结了三个:任务太多,有紧急的事情以及强制加班。今天我就根据不同的加班原因,来仔细和你聊聊加班这档子事儿。
## 任务太多
首先就是任务太多,事情做不完。大部分情况下,造成工作任务繁重的原因,都是一些现实因素。
比如说系统的架构,已经不能够高效地应对现在的业务,每次增加新的业务用例都很繁琐,而且容易出错。又比如公司里各种系统都不好用,工作中用到这些系统,就费时费力,还可能来来回回折腾很多次。这些现实情况,让本来听上去没太大工作量的工作,实际做起来要用的时间却会多很多。
### 提高自己的效率
如何应对这种情况呢?我们要去思考这些让自己效率低下的原因。为什么会效率低下?根据我的观察和切身体验,其实很多时候,加班并没有让自己的产出更多。程序员的产出是不能用代码量来衡量的。
如果非要衡量的话,可以用代码完成的功能这个维度来简单衡量。很多时候我们加班,并不是完成了更多的工作,而是用更长的时间,去完成自己本应该用作时间就可以完成的工作。这就是效率低。
回到增加业务用例的情况,我们可以问自己这样一个问题:如果系统重新设计重新做,是否可以让增加业务用例的时间大大缩短?如果是的话,现有系统架构陈旧就是效率低的原因。再看工具的问题,你能不能找到一个合适的工具,让系统更加简单自动化?
这里我举一个自己工作中遇到的例子。我曾经参与过一个系统的开发系统的输出是一条条互不相关的key-value记录总数大概五百万到七百万条。
为了验证输出的结果是否正确要和上次系统运行的结果做对比。但是这个对比工作没有很好的工具当时的做法就是将两份数据导入MySQL数据库然后对于怀疑有问题的数据用key去查询两份数据逐个字段地进行比较找出数据有差异的原因再分析原因是否合理。
这是一个纯人工的工作,每一步都需要人来操作,如果有这么十几二十个记录要核验,那基本上半天就搭进去了。这种事情如果是偶尔搞一次,那也无妨。但是随着系统的发展,这个事情几乎每周都要来个几次,甚至有时候一天就要搞好几次。那这就完全是一种低效率的工作方式了。
我当时思来想去,觉得几百万的数据量也并非一定要用数据库。于是我写了一个程序,可以将两份数据文件做对比,自动找出变化大的数据,并自动对比各个字段。这样,生成的对比文件,就可以直接用来判断这次运行的结果是否有问题,并且可以很方便地,对每个差别比较大的数据进行查找和比对。最后我再把这个程序对接到生成系统输出的任务上,做到自动化执行。
当然在很多时候系统重构也是很好的方式。举个例子如果数据的schema经常需要根据业务需求做改变但是查询条件就只是根据key来单条查询那就可以考虑搞一个text字段把动态增加的业务字段转成JSON来存储当然也可以考虑转到对数据的schema变化更友好的NoSQL数据库。
不论你是选择合适的工具,还是去重构系统,都是在选择一种用更短时间去完成工作的方式。重点不是在于你去选择什么特定的方式,而是在加完班之后,你得好好思考一下,今天的工作效率高吗?有没有什么事情让自己觉得没技术含量?你是不是可以避免这些没技术含量的事情?是不是可以让这些没技术含量的事情自动起来?
我们是软件工程师,我们要让每天做的事情,对得起自己的能力。加班不仅仅是在浪费自己的时间,更是在浪费自己的才华和能力。有时间加班,为什么不用这个时间,搞个系统替自己加班呢?
## 紧急的事情
其次就是有紧急的事件。可能是线上出问题了,也可能是忽然有个优先级特别高的项目,需要自己在的组协助,甚至有可能是你直接被抽调去做某个高优先级的项目了。
至于线上问题,这个基本上是不能逃避的。我们能做的,就是防患于未然。比如增强监控,要监控的不仅仅是自己的系统,还有自己依赖的系统和依赖自己的系统。又比如尽量避免在周五上线,因为如果周五上线出了问题,就要加班去搞等等。
至于优先级高的项目,在我看来,更多的是一个机会。这些项目无论是新业务新方向,还是系统升级更新,都是一个让自己刷新技能、扩展眼界的机会。这时候阶段性地付出一些时间,对自己的职业生涯来说,是挺值得的。
拿我自己来说,我是个比较懒的人,有时候对很多系统的了解也是浅尝辄止。但是我被抽调参与过几次紧急项目的开发后,对这些系统和业务的认识提升了很多,反过来再看自己的系统,也更能理解一些之前没注意到的细节了。
## 强制加班
最后就是被大家“深恶痛绝”的强制加班。事情嘛也没啥事情,就是公司的氛围就是这样,大家都在位子上好像都没啥事情做,下班回家吧,又显得突兀——毕竟大家都没走。甚至公司可能会强制规定延长工作时间。即使公司不硬性规定,也可能用各种政策和福利影响你,让你半推半就地加班。比如比法定下班时间推迟几个小时才有“免费”晚餐,或者推迟几个小时下班才有班车等等。
我们站在工作的角度,先看看公司为什么原因让员工没事做,也得留在公司里。
我总结下来,大概有这么三个原因。首先,员工留公司里肯定会做更多的工作。即使你不想做和工作相关的事情,只要在公司里呆着,也难免会不自觉地做一些工作。
其次,是方便彼此协作。即使你自己本身不加班,如果别人加班需要你协助的话,可以直接找到你人,你也不好意思面对面地拒绝别人。
最后,就是公司文化等原因,公司愿意营造出这么一个大家都在努力奋斗的氛围。
那么我们应该如何应对这种类型的加班呢?在我看来,既然选择了这家公司,还是尽量遵守公司的默认上下班时间。那么在你没事做还得加班的时候,在公司能干什么呢?
### 做些对自己有附加值的事情
公司是一个可以专注的环境。如果不得不呆在公司,那对自己最有利的选择,就是做一些对自己有附加值的事情。这里我列举两个例子。
### 学习和探索新技术
首先自然是学习新技术。一个选择是把自己白天没时间弄清楚的技术整明白。不要放过程序中任何一个错误日志,不要放过工作中任何一个没想通的事情。然后就是看看哪些技术可以用在我们自己的系统上,放心大胆地试试看。毕竟这不是被安排的任务,不需要背负产出的压力。
### 不要止步于抱怨
每个组、每个系统,肯定都有大家一直在抱怨的小事情。这些事情不做也可以,但是做了会让自己组的效率更高。这时候,可以选择自己有兴趣且力所能及的点,把痛点修正掉。一个系统既然有人抱怨,还在一直用它,那就说明这个系统解决了实际的业务问题,是有价值的,是值得做好的。
一个被抱怨的大户,就是大名鼎鼎的遗留系统。也许它的技术很落后,也许它的系统设计千奇百怪,也许它的代码很丑陋,也许它各种不好用各种容易崩溃,也许它在技术的角度说,怎么都让人看不上眼。
但是遗留系统,尤其是那些大家都在骂,甚至深恶痛绝,但是却每天都在用的系统,可以说是一块璞玉。因为这些遗留系统帮你积攒了最有价值的东西:货真价实的用户需求,而且是怎么恶心用户都恶心不走的需求,简称刚需。抛开里面的技术不谈,这些业务需求,是值得我们一点点理解和掌握的。
理解了这些需求,就可以找机会改造或者设计新的系统,来替代老系统。需要特别强调的一点是,这个前提和基础在于一定要深入理解这里面的需求。如果你仅仅是从技术和代码层面觉得系统烂,就想重新做一个,大概率做出来的系统还是会烂。因为你如果没有对业务需求的完整理解,新系统的架构设计大概率也会无法很好地容纳这些业务。
老的系统也是因为架构设计没跟上业务的发展才会被一会儿一个补丁、一会儿一个临时解决方案、一会儿一个hotfix慢慢给弄得乱七八糟的。那么如果你在设计新系统的时候不去全盘理解业务问题设计更优化的业务模型那么很可能会重复老系统的坑疲于应对自己无法处理的业务需求然后变成第二个大家眼中的烂摊子。
举个简单的例子,业务需求是要在遍布泥滩和小水沟的地面行驶,而老系统则是造了一辆普通的车。时间久了,普通的车自然无法很好地应对这种路面环境,这里进水,那里生锈,还时不时抛锚,慢慢成了大家眼中的烂系统。
如果你再重新造一辆车用更好的引擎、轮胎、底盘。对应到软件上就是用了最新的技术比如升级SDK、升级各种软件包和技术栈、上云、用Docker等等。这些技术层面的东西当然对车有帮助。而且新系统刚开始因为没有历史包袱看上去好像还不错。但是慢慢地这辆车也会和原来的车一样变成一辆烂车因为传统的车就根本不适合在遍布泥滩和小水沟的地面行驶。
技术升级无法解决架构的问题。对于遗留系统,很多时候需要考虑的不是升级技术,而是升级架构。比如面对遍布泥滩和小水沟的地面环境,就应该用履带车,而不是用传统的四轮汽车。
## 总结
程序员加班的现状,是由不同的原因造成的。我们能做的就是不断反思、好好利用加班,让加班的时间尽量短,让加班的时间尽量对自己的发展更有好处。
如果是效率低,那就尝试提高效率。如果是有紧急任务,那就好好做、好好学。紧急的事情,是公司层面优先级更高的事情,更值得我们花时间做好。而对于现在被大家诟病的强制加班,也不能浪费了自己的时间。毕竟时间是自己的,一旦浪费了,损失的其实还是你自己。
不浪费时间的好方法,就是做一些没有业务压力,但是可以提升自己的事情。比如去把白天不懂的事情弄懂,优化现有的系统,或者去遗留系统里淘金。这些都是在为自己的发展积蓄能量。即使这些事情都没得搞,还可以多和同事闲聊一下,沟通沟通。大家都在公司,又不忙,是多么好的一个沟通的机会呀。
<img src="https://static001.geekbang.org/resource/image/ac/9d/ac981098d5d6d6ea224acc9ca1c3c99d.png" alt="">
## 思考题
你现在的工作需要经常加班吗?你是如何应对的呢?你加班的时候,效率高吗?
欢迎在评论区和我交流。也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。

View File

@@ -0,0 +1,105 @@
<audio id="audio" title="30 | 焦虑:程序员怎样才能越干越给力?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/fe/5d/fe70d09c53716df6accf903a3fb6aa5d.mp3"></audio>
你好,我是臧萌。这两天看了半佛老师的一篇文章,有感而发。文章叫做[《为何有的职业后期不给力》](https://mp.weixin.qq.com/s/QaUoAC0wzpQ42Qj48HTL3Q)。
你没看过的话可以去看看,当然,你要是懒得看半佛的原文的话,也不影响我这节课。简单来说,半佛老师从职业什么时候开始给力这个角度,把职业划分为了前期职业和后期职业。
前期职业刚开始很给力,后面越来越不给力,比如工作多年后,竞争不过新人,薪资待遇无法持续提升等。后期职业则正好相反。半佛老师的观点我还是比较赞同的,但是也让程序员这个职业看上去前途堪忧。所以我有感而发,想来和你一块谈谈程序员这个职业的前途。
## 焦虑着,也就习惯了
如果我在二十出头的时候看到这篇文章,肯定会焦虑得不行。那时候的我,非常像是半佛老师文中那种,可以被公司用完就扔掉的零件。所以我那时候就一个理念:提高自己的性价比。简单来说就是努力工作,好好学习。
“程序员是吃青春饭”的这个观点,其实当时已经有了。所以焦虑感肯定还是有的。而且当时看不清自己如何才能站住脚,稳扎稳打地向前发展。
最近几年,反倒是没有那么焦虑了。
一部分原因是焦虑惯了,这份焦虑感,让自己持续要学东西,跟上技术的发展。一段时间没学习没成长的话,就会感觉心里不安。
就像我经常提的那句话一样:软件行业在快速发展,一个技术如果适应行业的发展,那么势必一直保持升级换代;而保持不动的技术,基本都是不适应行业发展了,慢慢地都会被淘汰。因为程序员见过太多潮起潮落,一直这样焦虑着,渐渐就养成了持续学习新技术、持续扩建自己技术领地的职业习惯。
另一部分原因是,自己在误打误撞中,也算是走出了一条适合自己的成长之路。我觉得我在这条路上的有些感悟,对大部分愿意走技术路线的人还是有帮助的,在这里我想借半佛老师的文章为契机,在这篇文章里和你分享一下。
其实我在专栏里,原本有一节叫《对不起,程序员这个职业可能无法混到退休》。但是考虑到内容连贯性等原因,这一节中的很多观点和内容被拆散到别的章节去了。那这节课,我们再多聊聊程序员这个职业。
## 前期职业 V.S. 后期职业
半佛老师在文中,用前期职业和后期职业来给职业分类。前期职业的典型可以说就是程序员,后期职业的典型就是教师和医生。
### 职业类型是后期发展更好的决定性因素吗?
这里其实是有一点幸存者偏差的。其实仔细看看教师和医生,有多大的比例是在职业后期,成为了名师或者名医呢?
教师和医生可以一直做下去,这点对比程序员确实是优势,但是如果没有混出点名气来,待遇也不会提升太多,这么一直混下去有啥意思呢?
所以说,无论是程序员,还是教师和医生,想提升自己的待遇,肯定要提升自己的能力。这个过程必然是艰辛的,绝不是说选对了行业,就可以闭着眼睛随便怎么混都可以混出名堂来了。我们都在说,选择比努力更重要,但无论选择是什么,努力都是让一个人脱颖而出,提升自己职业发展上限的必要因素。
### 软件行业的特殊之处
借半佛老师的一个观点,软件行业是新行业,在爆发式发展中,缺人不缺钱。其实真就能力和产出而言,很多人是不值这个钱的,但是缺人,没办法。尤其是对于职业初期的人来说,多出几千块,其实就感觉挺多了。
程序员很多时候也确实要加班,工作强度确实很大。所以对于能力略逊一筹的人,只要肯吃苦耐劳,很多公司也愿意给到行业标准水平的薪资。比如说我自己,我就觉得我刚毕业那会儿不值什么钱,因为什么都不会。
种种因素,造成了程序员的起薪比较高。但是这也可能给程序员一种错觉,感觉自己就是值这么多钱。所以想当然地觉得,随着自己工作经验的增加,收入应该相应增长。但其实人才只会越来越多,程序员的精力会慢慢下降。所谓的工作经验,如果得不到市场的认可,自然无法获得更高的薪资。
更残酷的一点是,正如半佛老师所说(我附议),程序员用到的技术一直在更新换代,老师和医生在立住脚之后,可以不用持续在自己的专业技能上投入太多,也能混得下去,但是程序员却不行。
### 程序员这个职业更深层次的不同
那如果程序员可以保持自己的技术并且跟得上发展呢比如说一个程序员现在可以用主流技术熟练的写着CRUD的业务代码n年后依然跟得上主流技术依然可以熟练地写CRUD的业务代码。不得不说即使在这样的情况下程序员可能依旧很难跟得上行业主流的薪资水平。
为什么呢?很多人会说能力没涨,但是年龄涨了,精力慢慢不行了,自然不值那么多钱。当然这是一个原因,但是我觉得这不是主要原因。更主要的原因在于,软件行业需要程序员有创新的精神、有斗志、不安于现状。
比尔·盖茨是微软公司的创始人可以说他用Windows+Office软件改变了世界一点不为过。这里我借用比尔·盖茨的一句话微软离倒闭永远只有18个月。
你仔细思考一下这句话。很多人会觉得这句话是危言耸听,但是你纵观微软的发展历程,看看它经历过的那些低谷,这句话绝对是真实的写照。当然,微软最终没有倒闭,而且还发展得很好。有一点我想你肯定认同,那就是微软里绝对不是一群喜欢岁月静好,安于现状的人。
所以,公司也绝对不想攒一堆发展后劲不足、安于现状的员工。这是在给公司的发展埋雷。从这个角度,你是不是对为啥年龄大的程序员容易被淘汰这件事,有了新的认识呢?
当然,我并没有做过调研,去分析这些人被公司“优化”是什么原因。但是任何一个明智的软件公司管理者,都会淘汰后劲不足的人。简单来说,我相信很多公司都有或明或暗的规定,一线软件研发岗位,如果在某个年纪前无法升职到某个岗位,那么就必须淘汰。这是为了让公司保持活力的措施。
## 程序员的路怎么走?
在专栏中,我也尝试谈过我对职业分类的理解。当然这里只是谈论职业本身,并没有论高下的意思。也欢迎你在留言里说说你的想法。
### 不同类型的职业
首先是有些后缀为“员”的职业,比如售货员、收银员、操作员等等。这些工作的特点是技能要求少,而且技能本身不怎么需要更新。这些职业的工作成果,可以有非常明确的评判标准,工作内容也可以详细地用规定来约束。员工不需要去想怎么把工作做好,因为都已经规定好了。当然,这不是什么严格的分类,比如宇航员需要的专业知识、技能和素质,绝对比大部分职业要求都高。
然后是后缀为“师”的职业,比如教师、医师、律师、厨师以及我们软件工程师等等。这些职业的一大不同就是,产出成果的过程很复杂,影响工作的因素很多,无法规定标准的工作流程,产出的成果没有统一的衡量标准,所以这类人才是无法批量培养的。从业者需要积累大量实践经验,才能形成一套自己的工作方式。
就拿教师来说,如何培养学生,没有固定的套路;怎样才叫好学生,也没有统一的标准。这种类型的工作,就需要从业者发挥主观能动性,根据自己工作的经验,思考如何才能将工作做得更好。
最后是后缀为“家”的职业,比如科学家、教育家等。这些职业更偏向研究方向。做开创性的工作,工作成果的不确定性更大,对从业者的专业技能要求是无上限的。如果对别的职业来说,创新是加分项,在各种“家”这里,创新是起点。
### 程序员要怎么办?
回到我们的主题,程序员的路应该怎么走呢?我有两个建议:第一,技术要不停地学。第二,脑子要不停地思考。
技术这点我不再赘述了,技术一直在发展,不学的话,老的技术就被淘汰了。脑子思考什么呢?回到我反复强调的一点,那就是思考业务。思考自己所在的行业是在解决什么问题,问题是如何得到解决的。这是一个软件架构师必须锻炼的能力。无论我们有没有软件架构师的头衔,这都是我们不断进步所需要的养分。
回过头来再echo一下半佛老师的一个观点吃下的资源越多要替代你的成本就越大。对于程序员来说什么是资源呢就是日常工作、做的项目解决的问题等等。工作中亟待解决的问题是最宝贵的资源。能够理解这些问题解决这些问题那么收获的经验就是自己成长的后劲儿。
有人吃了很多资源,确实是成长到了更高的水平,但有人却成长不够快。那么公司肯定更愿意把资源供给这些成长的更快的员工,期待他们可以助力公司发展的更好。
软件行业确实残酷可能没有哪个行业里公司的危机感如此强烈。如果微软距离倒闭永远只有18个月那么别的公司呢如果公司本身都需要保持奋进才能生存又如何养着一群期待岁月静好的程序员呢
程序员不是一个能混的行业,混只能坑了自己。无论待遇如何,无论职位如何,问问自己:我今天学了点啥新东西吗?我今天悟到了点啥新道理了吗?
## 总结
根据我的实际体验在软件行业中一线程序员的高级人才还远没到饱和的程度。至少就现在的情况看对标阿里P8左右的高级软件开发工程师在市场上还是一人难求。在面对人才这个事情上绝大部分公司都不差钱。所以我们需要担心的不是自己以后有没有地方呆而是更应该注意如何才能让自己成长为人才。
其实只要有合适的候选人,很多时候公司更愿意雇用高级人才,一方面是出于人力成本的考虑,对公司来说,能力强的人投入产出比更高。另一方面,这些人才已经用自己的实力证明了自己的能力和成长的动力,公司可以更放心地向他们投放资源。
软件行业,真的不能混到退休。很多职业,即使是对于医生和老师这些职业,保持水准也是标配。一直保持水准做下去,并且提高自己则是高配,可以成为名师或者名医。但是对于程序员来说,提高自己才只是标配,超速地提高自己才是高配。长期来看,程序员的职业生涯,没有保持水准这个选项。
时间不等人,技术在更新。你要学会锻炼自己的工作能力,做好技术与业务问题之间的桥梁,用好公司给你的资源,成就自己的成长。
<img src="https://static001.geekbang.org/resource/image/0b/4d/0be907ff6b1ec0efcf1089c2ebd2704d.png" alt="">
## 思考题
在程序员的从业之路上,你有焦虑过吗?你是如何应对焦虑的呢?你是如何定义软件工程师这个职业的呢?你对职业分类的理解是什么?
欢迎在评论区和我交流。也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。

View File

@@ -0,0 +1,103 @@
<audio id="audio" title="31 | 数据观:在你眼里,数据到底是什么?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ff/46/ff0cec40d81a8e680a32dc9511a6bc46.mp3"></audio>
你好,我是臧萌。这一节我来和你漫谈一下数据。工作这么多年来,我看待数据的态度,经历了从轻视、差不多就行,到重视和严谨对待的转变,甚至对数据有些敬畏。
我相信很多同学在刚开始工作的时候,也是只重视程序不重视数据。程序员嘛,就是写程序的。数据结构、算法、设计模式,这才是我们程序员的战场高地。数据什么的,随便搞搞,别耽误我写程序就行。数据大不了删了重来。什么?不能删?那就迁移一下嘛。
还有的同学在抛出自己的观点时,经常是七分靠直觉,两分靠猜测,一分靠经验。就是没数据什么事儿。当别人就某个细节问下去的时候,就开始拍胸脯拍脑袋,但就是给不出什么具体的数据。这时候,沟通基本就进行不下去了。因为当每个人的观点有冲突时,光凭直觉、猜测、经验都无法让对方信服。
今天,我们就从软件系统和与人沟通两个方面,来谈谈数据的重要性。
## 程序重要?数据更重要
我们来思考一下这个问题,是我们设计的系统和写的程序代码更重要,还是数据更重要呢?相信很多同学都会下意识地觉得系统和代码更重要。但我觉得不然,数据其实更重要。下面我们来聊聊这个话题。
### 数据是软件系统的根本
我们来打个比方,数据就好像经济活动中的钱和账。数据在各个系统里的流动,就好像钱在不同的组织之间流动。无论是什么经济活动,做账都能把钱的流动一笔笔记清楚,通过账本,你就能够把经济活动给理解清楚。钱和账,是经济活动中最重要的。
公司可以今天卖口罩,明天卖水果,但是账的重要性是不变的。就好像软件系统可以重构、重写,甚至可以换技术、换语言、换平台,这都不重要。重要的是软件系统要能把数据落地入库。只要数据能够按照之前的规则入库,软件系统怎么改都无所谓。
在软件构造的虚拟世界中数据是唯一的真实存在。尤其是那些以数据处理为目的的软件系统更是这样。软件系统的目的就是把数据写入库。所以很多程序员戏称自己是专业的CRUD从这个层面来说CRUD才是根本。如果一个程序不CRUD不读取数据也没有数据落盘那它跑起来有啥用呢
下面我们再从实际情况来看看,为什么应该重视数据。
### 软件系统可以升级,数据很难升级
对于很多偏数据的系统数据架构设计比软件的架构更重要。数据的架构包括系统中有哪些实体、实体有哪些属性、属性分别是什么类型、实体与实体之间有什么关系、数据如何联动等等。当然也包括采用哪种数据库、数据库怎么分库分表等等。如果采用的是NoSQL数据库则要考虑数据的访问模式、数据的可靠性、数据的可用性等等。当然两种数据库都要考虑如何应对数据的增长问题。
为什么说数据的架构比软件更重要呢升级软件系统很多时候是可以测试的。只要最后输出的结果对就没啥问题。给软件系统升级还有很多方式可以让系统升级的影响更小比如灰度发布、A/B测试等等。只要底层数据结构不变底气就还有。只要程序没破坏数据出了问题回滚就可以了。
但是数据升级,难度就远远不止这样了。如果说给业务系统升级是给飞驰的汽车换轮子,那么给数据升级则是相当于是给飞驰的汽车换发动机。有时候还是得从内燃发动机换成新能源发动机,同时车还不能停。
为什么这么说呢?因为给数据升级,有很多沉甸甸的问题需要解决。这里我随便列出几个:
1. 数据如果不兼容怎么办?如果补的话,缺的属性值怎么补?
1. 数据的结构变化升级如何保证业务不受影响要知道历史数据的大小绝不是一个alter可以简单搞定的。alter一下数据库可能很久很久没反应甚至直接挂了都有可能。
1. 如何保证数据不丢失?
1. 这种数据升级往往是没有回退可能的,或者回退的代价极高。如何能做到万无一失?
删库的代价和删程序的代价是不能比的。删库给公司带来重大损失,甚至倒闭的例子有很多。但是把程序删了,恢复的挑战和风险要小得多。比如当年携程不小心把线上的程序给删了,但是真的恢复起来,也很快。对后续的业务,也没有任何影响。
这里我们再强调一点。程序写得烂,比如跑得慢一点,设计得不好等等,这些问题很多时候并不麻烦,大都是稍微花点时间就能够修复,也不会造成什么损失。我们写程序的时候,尤其需要注意的是生成入库数据和写入数据的代码。在对这些程序代码进行更改的时候,更是要谨慎谨慎再谨慎。如果破坏了数据或者写入了脏数据就麻烦了。这点一定要注意,敬畏数据。
### 数据是新时代的土地
对于很多行业来说比如AI、自动驾驶等数据就是根基。再牛的算法和模型也顶不过真实的海量数据有价值。算法可以招人来做实在不行可以买。而数据呢得自己积累需要时间和渠道。想购买数据呢也很难买得到因为数据就是核心竞争力谁会去卖自己的核心竞争力呢
我们可以把数据理解为新时代的土地,是一切的根基。有了数据,干什么都可以。没有数据,再好的种子,也没有发芽的空间。种子和土地,当然都重要,但是两者的分量不在一个级别上。数据够多,随便什么算法模型都能得出不错的结果。但如果没数据,能做到的事情就会很受限。可以说,数据起的是决定性的作用,是基础,是土地,算法和模型是地上开花。
即使是算法和模型工程师,日常工作中很大一部分时间,也是在整理数据。俗话说:数据从来不是干净的。所以能把数据整理好,基本上就胜利一大半了。
## 没数据,莫开口
我们之前反复聊了沟通。今天我们从沟通的角度来看看数据。我们可以思考一下,我们在和同事沟通的时候,信息是否足够地准确和清晰呢?我们在沟通中,有没有提供或者接收到足够多的数据呢?
### 先说数据
我刚工作那几年,交流的时候经常无法传递准确的信息。比如被问起数据量增长了多少,我就说增加了一点;被问起数据丢失了多少,就说丢失了不多;被问起一行数据有多大,就说不太大;被问起有几个单元测试没过,就说没几个。有时候对方不再追问,我可能还感觉自己回答得挺好。
有时候对方一个反问:增加了一点具体是增加多少?我就傻眼了,可能支支吾吾也说不出个所以然来。当然,数据我确实是看过,在我看来,也确实就是增加了一点,但是具体的数字没上心,被问起来,就很尴尬。
可能有时候我心里还有点不平:一点就是一点,你管他多少,反正不多嘛。但是实际情况是,每个人对于一点、不多、不大、没几个这些词语的理解都是不一样的,很多时候这些都会掺杂进个人的判断。而交流首先应该提供事实,而不是个人的主观判断。当大家对事实都有了一致的认识之后,再各抒己见。
再比如说单元测试很多人看来一个不过就是有问题的也有的人心大觉得10%以内的就没问题。当然这个也和具体的项目有关系,可能某些项目的单元测试已经对环境有依赖了,有几个不过确实难免。所以,交流应该从具体有几个单元测试不过,具体是哪几个单元测试不过这些方面开始。而不是上来就给出自己的结论。可能有些测试特别重要,而且一定要求过呢?
所以我渐渐地养成了给出准确数据的习惯。任何问题,先找出数据,罗列清楚,再去做自己的分析。准确、经过整理的数据是自带力量的。我们经常说:一图胜千言。这里除了具象的图画之外,我觉得图表也应该算在这个图里面。一份整理好的数据传递的信息,有时候胜过反反复复地讨论得出的结论。
### 注明出处,交叉验证
很多时候,仅仅是列出直接的数据还不够。为了更全面地理解问题,还需要注明数据的出处,甚至需要从多个数据源来交叉验证数据。数据是我们用来做判断的依据,对数据的态度要仔细认真,否则后面基于数据的讨论、结论和方案,可能都会是错的。
注明出处是对数据负责。很多时候,罗列的数据可能并不全面。注明出处,方便你可以根据出处去对数据进行更详细的检查。而且不同的数据源,数据的可靠性也不一样。可以说数据源本身,就是数据的一种。
关于交叉验证我举个简单的例子。A服务调用B服务那么要验证服务调用的增加量自然需要对A服务对比过去一天的服务调用数据为了更加全面还可以增加上周同一天上个月同一天调用量。同时呢从B服务这一端也可以做同样维度的考量这就是从另一个数据源做交叉验证了。如果发现两边的数据有差异那么就要先找出差异的原因再来看调用的增加量。
这里我再举一个生活中的例子。市面上有很多种牛奶:巴氏杀菌牛奶,高温杀菌牛奶,常温酸奶等等。如果要选一种牛奶喝,你会选择哪种呢?在做判断之前,你可能会觉得酸奶风味好,但是有糖热量高,在我去超市逛了一趟之后,我收集到了下面这些数据:
<img src="https://static001.geekbang.org/resource/image/e3/30/e385d4b45c1f05d22ec3eb209f008b30.jpg" alt="">
数据来源是商品外包装标注,这个来源还是可靠的。同时经过了多方对比,我看了三个主流的牌子的牛奶。这些数据是事实。酸奶是用乳酸菌消耗掉牛奶中的乳糖,所以无添加的酸奶肯定是酸的,因为乳酸菌会生成乳酸,这是常识。在这个基础上,我们可以去推断自己的结论。比如下面两个结论就是比较初级的结论:
1. 纯牛奶的热量是差不多的上下不会超过10%。无论是巴氏杀菌牛奶还是高温杀菌的常温奶。
1. 酸奶的热量比纯奶更高说明添加了很多糖以及其它增强其风味的物质。一般来说会比纯奶高出20%~30%。
有这样一张表格是不是说出来的话就更有力量了什么叫差不多相差不到10%就叫差不多。什么叫酸奶比纯奶热量高高出20%~30%就叫热量高。
## 总结
数据是有分量的,对数据的辗转腾挪,都要费很大的劲。数据是有力量的,当你把数据整理好罗列出来的时候,甚至都不用说明自己的观点,就可以不言自明,让人无法反驳。数据是最难获取的,真正有价值的数据,钱是买不来的,只能靠自己积累。数据是软件系统的目的,和现实中业务相关的软件系统,无论业务逻辑玩的多花,最后都是要生成相应的数据,落盘为安。
数据不会说谎,数据很难伪造,数据中最重要的一个属性就是时间,这让数据可以日积月累的积聚力量。小小的一张地铁卡,只有两个操作,滴,刷卡进站,滴,刷卡出站。如果一个人用地铁卡刷卡上下班,一次两次,数据确实没啥意思。
但是如果这张卡积攒一年的数据,那么数据的力量就会爆发出来。它可以证明这个人有稳定的出行时间和路线,从而可以证明这个人有固定的工作地点和居住地点。这就是一个人信用的证明。这个数据,能伪造吗?一次两次,可以。长期下来,很难。
数据是什么?让我们在工作中来重新思考这个问题,重新认识它吧。
<img src="https://static001.geekbang.org/resource/image/93/c7/932f8803901f18b0e5c7f9ee003c8ec7.png" alt="">
## 思考题
我们每天都在跟数据打交道。你是如何看待数据的呢?你在设计程序的时候,有重视数据存储的设计吗?你在与人沟通的时候,有注意把支撑自己判断的数据都罗列出来吗?
好,今天的加餐到这里就结束了,希望可以帮助到你,也希望你在下方的留言区和我参与讨论,并把文章分享给你的朋友或者同事,一起交流一下。