speaker 1: 朋友们好,这里是原子人。 今天聊一聊让不少程序员产生焦虑感的一个话题,那就是软件开发过程中的一些困难。 其实很多程序员在工作中总是想的太多,给自己上不必要的强度,把问题有复杂化。 实际上呢这个工作就是没那么难的。 因为随着技术理念的发展和硬件条件的升级,软件开发这件事情本身应该是越来越容易的。 在上世纪60年代的时候,造一个操作系统,你要一千多个程序员花上三四年的时间,他们的产品经理甚至都可以用这个项目的经验出一本书。 而到了90年代的时候,一个芬兰大学生就可以一边读博一边摸鱼,写出来一个完整的操作系统。 那接下来我说说几个客观上不需要存在,那就是主观上很多人就会给自己加上的问题。 第一点就是过度开发。 很多程序员喜欢在开发的时候,自己想象出来一些要解决的问题,然后花很多时间的精力把它造出来。 可能是显得想要显得自己经验牢叨,未雨绸缪。 但实际上这些问题本身是不存在的啊,我这里讲个故事,曾经呢有这么一个产品,就是它的功能是可以全世界通用,但是它主要的市场目标是中国,所以没有考虑过出海的问题。 但是我的朋友呢作为这个产品的主设计者,他就脑洞大开,一上来就设计了international alization,也就是I18N国际化框架。 把所有前端要显示的文字都提取到了词典,然后就为不同的语言准备不同的词典,这样就可以在浏览器就实时进行不同语言中的切换。 而且为了测试这个语言切换的效果,我的朋友还做了一整套完整的英语词典,每一个词都一一对应。 而且因为有一些词它没有对应的英文单词,它还独串了一些名词,然后就整就等着哪天还可以接入德语、法语、西班牙语、葡萄牙语、日语、韩语了,就听起来好像是没多少活,对吧? 那你就跟我朋友一样,就远远低估了这种东西的工作量。 因为除了每一次改动,ui上面的文字你都要同步更新所有语言的词典之外,你还要考虑到前端代码部署的时候,词典的版本的对应关系。 因为有的时候你代码改了词典没改,有时候词典改了代码没改。 而且取决于你的这个版本部署的策略,浏览器的缓存和cdn上面的缓存都会受到不同不同程度的影响。 而且最后的话你还要考虑到这些词典文件下载是和你的前端下载是分开的话,延迟所导致的一些画面抖动的一些问题啊,所以就是为解决这些问题,我的朋友在这些事这些事情上面投入的工时远远超过了任何人可以想象的程度。 而问题是这套东西现在都没有发挥任何的作用,因为这整个产品现在都还在中国市场,并没有任何需要英语的是或者其他语言的人来用它。 所以他白白浪费了这些人生,我觉得他唯一的价值就是给大家留一个警醒了。 这个故事就是源源自于前端的开发,在后端数据端、运维端、架构端也很很多地方都容易出现过度开发。 就比如说大数据吧,数据端我还记得大学的时候,在大数据这门课上面,我们教授请了一个超算中心的人来分享经验。 那位大哥就拿起他的手机说,你们的数据如果连这一台手机都装不满,那你就别好意思说自己的什么鬼大数据,也别去想什么分布式处理那种东西啊,都是高射炮打蚊子。 结果我毕业之后第一项工作就是数据处理啊,说是处理其实只是简单的做一些周期性的统计。 比如每每小时、每日、每周的一些简单的统计。 但是呢当时的项目负责人二话不说就动用了哈,就是首先他就要在开发环境里面部署哈的全家桶,这样才能够在本地做测试。 然后呢在生产环境里面还要走各种流程去接入运维部门主管的那个超大型的合作集群。 但实际上我们真的上线之后,这个产品每小时要处理的数据量只有1000万哈,就是总共加起来也不到10个G完全可以全部都读取到内存里面,然后直接在内存里面进行统计。 不需要通过整一个网络的跨路去调用和度,不需要做任何大费周折的事情。 这至少能够省几个月的工时,就是除了省色之外,这个做法而且还特别省时。 因为硬件的反应速度的相差非常大。 你把数据传到内存和把数据和命令传通过网络传到和度集群,这个是有好几个量级的区别的啊,只可惜当年的我没有看到过这条视频,要不然我就早早就站出来反对这种分布式的处理方案了。 还能够顺便拯救同事们好几个月的宝贵人生。 第二点就是没有规矩不成方圆。 在我十几年的职业生涯里面,在code review里面看到看见过了一些奇葩的吵架话题,真的是包罗万象,无奇不有。 从最经典的什么大括号放在哪儿,tap有几格,到一个函数和参数的命名的规律规则。 我曾经见到过有一个新函数放在哪个文件这么一个问题上面。 有两个人就是在review的评论区里面来回讨论了十几条很长很长的评论,各种引进句点,我真的非常无语。 因为他们周报都没有写过那么长的。 其实就是这一类的代码规范的问题啊,其实只要在项目开始之前,团团队里面有一个统一的指定的规则啊,这种规则其实都不需要去人工的去执行,只要把它整合到C D的流程里面。 就比如说代码的规范,嗯,通过formatting的工具在代码commit之前format一下,在merge之前format一下,在build之前format一下,就能够做到所有人在所有地方都统一了,就没有任何冲突可以发生了。 还有一个更经典更常见的就是在构建H T B的A P I的时候,怎么把这个语法给做出来。 其实有很成熟的规范了。 你要么是遵守refor api的那种标准,要么就是你们内部有一个啊比较基础的一个标准。 然后大家只要像一个专业人士那样按规则来执行就好了。 但偏偏很多人就自作聪明,就搞出一些屎都不如东西。 这不仅api这个东西它的重要性是它不仅仅是为了你们自己的开发而用的。 Api是一种对外交流的工具,你的这些东西做的乱,你会让所有跟你有合作关系的人的工作难度都提升一个量级。 如果有接触过微信的生态圈或者微信小程序的开发人,应该对这个非常深有同感。 微信作为软件工程史上数一数二的反面教材,你说他的api是屎,那就是对屎的侮辱啊,他的这些反面的案例可以不是不不只是出一个视频呢,可以出一个系列的视频这里所以就不花时间去说了。 其实就是这一类就没有对错的东西呢,就特别容易制造混乱。 就虽然程序员大部分时间都很理性的,但是呢你给了他这种发挥的空间,就很多人就是心痒痒的。 然后想要秀一下操作,我这里加上一些我的风味的东西,你不给他留任何的余地的话,他们就很老实了,其实反而是对大家都好。 第三点呢是对第二点的补充,那就是一些反人类的规范就不要执行了。 这一点专门用来批判clean code和类似的这种写作要求。 我个人觉得近些年这些反clean code运动的启视,很大程度上是因为越来越多人意识到代码只是一个工具,它不是一种抽象艺术。 就我本人其实不太关心clean co的一些具体的规则,比如说什么一个函数不能够超过多少行,或者是一个函数不能做超过一件事之类的这些。 很多人就喜欢在审美的层面去争吵这些话题,但是我觉得他们都搞错了。 这个问题真正的关键所在那就是代码。 它真正的目的是什么? 就是在最早期的这些abc d这种高级语言,高级的编程语言的发明之前,assembly就是人们编写软件的唯一工具。 所以人们之所以发明了C这种高级编程语言来取代assembly,而且很快的成为软件开发的主流。 那是因为大家都发现了用接近人类语言的形式来写出来代码,它更容易写,更容易看,而且更容易管理。 因为软件开发它是一种工程,它是一群人高墙入虎洞的一种事情。 高级编程语言的出发呃的出现,让这些软件的发展得到了像是工业革命级别的飞跃。 而在软件设计的层面呢,就古人也很早的在研发的过程中就总结出来了unix哲学思想,就是作为软件设计层面的圣经。 Uni哲学就是处处都提醒了大家要接地气,不要花里胡哨。 就比如说uni哲学提到纯文本就是最好的api接口,如果你的软件用纯文本作为输入和输出,就不仅能够保证它100年之后它还能够被兼容,而且还保证100年之后的人也能看得懂。 所以你可以看到的是,就在软件设计和开发这些理念的发展的过程中,一直都有一个很明确的一个方向。 那就是让他更容易写、更容易看、更容易用、更容易合作。 这些都是围绕着程序员本身的以人为本的一个做法。 所以当你定下来一些规则,是源于一些虚无缥缈的所谓的美观的理由,而不是为了让人的工作变得更容易。 那这个规则本身就是一个错误的这整个方向都是一个错误的方向,所以都不需要去深究它的具体内容到底是好还是不好。 而且我感觉就是很多追捧clean的人,一要么是刚毕业,然后就是读书的时候就被推荐了看clean就觉得说哇这些概念好高大上,好优雅,然后被忽悠到了。 第二类就是基本不参与一线的开发。 就是那些管理层的人,他只是从别人那里听到说clean co这些东西,纸面上的好处啊,让这些代码变得多么的干净漂亮,然后他就全盘的接受了牙,接着就要求下面的程序开发都要去遵守这些规则。 嗯,这些人呢真的他们的问题还真的不只只是口,这些人还间接性的养活了school master这一类就狗都闲的职业啊,那那就是另外一个话题了。 第四点,技术占不是越大越好,而是越小越好。 我发现不少程序员就特别喜欢在项目里面堆料。 就是他们有一种错觉就是堆的越多就显得自己越有知识,然后越能得到赏识。 但实际呢在现实生活中,绝大部分情况下,上级都不会因为你用了一个什么新的技术,或者是用了多少多少个技术而夸奖你。 因为他们只关心的是产品层面的,你能不能够教出来他们向客户承诺的那些功能和作用。 技术层面的东西呢大部分都只是程序员之间的自娱自乐啊,他对你最大的就是工作上的价值,可能就是在简历上面能够多写几个词。 而且有一点更重要的是,技术章其实跟技术债是成正比的。 你的堆叠的技术单越多,你借的债就越多,你欠的东西以后都是要还的。 当然我个人也不是说非非常的反对引进新技术,尤其是如果一项新技术能够同时取代多项的老技术的话,它就是特别有价值的。 我第一次将容器架构中的佼佼者ku引进到项目的时候,就可以直接在deops层面就划掉了好几个老的技术,整一个C D的过程和整一个呃部署了之后,运维层面的一些工作都大大的被简化了。 所以从整体上来说,这个项目的整一个的技术章是缩小了的,人力成本是减少了的,维护难度是降低了的,工作效率是提升了的,真的是一个皆大欢喜的一个结局。 而且呢还有一点就是成熟的技术很多都可以应用在很多的场场景里面,解决多类型的问题。 就比如说postgre它是一个传统的关系型数据库,但是它同时也有很强大的处理其他类型的数据的功能。 当你能够熟练的应用postgre的时候,你就不需要有单独的no西口的数据库去处理这些Jason这种就不规则的数据,你也不需要new for J这种东西来处理呃图形的数据。 你甚至可能都不需要read来处理一些key value的数据。 你一个post能解决多类型的数据的时候,你的技术占立马就可以减少75%了。 第五点,别造轮子了。 很多很多造轮子的人就是都没有对这件事情的难度有足够的心理准备。 因为很多人他们一开始的时候就是单纯的觉得说为了手头上这个项目的需求啊,我造了一个轮子。 但是呢我把它给稍微打扮,打扮了以后的项目还可以继续用啊,这不是很省事吗? 但是他们没有意识到是一个需要长期维护的一个通用型的工具。 你是要不断的为以后的新的需求进行改动的,同时你还要维护以前的功能的兼容性。 那其实这个工具本身的已经变成了一个具有完整的生命周期的一个产品了。 而随着这个产品的应用场景越来越多,你需要更改的需求越来越多,更改的难度就越来越大,做bug的机会就越来越多。 啊,所有千千万万个用这个轮子的软件和程序员都会一起承担它所带来的风险。 但实际上的话就不会有千千万万的受害者,为啥呢? 因为大部分的轮子在取得大规模应用之前,都已经被开发组弃坑了。 说好听点就是知难而退,说难听点就是汽车撞墙了,你知道拐了。 曾经呢有一个国内的一个咨询公司做过这方面的调研,他们就是去到各种大厂去问这些程序员。 结果总结出来呢,大家造轮子的主要原因排在前两名的。 一就是别人的轮子不好用啊,就缺那么一点点他需要的功能。 然后就是二就是在企业层面用别人的轮子,这个沟通成本太高了,扯皮扯的太花时间了,还不如自己造。 其实这里话就体现出一个很有意思的地方,就是我发现中国和美国的大厂在造轮子这件事情上,真的是完美匹配的两国的文化特征,就中国的大厂呢就喜欢造完之后就缠着自己用,甚至呢连自己隔壁的部门都不给。 而美国大厂呢喜欢造完之后第一时间就开源,然后到处宣讲,到处推荐给别人用,邀请别人来开发,就所以就很好,很有意思。 所以你看看中国人的想法,就有点就很中国大厂的那些人的想法,就有点很天国上朝的感觉啊。 我搞我的我不稀罕你的啊,我也不稀罕给你看我的东西。 美国人的话就是他搞出来搞出来什么东西,第一时间就到处传播啊输出,扩大他的影响力。 然后呢通过这个先发的优势,把其他还没有成熟的对手直接干放在襁褓里,而且还把人家的那些人才的资源拉过来啊,为自己的这个东西的提升出工出力。 那不有是不是有点像好莱坞那种招数,嗯,就是人家老美就是手指一套。 我到现在真正用到过的,能够输出到国际上的,就是来自于咱们国家的这些软件技术。 比较现代的技术,我印象中就只有呃百度的1X和阿里的design,恰好两个都是前端的工具。 然后我个人见识少,如果还有什么别的在在别的领域有国际知名度的那些技术框架是我们中国人做的那请各位在弹幕评论里说说,让我长长见识啊。 View这种不算啊,他只是一个华人。 Ok扯远了。 第六点,最后一点就是最好的解决方案。 一般情况下反而是很朴素简单的那个就比如说有一些产品他在运营的过程中数据越来越多了,嗯,数据库要装不下的话,你这种时候程序员就要考虑怎么扩容了,对吧? 比如整一个分布式的架构啊啊一个数据库集群啊这种东西。 呃,分布式和集群这些概念就用在前端或者后端那种服务上面其实还好。 但是一旦跟数据数据库这种具有A D特性的东西扯上关系的话,那个复杂度真的直接上升到图灵奖的级别。 那其实真正的解决这种数据装不下的问题的最好的解决方案是什么? 你猜猜其实就是直接的拆分逻辑上,如果没有很大瓜钩的数据的话,那你们就把它分开放,就不要放在一个数据库。 那如果你这个是企业级的软件的话,就很就一般情况下你不同的客户之间的数据也是没有任何瓜葛的那你就一个客户一个数据库啊,又或者是如果有一个你的数据库里面有一个表,它就特别大。 你你把它直接拿出来,把这个表单独放一个数据库,是不是听起来很笨,就有点有点蠢蠢的。 实际上这个方法非常实用,因为你做你把数据拆分,你唯一承担的一个额外的一个负担就是在你要在应用层面多写一些代码。 就是来判断你要获取的数据来自于哪一个数据库,就是你的对接的这个接口和你这个数据库的地址有点区别而已。 但是你想想,就是这么几行的应用层面的代码,你已经解决了一个图灵奖级别的难题,这样看是不是就很划算? 这别以为我这个是在瞎扯,这小红书的老鼻祖就是美国的Pinterest,就是当年就是靠这一招,就是应付了千万级别的越火。 当然他们一开始的时候用的也是集群的,而且还不只是一种数据库的集群。 首先他们有14个节点的m口集群,15个节点的coach base集群,十个节点的ready集群,八个节点的main cash ache集群,四个节点的cassand集群、四个节点的ersearch集群,三个节点的蒙古db集群。 而且那个时候他们总共就只有三个程序员,你能想象一下这三个人平时在办公室是什么状态吗? 啊,幸好了是他们看到我这个视频啊,然后在一键三连之后呢,他们回去就把这个技术章从七个数据库减到了三个。 然后呢,把整个集群架构全部抛弃掉,采用了最简单朴素的一个拆分的方法,呃,东西多了就拆开来放东西多了就拆开来放,然后表比较大的表就单独放到一个数据库。 一直到他们月活已经到了2000万的时候,他们的数据主的数据库麦已经拆成了88个了,依然能够支撑他们的所有的业务。 我自己其实也有不少类似的经历。 其实最经典的一个就是我当年就是靠着一个excel表来做前端界面,把一个我们子公司的一个cms给整个给替代掉了,而且还获得他们的广泛好评。 他们没有因为这个excel很简陋而有什么怨言。 而反而他们觉得说excel比他们原来那些用Java web写的那个操作界面好用100倍。 因为对他们来说,解决问题才是更重要的。 不过限于时间关系的话,这个就是以后再说了。 以上说的这些全部的这些观点啊,其实都呼应了同一个主题。 我觉得是可以拿来做最后的总结了,那就是四个字,大道至简。