资源访问控制上的一些思考

业界有很多种权限控制的设计模型。做过访问控制的人或多或少都比较过这些方案的优劣。我过往的一些相关经历,让我发现一些在做这个选择的时候,可以思考的问题。简单梳理一下,以作备忘。

引入访问控制的目的是什么?

这是非常重要的问题。是“为了安全”吗?不,这个目的太宽泛了,宽泛到无法指导你做任何有效而且合理的决策。作为一个安全策略的制定者,除了“为了安全”之外,必须要搞清楚,你要防范的人是哪些,想要控制其的哪些行为。不用很细,但是至少是“原则上”地。比如:

  1. 要防范的人,分哪些?公司内部,公司外部两类吗?防范方案有什么不同?
  2. 防范他们的什么行为?是要防范他们无意的误操作?还是要防范他们恶意的删库跑路?真的都要吗?
  3. 你愿意为了“安全”将效率牺牲到什么程度?比如,为了保护代码安全,最安全的做法,显然是给电脑断外网,并且禁用除显示器外的所有输出设备,不允许带入手机,也不允许把电脑带出,而且办公室不能有窗户,以防对面办公楼的长枪短炮拍摄到你屏幕上的代码。这个时候,你可能牺牲的不仅仅是效率,可能还有员工的技术成长、身心健康,以及这个岗位的离职率。这可不是说段子,很多外包IT公司的部分项目就是这么搞的。

访问控制的主体是谁?

或者说,谁应当受到访问控制?

  1. 人。人分哪些?内部员工,外部用户,还有吗?他们的权限模型需要统一吗?能够统一吗?
  2. 服务。首先,服务本身需要访问控制吗?我认为是必要的。因为服务所应当有的权限,是很难和公司内部某一个人的权限完全一致的。而且,人的变动会远多于服务的变动。对服务本身的访问控制的管理成本,一般也会远低于对人的访问控制的管理成本。另外,不要觉得对服务这个东西的访问控制很不自然,你手机上的App,也算是一种服务。而你肯定是想管理App的权限,而不是App的开发者能在你的手机上干什么。我见过的最奇怪的规矩是,权限只能给人,不接受给服务本身设置访问控制方案,但是接受服务以root身份运行,也接受负责服务的人,拥有本当属于服务的权限,也即生产环境的所有权限。当然,我也理解他们给出的解释:出了事儿,他们可以很方便地定位到责任人。而且他们只需要维护人的权限,完全不需要考虑服务的权限这么个事儿。这对他们自己而言,这的确是最安全的方案。
  3. 要统一吗?人类才华产生的最大非理性的冲动,就是见到分开的东西,就想找到一个统一的方式去处理,比如爱因斯坦干的那事儿。也许能统一,但是作为一个企业,而非一个科学家的时候,你要着重考虑的是成本收益及可操作性。而不是一个方案看上去有多完美多NB。当然,如果你要拿着这个方案去骗某个风投的话另当别论。

访问控制的客体是谁?

或者说,控制对什么东西的访问?显然并不是所有的东西都需要访问控制的。但你判断一个东西要不要做访问控制的条件有那些?要不要花钱?会不会失控?举几个例子:

  1. 办公室空调的按钮。据我了解很多人都希望有,但是这并不需要权限系统来解决,如果真要暴力解决,这只需要一些胶带并让公司行政把遥控器收好。
  2. 数据库DDL。这个一般都是要控制的,但是再考虑下主体,你要想好想让哪个主体来做。是人,还是服务?是开发还是运维?如果你选择人,那基本上就和市面上的DB Migration框架说再见了。这也说明了,访问控制上的一些高层面的决定,会影响你服务内技术栈的选择。
  3. 服务运行时环境变量及参数。这个伪逻辑是这样的,环境变量的变化,可以彻底改变应用程序的行为,所以要严格控制对环境变量及参数的改动,只能由维护人员有权限改。于是上线的过程,就需要由开发给运维交待一整页配置变更。于是,基本告别Continous Delivery了。当然,这个时候人们一般都会安慰自己说,我们其实也并不需要CD,而不是反思前面的问题有没有更好的解决方案。毕竟项目都是有Deadline的。

谁负责设计资源访问的细节?

我之前在一家投行工作,公司使用的是一个内部自研的权限控制系统,混合了ABACRBAC两种方案的优势,其权限数据结构是可定制的,由各个业务团队自行定义资源的一切细节,非常强大灵活。那段时间,负责这个框架的那个团队,开始做这样的一个事儿:用AI技术,分析当前的权限配置中不合理的部分。因为公司当时面临这样的一个问题:连业务团队自己,都已经无法看出自己的权限数据中有什么问题了。因为绝大多数情况下,人们使用这个框架的方式都是:简单看下原来的数据是什么样的,用最少的改动,最少的数据量,就可以完成这次权限配置变更的要求。而不会去深入地思考,“应该”做什么的数据变更是最合理的。最后这个权限控制数据库就失控了。不过好在人们都知道这个问题,并且在积极解决。所以再好的框架,再好的设计,也会因为不当的使用而难以发挥其里大的价值。那么哪些是使用上的细节和设计上的细节呢?比如:

  1. 公司到底有哪些角色?这些角色应该有哪些权限?这些细节是技术人员先定一个,还是先和相关方讨论清楚?
  2. 公司有哪些资源是比较容易分辨的,但是每类资源应该有哪些属性呢?是加属性好?还是加新资源好?
  3. 可以为每笔交易都定义一个独立的资源项吗?
  4. 客服需要客户信息,交易员也需要客户信息,但是需要的部分不同。这时,这两类客户信息,是两种资源吗?

类似以上这些问题,无论如何选择,都是可以完成工作的。但是质量上却有云泥之别。只是有些差别,有些后果,要出现后续的状况时,才会体现出来,做决定的时候,常常因为“都可以”而无视掉。

谁负责设定资源访问的权限?

即授权。一个简单的回答是:owner。然后下面的问题就是,谁是owner?我只想表达一点,从权限控制的角度,同一个东西的不同方面,其owner可以是不同的。比如:开发写了一个接口,这个接口谁能调用谁不能,肯定不是这个开发人员决定的,至少也要构架师才能决定;但是同一个接口,假设为了保护自身稳定性,添加了访问频率的上限的设定,在不影响整体服务功能和可用性的情况下,这个设定的owner可以是而且应该是开发者本人。

说说“对事儿不对人”的打开方式

“对事儿不对人”大概算是少有的几个无论内资外资都会声明认同的行为准则之一。但是却少有写进公司官方员工手册进行详细解释的。我不是官方,但是我想解释一下,也许你还能顺便悟出这个词为啥没有官方的详细解释了。

开宗明义,对事儿不对人,更合理的做法,是指做决定、决策的时候对事儿不对人,而不是指提建议或批评的时候对事儿不对人。容我娓娓道来。

声明

体制内的看官看看笑笑就好。我这里说的是体制外的情况。

建议与批评时

我们回想一下,批评一个人,或是给一个人提建议的时候,最重要的一条是什么?是要私下进行。对不对?你公开批评一个人,哪怕你批评得对,哪怕你职位比他高,有的人也会不接受,因为面子挂不住啊。他面子挂不住了,搞不好还要牵扯出你祖上十八代来撑场子。所以说正常人根本不会在公开场合批评某个人,还有什么“对事儿还是对人”的问题呢?

那么,公开场合,审明公司组织纪律算什么?比如有人天天拿公司牛奶洗脸,公司开全员大会,你猜会怎么说呢?会说是谁干的吗?不会啊,会说牛奶洗脸这事儿吗?也不会啊,你如果说,不让牛奶洗脸,那洗手呢?不让用牛奶,我用咖啡粉行不行?场面上会这么讲,公司将严厉惩戒将公司资产私用的情况。这叫既不对事儿,也不对人。使用官方用语。泛指你们所有这些烂人干的所有这些破事儿。普通员工去批评人,哪怕是批评一个群体,也不敢用这种“既不对事儿,也不对人”的口气,因为规格不够。也就CXO才可以。所以公开批评也没有“对事儿不对人”的问题。

好,那我们说私下批评,想象一下,你找到了那个用牛奶洗脸的员工。用对事儿不对人的说法怎么说呢?

A: 小王啊,我听说公司的牛奶常常失窃,搞得大家天天只能喝黑咖啡。你离厨房近,你帮忙看着,发现了告诉我一下,我们看能不能把这个小王八蛋逮着。

W: 你拐弯抹角地骂谁小王八呢?

而且,其实公开场合提建议也应该针对具体人。 比如代码评审会的时候,

我提一点儿,不针对任何人(哦,原来是要说我们所有人)。按编码规范,方法参数最好不要超过5个。我看刚才不少代码的参数都十七八个了,这个会后改进统一改下。

完了,这事儿肯定没人干。有人感觉我没问题不用管,有人有问题,还没到十七八个,等别人改好了我再改吧。最多的那个人压力本来最大。一听到“统一”改就想着这事儿不用我个小愣头青操心了,肯定要大牛出手啊。 当然我这里YY,实际情况不会这么糟,但是显然也不会太好。

试问,提出问题又不针对人,这事儿还怎么SMART化?每次都是:“我不是在说某个人,我是说在座的所有人。”不成? 所以提建议,批评,就应该对人。否则起不到效果。

换一个角度,如果一个人连别人私下的中肯的批评都承受不起,我不知道这个人还能承受得起什么? 而且如果你批评得对,也不用担心被批评的人,用“对事儿不对人”反驳,因为听上去很二。比如:有人随地吐了口痰,你应该不大会听到这样的对话:

A: 唉,你怎么随地吐痰啊。

B: 唉,你这人批评不要针对人好不好。

倒是可能会听到这样的对话:

A: 唉,你怎么随地吐痰啊。

B: 你找打?

人与人之间意见不同是非常正常又常见的,有分歧就打开门讨论。拐弯抹角地旁敲侧击得搞到什么时候? 当然,对人,不表示针对某个人,更不表示人身、人格攻击式的批评与建议。

决定与判断时

最后来说说,什么叫做决定做判断的时候,对事儿不对人。

我举个例子, 线上一个服务负载过高,需要找运维人员加一个节点。我相信如下对话模式,做过开发的应该都不会陌生。

开发: 能给XXX服务加个节点吗?

运维: 你说加就加啊?自己服务有性能问题先解决自己性能问题啊。

VS:

总监:能给XXX服务加个节点吗?

运维:好的,马上,好了告诉你。

另一个例子:

开发:能不能从你们的ElasticSearch里直接读数据啊?

运维:这不行的,万一你们做个大查询什么,直接就把日志服务搞挂了啊。

VS

总监:能不能从你们的ElasticSearch里直接读数据啊?

运维:我想想啊,也行,注意控制下查询参数不要太宽哈。

这就属于对人不对事儿。一个客观的事儿,能不能做,要不要做,应该由客观情况决定,不应该看这个事儿是谁来问的。至于某天晚上聚餐去哪儿玩,如果领导有想法,当然要听领导的。因为这是主观的事儿,没有客观是非。

对于这个问题,我还得意和一些从阿里出来的人聊过,我以为阿里这种政委风气重的地方,简直就是培育看人办事儿风格的沃土。结果对方十分肯定的讲,同一个事儿,谁去问都是一样的,不会有不同的答案。我对阿里的印象因此还好了些。

反过来讲,就算做决定的时候对人又怎么了?问题多了。比如工作低效啊。本来可以交给某个小弟去处理的事儿,搞得什么事儿都得我自己来,而且小弟们也会挫败感十足,好像自己什么事儿都搞不定一样,虽然问题根本不在他们那儿。我要再有点儿心,还要去安抚小弟。我怎么说呢?这不是你的问题,这边儿风格就这样,适应适应吧。他心想,哦,公司这个问题好像有点儿严重啊,我还是换一家吧。

更宽泛地讲,对事儿不对人,本质上是在说,在工作上,要以事实为依据通过理性思维做决定,而不要感情用事。 回到一开始的问题,你猜为啥一般公司都不会详细解释“对事儿不对人”呢?

有人听到这儿就上头了,说实现中,你看看哪家公司是这么做的,完全不切实际!你说得对,就像几十年前会随地大小便那帮人,看着“不要随地大小便”的标语时,也是一脸的莫名惊诧:大家都随地大小便啊,这个标语完全没说到重点啊,明明应该写“随地大小便时请注意遮挡”,这才合多数人的心意。 是吧?

从模式匹配与类基多态之间的选择说说项目的良性成长

一个选择问题

网上可以找到不少讨论这个话题的文章(如果你不知道为啥这两个东西要放一起比较的话,建议你先读懂以下这两篇,或者跳到下面讨论重要及解决方案的部分):

本文不讨论模式匹配和多态是什么,这种知识性问题。本文只想先讨论一下,如何正确合理地使用这两样东西。

因为了解一个东西,其难点从来都不是知道它是什么,它有什么优缺点。这些都是非常简单的。真正的难点是,拿到现实场景中,分析出并现实中需要考量相关因素是什么,分清主次,并做出合理的选择,以及,最容易被忽视的:接受相应选择背后的成本。否则就会出现,知识性的东西说起来头头是道,但是就是用不对地方的问题。举几个反面教材来做热身。

场景一:

A: “我这个类有好多字段,写个equals和hashcode方法都要写半天,apache commons用起来也不方便。”

B: “用data class啊,自带了equals和hashcode的实现啊。少撸好多代码,多Clean Code啊。”

场景二:

A: “这边儿处理各种税费的case好多啊,处理起来好乱啊。”

B: “用case class啊,然后用模式匹配给各个情况分别处理,多清楚。”

你看,这一来一回的字面上的逻辑都是通的。但是其实逻辑狗屁不通。 或者至少是没用到点子上。

做正确的选择并承担成本

说了一堆废话,还是开门见山地陈述一下自己的观点。

多数文章都会讲到:“模式匹配,便于扩展功能;多态,便于扩展类型。”但是从来不会提到前提及代价是什么。所以我想补充一下。

关于模式匹配:

  • 用对的前提是,维护好功能实现的完整性。一个功能就用一个函数或函数组实现。什么意思?意思就是当一个新的类型加入的时候,直接修改现有代码分支,而不是在外面包一层,谓之不动老代码,安全,还冠名Proxy啦,装饰者啦来justify这个拙劣的决定。这也展示了一种常见的出品屎一样的代码的方式:一个代码库中,不同的开发者,把不同设计理念杂糅在一起,相互交织。每个人的想法单独拿出来或许都是对的,然而不那么上心地堆放一起,就变了一坨屎。
  • 另一个前提是,最好用在类型真的不大会新增的场景下。否则不是给自己找麻烦吗?这个说起来容易,到具体问题上就容易抓瞎,一年有四季,不会有五季,这种一看就适合用模式匹配。屋子里的房间类型,客厅厨房什么的,也还行。但是如果产品拍着胸口说句话,税费就这几个类型,然后你就开心地决定用模式匹配了?
  • 代价是,以整个函数为单位实现功能,功能就是封闭在函数内的,你没有办法在不修改现有代码的前提下,修改一个现有的功能。这算什么代价?代价要看场景,我举个例子,插件体系。基本都是通过新加类来扩展功能的。没有哪个插件是通过动态修改主体函数内实现来扩展的,因为不好改啊,有也是Hack,需要很底层的机制,成本也很高。所以没有哪个插件体系是基于模式匹配的。当然还有别的场景,引入模式匹配的代价也是完全不可承受的。要具体分析。

关于类基多态:

  • 前提是,不要对“便于类型扩展”有什么误会,如果是那种会产生类爆炸的场景,无论是模式匹配还是类基多态都是不合适的。你可能需要的是数据化,也可能更需要重新思考你的类体系设计。
  • “便于类型扩展”的代价是,同一个功能,其实现逻辑,会散落在各个类中。于是会相对比较难以从代码上,获得对某个功能的完整的全局的认识。但是这不应该是你声称一个代码不可读的借口。多态的代码读不懂,是你自身水平够的问题,不是写代码的人写得烂的问题。

我们选择一个东西好的一面的同时,事实上也同时必须承担相应的成本。选择不仅仅要看正面的效用,也要乐于接受其负面的损耗。最怕是什么呢?两个方式的好处想全要,又想易于对类型扩展,又想易于对功能扩展。讲道理鱼与熊掌不可兼得,他开启杠精模式,说那是你水平问题。也是,我的确没有水平创造出这样一门全新的语言来。

这种选择有多重要呢?

最后一个问题,这个选择,把这俩东西用对这么个事儿,有多重要呢?

从现状来看,一点不重要。我这工作十来年了,从来没见过哪个公司的Code Review(如果有的话)中,大家会聊到如此深入的设计理念上的细节。为啥?因为即便你用错了,如果就那么几个地方,加加班改改就是了。如果用错的地方太多,而且错误又不限于模式匹配用得不对这一个问题,就干脆立项重写好了。把产出垃圾代码的锅甩给前任,现任人员从上到下都是功绩。所以没人死扣代码质量。况且,也不是所有人都喜欢讨论这种问题。有的人喜欢死扣细节,有的人还不高兴:“没bug能work的代码,非他妈要讨论写成啥样好,还讲一堆大道理。早点回家吃饭不好吗?蛋疼。”。

然后呢,重写后的第一版,一般都是好的。但是之后,就也走向越写越烂的老路了。然后又是新一轮的重写。最终结果呢?每一轮产出的都是垃圾。如果公司业务良好,走在快车道上,不差钱,倒也不在意这些重写的损耗,只要每次打完补丁,每次重写完,都能满足业务要求就好。人不够就加上嘛。有人什么垃圾代码搞不定?但是如果公司处于一片红海,整体经济环境又不乐观呢?一个人写垃圾危害也许还可控,如果一个公司整体风格就这样,那这些拙劣的设计和代码,迟早会拖累公司的成长速度。

还有一个问题是,如果一个人,其工作涉及到了模式匹配,多态的使用,但是他都没有办法正确使用的话,你如何相信这个人,能正确地使用各种设计理念更加复杂的框架与中间件呢?比如Spring Boot, Spring Cloud, Kafka, RabbitMQ。我是不相信的。

还有一个问题是,如果一个公司,对这些完全不在意,不去鼓励甚至要求员工去关注细节,一些员工就会觉得没有成长(尽管满眼的机会他看不到),没有技术含量(尽管一堆的技术问题没有解决)。然后这些一般般的员工也就离职了。优秀的员工是什么态度呢?他们这种嗅觉敏锐的,会第一批走,才不会甘心在一滩烂泥里同流合污呢。剩下的,就是没有丝毫追求,没有技术水平的员工。毕竟他们找新工作一般也比前两种人困难。 当然这是里糟糕的结果,也比较少见。我干了这么多年也只是听说过些故事。大家当段子乐乐就好。

解决方案

写了这十多年代码,对于如何解决这些问题,小有一些心得。如果一个团队的人,可以做到如下几点,是可以遏制项目腐烂的趋势,如果都做得不错,项目才能长期地向上成长。(如果这个公司的战略需要这个项目长期存在的话)

  • 不要Patch它,Fix它。我是这么判断是不是打Patch的。当你去改代码的时候,脑子里萦绕着“尽量不要动老代码,仅仅针对发生问题的这个case就好”的时候,你就是在打Patch。在以快速和不影响现有业务的幌子,行无脑不负责任编码之实。因为真正Fix一个东西,是要从这个问题是如何产生的开始,到仔细考量最合理的解决位置,以符合现有代码的设计思路的方式来处理。这个工作量与Patch不可同日而语。但是一个维护良好的代码库,Fix一个问题的成本永远是可控的。只有失控的垃圾代码,才会陷入“要从根本上解决这个问题,差不多要重写。”的窘境。
  • 认真地读现有代码,读懂。这是找到Fix方案的前提。如果你代码都没看懂,那碰到NPE的时候,那的确是,除了加句if not null,打个自己都不知道行不行的Patch,你的确也做不了别的更多的了。如果你感觉现在这个代码太垃圾,那太好,你展示才能的时候到了不是吗? 一般烂代码都是好读的,因为写的时候就没用脑子,只是分支多些罢了。设计精巧的代码才不好读,因为写的时候就是花了脑子的,你也不用指望自己脑子都不过就能轻而易举地看懂。如果你连烂代码都读不懂,那我建议你转行吧。读代码是基本功。
  • 编写有效的测试。如果你连有效的,能发现代码变更产生的非预期的bug的测试都没有。你当然也是不敢动现有代码的。如果没有测试怎么办?太好了,你可以通过写有效的测试来尽快熟悉这个系统的功能。另外,光看代码覆盖率是没有用的,我可以轻而易举地写出100%覆盖,但是实质上毫无用处的测试代码。
  • 持续改进。这个涵盖比较广,细说能独立开一篇文章。但是这部分才是解决根本问题的精髓。不断地发现问题,解决问题,一个系统才能成长。把问题隐藏掉或是绕过,都不是长期的处理策略。这里的重点在于追求卓越的心态。比如,抱着“大家都是这么搞的,所以我这么搞就可以了”的心态,是没办法改进的。要持续改进还包含要实事求是。事实是什么样就是什么样,不看人,不双标。不要因为这个代码是CTO亲手写的就不敢动,不要因为一个需求是CEO提的就不敢讨论。自己到底在什么位置上都看不清,对与错都不敢坚持,是没办法改进的。

但是问题是,我还没有见到过哪个团队的所有人,都能做到如上所有点的。毕竟,每个人写代码的动机,都是不一样的呀。

聊聊一个自行车棚的故事

之前因缘既会看到一个单词,bikeshedding,和它背后的故事。想和大家分享一下。wikipedia上可以找到故事原文,我这里简单用现代文描述一下。

上世纪60年代,某国财政部讨论建设核电站的议案,该议案有三个部分。一个是预算10,000,000英镑的核电站,一个是预算350英镑的员工配套自行车棚。一个是每人每年21英镑的午后茶点供应。

在议案的讨论过程中,预算10,000,000英镑的核电站主体部分,经过2分钟的讨论即获通过。因为内容细节太专业了没人看得懂。 而且毕竟人们都认为这个事儿反正要搞嘛。

然后大家对于350英镑的自行车棚的预算金额的合理里展开了激烈了讨论。有人表示车棚用的铝质材料过于奢侈,应该用石锦以节省成本;还有人表示3个月的工期长得不可理喻,说自己在家里后院搭过一下,只用了3天时间。本部分最终以削减50英镑预算而获通过。

最后一个议题也花了一个多小时的时间,但是由于部分细节的缺失,会上没有对此部分展开表决。并要求会后继续补充细节。

这个故事当然是杜撰的,但是道理不爽。在现实中,如果我们细心回想品味,其实也不难找到对应的案例。 在我看来,在软件工程领域,类似自行车棚的东西也很多。比如传输格式用SOAP还是JSON。

与其在这种层面的技术选型上花时间,甚至花时间比较各个方案的代码量、可扩展性、性能,倒不如花时间讨论一下,如何更好地设计框架,以便我们能随时在这些选择上做出变化。

简单而言,对于技术公司,技术层面上对方方面面的斤斤计较也许是必要的。对于非技术型公司,技术层面的选择问题当然也重要,至少不能比同行用的差太多,但是更重要的是技术层面的灵活性,能够快速应对市场变化才是一个业务驱动型公司赖以生存的根本。我相信,所有的产品,都不会听到技术人员如是描述他们系统的现状:

  • “数据大多了要分库分表?大概至少两个月吧,涉及的代码太多,而且每个项目访问数据库的方式都不一样,整个过程风险也比较高。”
  • “加一个商品品类?这个牵扯甚广啊,需要多个部门协调啊。要不你兼职一下项目经理?”

在非技术公司,还有比技术层面灵活性更重要的事情,就是分析清楚,从业务和系统功能角度,我们到底需要什么。给这些业务功能的重要性分级,并把技术上的问题挂靠在需要这个技术点才能支持的业务功能上。以免空谈技术方案本身的优劣。(这里补充一下,“搞清楚我们到底需要什么”不仅仅是产品的工作,需要产品和技术协同才能达到。这部分内容超过本文范围就不展开了。)

这个话说起来容易,但是具体到实际问题,如果没有点儿功力,可能会面临这样一个严峻的问题:摆在面前的这两个东西,哪个是核电站?哪个是自行车棚?比如:

为了支持大量的业务消息数据,所以要引入Kafka做消息中间件,还要招聘相关的Kafka运维支持人员,为了实现对数据的保密,所以要对Kakfa消息加密,因为我们数据敏感,所以要有审记,要有ACL。 于是要和公司SSO集成。相关配置要能适应业务随时变更的要求,所以以上Kafka的定制行为,要能通过访问公司的配置中心中的配置,完成变更。

请问,上面这段高层需求陈述,从哪句开始陷入了bikeshedding呢?

当然并不是这种选择问题都是bikeshedding,比如用Java还是.NET,服务网关是用Spring Gateway还是nginx这种涉及整个技术栈及人员配置的选择问题还是需要慎重对待的。

但是那个问题又来了,一个公司的技术栈选择和人员配置,到底是一个公司的反应堆的一部分还是反应堆边儿上的自行车棚的一部分呢?

你看,那锅粥里好像有颗屎唉

“你看楼下有人在遛狗唉,这都什么时候了,他还有心情遛狗,物业也不管管。”
“就我们的物业垃圾的,只会收钱,别的什么都不管。”
“一点都不自觉。”

“刚才小区里遛个狗回来,发现有人在小区门口收快递,也不怕被传染。”
“就是,我都是让快递员把东西放快递柜,我过两天再取的。”
“居然还买外卖,我都吃了一个星期泡面了。”

“明天我辞职也不送你们小区了,太危险了,都不敢进去。”
“嗯?没听说我们小区有病例啊。”
“反正我一打电话一个隔离,一打电话一个隔离。”
“要我说,他们就是自己懒得下楼而已。”

“有出入证吗?”
“我刚就在小区门口去取了个快递,1分钟都没有。”
“那我不管,没有出入证不能进。”
“我就住这儿的,你凭什么不让我进?”
“我们也没有办法,上头这么规定的,没有出入证就不让进。”

“哎?大婶你怎么不戴口罩啊?是还没领到口罩吗?”
“哎呀,我儿子打电话说没带出入证和你们保安吵起来了,我得赶紧给他送出入证去。”

“我刚看到楼下有个大婶没有戴口罩,往小区外面跑,后面还有保安在追。”
“不会是疑似病例拒绝隔离吧?”
“这年头SB太多了。”
“有的人就是只顾自己,不考虑别人。”
“就是,一颗老鼠屎坏了一锅粥。”

聊聊“结果导向”

“结果导向”的意思很简单,很明确啊。就是注重“结果”啊,看“结果”,成王败寇嘛。这有什么好聊的呢?因为“结果”和“导向”都不是字面看上去这么简单的事儿。

要说“结果导向”,就不得不先讲与之对应的“过程导向”。过程导向的人,喜欢追求过程的完美度,认为好的过程,正确地做事儿,总会有好的结果,有种“尽人事,听天命。”的感觉,最后失败了,就安慰自己说“重在参与”。更严重的是,过程导向容易迷失在无尽的细节之中,过度追求局部的完美,而忽略了最终要解决的问题到底是什么,然后项目就容易跑偏。如果一个领导是过程导向的,他会倾向于安排好整个项目的每一步,流程、手段、最终的结果的细节规划得规规矩矩得。后果就是手下人其实就是单纯地执行,没有发挥空间,也就没有主观能动性。我爷爷奶奶那辈儿,就已经有了这类人的代名词,叫“算盘珠”。

所以结果导向被提出来,其实是为了解决上面的几个问题的,归纳如下:

  1. 让人有明确的目标
  2. 让事儿有成败的标准。
  3. 让人充分发挥主观能动性。知道自己要做什么,目的是什么,价值如何体现。做正确的事儿(结果导向),而非正确地做事儿(过程导向)。

其中第3条其实是结果导致的根本。一个人知道自己在做什么,知道该做什么,不该做什么了,不再像算盘珠一样全凭人使唤了,其他的问题都不会是什么问题。

这事儿说起来简单,但是做起来其实很容易跑偏。有人可能嘴上天天“结果导向”,然而做起事儿来还是“过程导向”的风格。我不举例子,我只围绕“结果导向”讨论几个话题。

什么是结果?真正要追求的那个。

有人说很简单啊,大家找你要的那个东西,不就是“结果”吗?

那么我问一个问题,你从小学、初中、高中12年间,大多数的老师、家长找你要的结果是什么?是分数,是XX重点大学的录取通知书。大学的结果,是毕业证。那么这些东西,是结果吗?你12年学习的结果,就是一个数,一个证吗?好像不是吧。那是什么呢?

说得俗点儿,正确的结果,好像应该是把自己打造成一个“德智体美劳全面发展的四有小青年儿”吧?但是因为这个结果不太好判定,所以教育体系只能用一纸考卷把这个答案量化,同时把教育的内容片面化,跑偏化。

但是四有小青年儿们不要被带跑偏了。你可得知道自己苦读十数载到底是为了啥。

我的意思是,别人找你要A,你不能就想着如何给A,并仅仅把A做得完美。得主动地往A后面的真正的问题和动机去想。然后你给出去的东西,可能看上去都已经不是A了,但是效果是与A是等同的,甚至更好。

做每件事儿的结果只有一个吗?

不知有没有人注意到,“结果导向”的英文是“Results-Oriented”,其中的“结果”是复数。潜台词就是结果是复合的。你要得到一个结果R,于是做了事A,事A会产生结果R、S、T……。这时,作为既成事实,无论你接受与否,你得到的将不仅仅是R,而是事A产生的所有的结果,里面会有好的,也会有坏的。这是很多人在做事儿的时候会忽视或无视掉的部分。

比如某B公司,为了营业额R,冲KPI,有意无意地放松对广告来源合规性的审查,结果是营业额达到了,但是另一个负面的,非预期的结果是:失去了大家的信任。

“结果导向”,是要尊重、正视、接受所有的结果。也更应该,在事前充分分析所做的事儿可能产生的重要的结果。 并做好相应的准备。

应该如何描述结果?

对结果的描述不同,就会产生不同的结果。

我只讲一个故事。19世纪欧洲考古热,一群土豪去五大洲找当地土著买化石。土著很高兴,常常把一块化石敲成好几块分别卖出手,比一整块卖的收益高多了。

然后考古学家们都多了一件事儿要处理,3D拼图。土著收入高了,考古学家也有更多的活儿了,还能创造更多就业机会。这简直是多赢啊。除了对那块化石不太好以外。

当我们在说“效率”的时候,我们其实在说什么?

今天去听了一天的“工程效率”专场交流会。这次交流会邀请了Facebook, Amazon,Pintrest及上海几个知名大厂的工效团队负责人坐台。给大家分享了一下他们经历,方案及对于“工程效率”的见解。

整场交流会还是蛮成功的,尽管台下的听众只有几十人且一点儿都不活跃。参会嘉宾们讲的东西还是比较有诚意的。先从工程效率所解决的问题入手,从工具,理念,协同,流程,技术等方面的展开了分析与对话。该讲的基本都讲到了。有几个主要观点我是非常认同的(虽然并没有什么新观点,基本都是大家已经知道的东西)。

  1. 工程效率的本质,是解决复杂度问题,化繁为简,提高效率。
  2. 善用工具并且能把各个工具有机地串联起来,一提高工作效率的有效手段之一。任何需要被做两次以上的事儿,都值得自动化起来,避免低效的手工执行,但是又要避免过度自动。什么是过度自动呢?我的理解是判断都自动化就过度了。判断应该由人来做,判断好之后的处理,手工触发,自动执行,以免误伤。
  3. 工程效率要落地。可以以两个方面入手:
    1. 找到合作方,积极合作,共同推进。
    2. 找到真实的业务痛点(即使他们自己都不知道),并解决问题,提供价值。要以做产品,提供服务的心态来做工程效率。
  4. 工程效率不是一个技术问题。而是融合技术,人员与流程的综合性问题。我个人还想加上业务。因为业务不同,对效率的改进点的需要也是不一样的。
  5. 对于工程实践上的问题,没有银弹。不存在这样一个方案:每个公司拿去就能化腐朽为神奇创造奇迹。因为每个公司的成熟度是不同的,所适合的工程实践也会大相径庭。把一个公司跑得好好的方案照搬过来,跑不通还算好的,不好的是反而会产生严重的负面影响。每一个方案,必须是因地制宜地、因人而异的。
  6. 软件工程,与传统工程是非常不一样的。传统工程,做完就是完工了。而软件工程,做完只是开始,一个软件,从出生到消亡,始终都在发生变化。从外部的需求,到内部的技术方案,再到参与的人员,全部都是在持续变化的。
  7. 提高效率,要从最薄弱的环节入手,把瓶颈找到。有针对性地解决问题。
  8. 技术开放,以赋能扩展能力,而非以规范约束能力
  9. 每个公司间的文化不同,但是同一个公司,要上下一致,形成共识。这样才能劲儿往一处使。
  10. 工程效率的度量指标,不应该被纳入KPI或ORK,更不要以此为团队做排名,因为很容易产生误导。
  11. 不要写那么多文档,没人看。重要的处置方案,直接内化成系统功能。
  12. 系统不是设计出来的,是演化出来的。

另外想补充一个比较有意思的现象,因为本次与会的嘉宾比较多,会出现这样一种很奇妙的碰撞。阿里中间件的李云老师前脚说,团队是培养出来的,不是招聘出来的。后脚许式伟就在另一个话题上,表示严把招聘关是非常重要的,因为人是不可塑造的,“基本上大学毕业是什么样就是什么样了。”他们说得其实都对。但是话,都是有上下文的,脱离了上下文,单独去看,甚至会有些自相矛盾。

我下面想讲讲他们没有讲的。点也比较多,我争取讲得有条理点儿。

  1. 关于“工程效率的本质是降低复杂度”的论题,我有一点儿补充。假定工程效率本身的范畴包括:CICD,自动化测试,设计规约,代码审查,开发流程,发布流程,团队协作,工具打通并平台化,最佳工程实践的推广及开源。那么工程效率本身其实并没有降低复杂度。而只是把复杂度遮盖起来,让人们看不到。而上面这此东西的引入,其实反而增加了实际的复杂度(尽管不可见)。在平时的软件开发工作中,真正需要被降低复杂度的部分,是人为的额外的复杂度。比如一个用四则运算可以解决的问题,用了微积分来描述与求解。其实是人为地增加了复杂度。而在真实的项目中,这部分的复杂度,其实是远超工程效率所涉及的部分的。比如服务间的不必要的耦合,接口设计不必要地暴露了内部实现并强绑定,都会带来不必要的复杂度。而且,这种复杂度,影响范围更大,不仅仅会影响开发效率,还会影响服务的稳定性,可扩展性等。
  2. 老板们讲“工程效率”,本质上是指:“从公司整体,最终业务的层面,用更少的资源(一切成本,如:人,时间),办更多的事儿。”。个体的效能高,不代表整体产出高。但是个体效能低,整体一般也高不到哪儿去。所以工程效率,一方面是提高单兵作战能力,但是更更重要的,是团队协同作战的能力及规划调度的能力。
  3. 提高做事效率是一方面。但是在此之前,更重要的是明确,我们正在做的这个“事”本身。是不是必要的,有价值的。不然效率再高,也是无用功,白白浪费宝贵的时间。具体指什么呢?从最简单的,个人及团队层面上,要保证每个人不重复造轮子,起码做到一个公司内部,不要有两个人在做重复的事情。当然,B计划除外。从产品与技术的协同的角度,产品前期做好必要的充分调研,避免不必要的反复或返工。总结下来就是,专门的人或团队,用正确的方式,充分利用现有资源,做一次,做到位,推广开。

我在会上还问了一个比较尖锐的问题,经济学上有一个原理,就是劳动分工是生产力进步的原因,那么现在DevOps所倡导的,开发即运维,同一个组织或个人负责服务的方方面面,是不是与这个原理冲突呢?

有位嘉宾解释得比较形像,DevOps就像是工厂里的流水线。这个比较还是很贴切的。

我自己当然其实思考这个问题很久了,并不是在会上突发奇想想到的,所以自己其实是有自己的答案的。

在我看来,DevOps不是一个纯粹的方法论,而是一套体系,有方法论,有工具,有相应的人员素质模型要求。DevOps并不是真的要求开发人员去按传统的运维人员的样子去实施运维。DevOps是构建在现代的虚拟化的自动化的运维体系与工具链之上,在让运维本身接近透明的情况下,消解了开发、运维的协作壁垒,让开发能专注开发而且对于服务有更高的控制能力,从而提高了整体工作效率。这恰恰是分工的进化而非倒退。单就运维工作本身而言,运维已经比过去的搬机器、拉网线、登跳板,传文件,换硬盘的传统运维有了云泥之别。已经失去了成为一个独立的职业的必要。有些公司,打着DevOps的旗号,又没有执行现代化运维的能力,仅仅是为了强迫开发同时做运维,以求省掉运维的开支。这种DevOps,才是那种反分工的伪DevOps。

IMG_20190525_085747

苏州再游感悟

大概10多年前,工作没多久的时候,和老婆去过苏州,待了两天,去了北寺塔、也去了寒山寺。记得当时下着濛濛的细雨,举着把旧伞,跟了个团满苏州的景点儿逛,看着个什么都感觉新鲜得很,非要合个影才能安心离开。只是时间所限,当时连苏州标志性的拙政园、虎丘都没有去。但是离开时心里也并不感觉遗憾,因为这样的城市,早晚要再来的,而且毕竟离上海这么近。只是不曾想,这再来,便是10年之后了。

这次住的地方离拙政园比较近,吃过了午饭,沿着平江路,边逛边走十来分钟就到了。平江路在苏州也算得上是一景,沿途有各色文玩、作坊、秀场、小吃,有些看上去倒也别具一格,但我们怕错过了拙政园的参观时间,便一刻也未停留,匆匆赶到了拙政园。然而进了门,看着周遭的黑瓦白墙、水榭连廊,错落的古树怪石,脚下的青砖铺路,衬以各式卵石拼出的花鸟虫鱼,就有一种时空错乱的感觉,仿佛来到了上海豫园,只是进入了自己未曾涉足过的另一个区域。我没有找志愿者讲解,听听每个连廊,每座桥,每间堂,每棵树或许不一样的故事。因为在我看来,故事再动听也只是故事;而且听故事,也并不需要来到这里。来,便是为了亲身感受。遗憾的是,我人来了,却没有生出什么太多感受来。

回客房的路上,还是会穿过那条著名的平江路,只是返程更加从容。再次从那些让人眼前一亮的店铺门前走过。然而我的眼神依然没有亮起来。这些店一般都很小,一张大门上面挂着个牌子,就是它能展示给路人的全部。所以大多数的小店都是把墙及门都做成玻璃的,好让人们能看到更多有意思的东西,还会把最具代表性的产品挂出来,还可能专门派个伙计到门口引导。每家店的风格都很别致,看上去都有点儿意思。但这其实让我很恐慌,因为它们像是以一种最具活力的方式散发着一种死亡的气息:它做的一切都是为了做生意,为了活下去。这得是多么糟糕的环境,才能激发出如此挣扎的求生欲呢?看着那一扇扇大门,仿佛看到一张张血盆大口,而我就是一只迷途的羔羊,要选择从哪只口中穿过。于是我再一次地,匆匆走过,像是逃跑一样。一路上只是看看江上的扁舟,听听摇桨人唱着的民谣。

类似的感觉,不啻于平江路。

一路上,我也回忆过之前来苏州的感觉。思考着为什么找不到那样的感觉。是因为苏州变了?还是我老了?看着我的小女儿,哪怕是捡到一段小树枝,也能开心地玩起来。我想,应该是我老了吧。但是好像又不是,因为人老了,并不应该乐趣变少呀,只是应该会更高级一些。小屁孩吃个糖就开心半天,而我已经不会了。而且更糟糕的事,开心的事儿好像越来越少了呢。

真是有些遗憾呢。

佛系程序员 第五品 如理实见分

这一品我考虑了很久,始终没有开始写。因为这一品虽然很短,但是可以说是整本经文最深奥、难以阐释的部分。我自己都没有完全理解,又何德何能去为人解说呢?但是这一品又不能不讲,最重要的东西不去讲,就失去了写这个系列的意义。这一品,在我看来,是在讲三观。然而这年头,一说三观就特别敏感,我忘了之前在哪里听到过这样的一个人生经验,说:做人、做事,不要输出自己的三观。我想我是基本赞同的,虽然并不严格执行。再盗用另一个更接地气的说法,一个人的思想就像内裤,你穿没穿,穿的啥样的,你自己知道就行了,不用逢人就脱了裤子给人看。我这里主要是想分析一下佛祖的内裤,但是不免会夹杂一些私货。诸位看官自行分辨吧。

我们先来看看本品的经文:

金刚经 第五品 如理实见分

“须菩提!于意云何?可以身相见如来不?”“不也,世尊!不可以身相得见如来。何以故?如来所说身相,即非身相。”佛告须菩提:“凡所有相,皆是虚妄。若见诸相非相,即见如来。”

佛祖最后告诉须菩提的话,大概是《金刚经》最出名的几句话之一了,因为这句话的确涵盖了诸多法门。我对这句话也有很多个方面的理解,个人感觉最重要的一个方面是,这是讲看待一切事物的方法论。“一切事物”有点空,具体点讲,我认为包括从写代码到与人交往等所有事情。在我展开解释之前,我希望各位看官能先自己想一想,你自己是如何理解这句话的。

先说“凡所有相,皆是虚妄”。相,我的理解,是泛指一切具体的或有形态的或是可以名状的东西。为什么说他们都是虚妄的呢?因为那只是表现形式、手法。并不表示真实的内涵。真实的内涵,一般都是抽象的。比如,我问,你能不能简单说说你对面向对象编程的理解。一般人听到这个问题可能会组织一下语言,概括一下。而我见过的一个牛人是这么回答的,抱歉我对面向对象编程的理解没办法简单说说。

他说得是对的。如果真的对面向对象编程理解到了一定程度,是没办法三言两语说清楚的。一个复杂的问题,一定是需要一个同等复杂的语言才能描述清楚,也需要一个同等复杂的理论才能解释和解答。所以,如果有人说,面向对象的主要特性,就是继承、封装、多态。但是又没办法从这三个词引申、延展出多少相关干货出来,那他一定就是个水货。

而且,你如果把三个对面向对象很懂的人叫一起,聊聊面向对象,一定会发现他们的理解是不一样的。甚至有些点会有冲突。最可能的是,他们三个人,没有一个人说的是完全正确的。而且,别说仨,即使你把所有的面向对象专家都叫来搞个轰趴,你也没办法聊出一个绝对正确的东西出来。

找不到绝对真理,这一点儿问题都没有,因为我们解决大多数问题,甚至可以说所有具体的问题,都并不需要先找到一个绝对真理才能解决。

上面这些分析的另一层意思是:无论谁说的什么话,都不会是绝对到位的。甚至连本意都不是。因为一个人说的话,总会是他心中所想的很小的一部分。他为了说给你听,可能只是取了他觉得最重要的一部分讲给你听而已,并不会完全、完整地表达自己的观点。然后你听的时候,漏一部分、误会一部分、再脑补一部分。你的理解,和对方心中真实所想,就差十万八千里了。哪怕说的人毫无保留、听人的虚心接收,这种情况也在所难免。

上面的,都是“相”,所以说“凡所有相,皆是虚妄”。只是佛祖的意思比上面说的这些要更广大得多。所以出家之人都是六根清净、六亲不识的。

我再举一个例子,上面我说,复杂的东西就需要复杂的东西来描述。你听完上面的解释后,现在又是如何理解的呢?沃尔夫勒姆,在2002年出版的《A New Kind of Science》中提出计算等价性理论,认为:

自然界中各种过程实现的计算在复杂程序上都几乎等价。

自然界中的过程有简单,有复杂的。如果他们都是等价的,有没有办法用简单的方式描述、处理复杂的问题呢?

你可以试着回答一下这个问题。一点儿提示是:你随手在一把尺子上划一下,这个划痕所示的刻度,是一个无理数,而任何一个无理数,因其无限性和随机性,都可以被认为包含着人类发展到现在的所有知识的总和。那么你能说,你随手一划,就复制了人类所有的知识吗?

上面是说“相”。下面聊聊“身相”和“见如来”。

前段时间,一个老同学看了我前几篇之后来问了我一个问题。大体是问,佛教所宣扬的教义就是让人超脱轮回,为什么藏传佛教还搞什么转世灵童。我说这个问题有点儿大,我得写个文章才能解释清。其实我四年前在知乎上也问过一个类似的问题:“既然“诸相非相”,那为什么佛院里还要立佛像?”。本质上都是想问佛祖有没有点儿逻辑,自不自洽。怎么感觉说一套做一套呢?

这个问题说起来简单,但是其实很不简单。

简单的回答是:佛教不同于佛法。佛教团队其实是很世俗化的民间或官方组织。再多的我就不讲了。

稍微复杂一点儿地正面回答这个问题:佛法中的跳出轮回,并不是跳出生死的意思。死还是要死的。但是“阿赖耶识”会延续下来。这个名字,是不是有点儿眼熟?对的,就是圣斗士星矢里沙加领悟的第八感。

再复杂点儿的解释,会牵扯到身相的“圣义谛”和“世俗谛”的区别,就太佛学了,我自己水平所限,还没办法解释到这一层。

程序员的价值和末日

最近和一些人聊到现在的程序员这个职业(是啊,程序员和程序员在一起还能聊些什么呢),更加加深我几年来对工程类程序员(泛指一切技术岗位的员工)这个职业的一点儿感受。主要包括这么几个观点:

  1. 程序员越来越不值钱。这是大势。
  2. 程序员的价值,归根结底在于省钱。
  3. 企业用人要求越来越高,学校教育脱节与之越来越严重。
  4. 技术演进速度迅猛。思维理念、知识体系,五年间就能变得陈旧。

这几点看上去没啥直接关系,其实彼此互有关联。我来解释一下。

程序员的Good Old Time

我记得高中的时候,有一次心血来潮,把爷爷年青时评选高级经济师的论文打成Word文档。我记得也就不到一万字,我花了一个小时才打完,都不好意思让人看见。然而我爷爷一直在旁边转悠,看我打完了居然还夸我打得快,说他当年,他也要打出来,但是不会电脑,专门找了打字员,打了半天才打完,打完还请人吃饭。我听得一脸蒙逼。心想怪不得人们都怀念Good Old Time。妈得原来那个年代,会打个字都能混得风声水起的。

然后呢?当我满怀希望地学了计算机,从校门出来的时候,当时公司老大们训话的话风就变成了:“你们不要天天NB哄哄的,把现在你们全开了,我就算只招六指的程序员都能招满。”这位老大这么有底气,是因为那个年代,程序员就已经满大街都是了。而打字员这个职业已经没有了。

当时,离“会打字就能吃香的喝辣的”的那个年代,也就20多年吧。

当然那位老大毕竟还是说笑的,当年学计算机的,的确也还是很吃香的,我刚毕业那会儿,大公司招在校生都是飞来飞去,公司靠谱点儿的,给实习生都是租个别墅住(当然不是一人一栋)。实习工资都够别的专业的正式工资。

现在又10多年过去了,就算BAT有这么干的吗?没有的。为啥?因为程序员越来越不值钱。虽然相比其它行业还是高不少,但是相比过去,已经差太远了。而那位老大的笑谈,恐怕也快成事实了。

那么程序员为什么越来越不值钱了呢?我先来讨论一下程序员为什么值钱。

程序员的价值

商品的价值,决定于创造这个商品的社会平均劳动生产率。

商品的价格,还会受市场供需关系的影响。

这些话可能有人还记得,我没记错的话,应该是初中思想政治课上就讲到的。我当年觉得政治、经济是最没用的学科,现在反而感觉,这两是九年义务教育里,在成年后的生活中,最能用上的两个学科。

程序员不是商品(好吧,也许是),那程序员的价值在哪儿呢?程序(软件)吗?不,不是软件,你买个Office,装在电脑里,从来不去用它,它产生价值了吗?并没有。你下载个理财App,从来不买理财产品,这个App产生价值了吗?也没有。

为什么用Office就有价值呢?为什么从理财App上买理财产品就有价值了呢?我不用Office可以写在本子上啊,我不用理财App,可以去银行办理啊。

你想想,哪个效率高?哪个成本高?

所以程序员的价值在于:程序员创造出来的东西,能用极低的成本,提高所有(买了这个软件的)人的效率和产出。简言之,程序员是史上最强大魔法系奶妈的角色。

当然这里的程序员是指群体,毕竟不是所有程序员都做具体软件的,但是从宏观角度看,软件行业做的事儿,就是以极低的成本,颠覆其它各个行业的劳动生产率。

所以程序员的平均工资高,因为软件行业创造的价值的确很大。尤其是在节省原有的人力、物力上。所以说,程序员的价值,其实是省钱。

程序员的贬值

然后回到原来问题上,“为什么说,程序员越来越不价值了呢?”。因为软件业,和其它行业最大的不同在于,软件的发展是累积的,不需要每次从头开始做,而且成长速度没有物理量约束。而且,代码是无国界的。

从小的说,基本所有编程语言的库都自带的排序算法,现在的程序员,除了在学校和在某些面试官面前,根本不会去写什么排序算法。

往大里说,现在有Spring Cloud,有Dubbo,有Istio。你说你也会写服务治理框架,这很好,但是不用写了,你只要会用就好。写了也没有真正的价值。因为这个问题已经被大体解决了。在软件行业,除非有技术壁垒或专利保护,一个问题只需要被解决一次。第二次做的价值基本为0。当然,价格不会为0,因为总会有公司愿意为这第二次到第N次的实现掏钱的。

所以你会自己从头写一个服务治理框架,很好,也能拿到高工资,但是没有价值。这只是有价格而已。除非你做得比前人的都好,会贡献出Delta部分的价值。

那么现在程序的价值在哪?是你能把一个东西(无论是自己写的,还是现成的)在一个公司用起来,为公司解决他们业务上的独特的问题。才是有价值的。这时你会发现,用现成的东西的成本会更低,于是利润空间会更大。

随着软件行业的日益成熟,能创造的新的价值空间会越来越小。而程序员的价格(即工资)从长期来看,总是要回归其价值的。所以很不幸的,最终价格,按我的逻辑,会是0。只是可能要个几百年吧。

程序员的脱节

做程序做久了,会发现程序员做的事情一直在发生天翻地覆的变化,变化快到很多程序员根本跟不上这个节奏。于是公司招人也面临一个尴尬的囧境:会写排序算法的,会Copy Paste的,会写CRUD页面的教科书式程序员汗牛充栋。但是想招一个能创造性地用代码高效地解决实际问题的人就凤毛麟角。而且更糟糕的是,CRUD程序员多得已经营造出了种程序员就是CRUD的不良氛围。这和现在国内互联网行业如火如荼,大都处于跑马圈地的阶段不无关系。

但是当潮水退去了呢?

程序员的末日,就要来了。