聊聊2017年做得三件技术上的改进

2017年也如同其他年份那样,渐渐远去。技术上的工作内容总还是重覆的多,但还是做了些改进。这些想法其实在我脑中很久,总是因为各种原因和阻力得不到实现。2017算是对自己有个交待了。

 

二方库开发

可能“第三方库”大家听得多,二方库是说在同一个组织里开发的,用于其他产品的代码库。说白了,就是共同代码提取。

把这事做成阻力远比当初想的大。这不是一个技术问题,或者说技术上不是大问题,更多的是一个软件组织分发、资源分配、挑战现状的问题。在组内大量讨论,和各老板做说明演示后,终于,老板们同意了!至少在我负责的产品里,做现有共同代码的提取,并用独立的项目发布周期维护。

大家给这个项目起了个名字叫“Kona”,是一个Hawaii的岛,那也产咖啡。😀

桌面端开发引入Web技术

其实这是我很久以来的想法,几年前就做了些实验,积累了些经验。结合Web容器,就可以利用大量现有的Web框架和技术,使前端体验大大提升,也可以提高开始的效率。在我”强烈”的推动下,终于把AngularJS+Bootstrap塞到了JavaFX的WebViewer里,收获了些好评。虽只能算是向前迈了一小步,但希望之后的步子能大些。现在组里的同事学习Web技术的热情高涨。

引入Kotlin

感谢Google在2017 I/O大会上把Kotlin提升为未来要支持的一级语言。我在关注Kotlin多年后,终于到了最后一个重要的理由把它引入到开发中。虽然只是先用来做Unit Testing,但之后,我相信使用的地方会更多。它的很多特性绝对是大大的提高“生产力”,同时产出更多安全的代码。

之后。。。

可能这些东西,把别的公司看来都不算什么,技术上并没有什么高深的玩意。但对于我个人,看着这些多年来的想法得以实现,感觉还是很好的。现在很多旧项目占去了大量的时间和精力,要挤出时间想想之后的事情了。希望能有好运气吧!Finger crossed!🖖

当需求来了,开发人员能做什么?

最近面临的一个遗留问题所引发的惨案。

此问题大概是说某功能在前几个版本中做的太麻烦,性能瓶颈非常难跨越,向后兼容也很成问题。最让我们这些开发觉得不可思议的是,几乎没有客户在使用此功能。怎一个惨字可以形容!讨论会上有种声音说,“开发人员当时在实现时,就应该察觉开发繁杂,而得出这个功能有问题的结论”。“是吗?”我问自己,然后陷入沉思——当需求来了,开发人员能做什么?

我仔细回想了当初在开发这个功能时的各种会议、讨论,试图去发现开发人员能制止这场惨案的机会。讨论中,产品工程师在PPT里展示着精心设计的流程,那几乎就是考虑到了客户的心窝里,我们开发人员抱着敬畏之心,无不啧舌。然后各组老大在原来的需求上加入新的要求,要支持更多功能,”要让我们的客户感觉更加灵活“。开发人员警惕起来,”这个功能好像很复杂,实现起来好像很复杂,真的要在这个Release里实现吗?”。声音太微弱,无人理会,于是新的功能加入了原来的规范文档。

开发人员开始实现了,组织技术攻坚,各种探针实验,画UML图,讨论类的职责、关系。为了实现“客户”的需求,体现团队的实力,若干星期后,功能实现了,但也意识到了问题,如果数据量特别大(millions of records),会有性能瓶颈,加载会很慢,1G的内存也不够用。可测试过程,没有数据量特别大的case,偶尔出现的问题也有一些workaround可以解决。开发人员以为不是大问题,心放下了,产品也顺利发布!

之后发生的事如开头所述,客户的数据量都非常大,常常有几百万条数据。产品太慢了,之前的实现方案,完全不能应对!同时也发现客户几乎不用这些功能,用的也只是自家的产品工程师。

反思一下,需求来了,我们工程师能做什么?

  • 积极地和产品工程师讨论,基本错误,违反常识的问题要指出。当然,谁都应该指出。实现难度太大,要让老大知道,摆事实讲道理,实事求是。
  • 高级的需求描述,如操作流程,我们的意见往往无足轻重。产品工程师更了解客户,开发人员总不能因为难而不做吧?难免有捏轻怕重之嫌。此事之后,我想,也许应该多唱唱反调,让产品工程师多些思考。当然,也许谁都应该唱唱反调。
  • 规范文档要更细致,包括常见的用例、性能指标;开发人员也要意识到实现的瓶颈。此例,如果这些能明确,也许问题早就发现了。

一切软件产品的根本是需求,最大的浪费是东西做出来没人用。夜有所悟,总结之!

聊聊代码的质量

程序员、工程师用不同的编程语言写出源代码,去实现项目的需求、功能,为客户带来价值。极少客户会直接看到源代码,但源代码却是程序员的重要产出,可以视为产品的一部分。代码的质量自然会影响最终产品的质量。好的代码是好产品的基础,将来产品维护、更新升级都从中获益;差代码则绝对是定时炸弹,即使短期没有发作,公司或组织在未来也很可能付出高昂的代价。

代码质量很容易被组织所忽略。第一,“老大”往往只关心功能是否实现,客户又不看代码;第二,代码质量提高很难立竿见影,“老大”看不到明显的产出(作用体现在将来,团队的能力也需要一定时间培养,如设计能力、组织架构能力等);第三,质量的量化有些困难,工具往往只能是辅助。因为这些原因,公司或组织只有在质量问题非常严重时,才会给予高度关注。可往往此时已为时已晚,代码已然“臭不可闻”,维护成本高企,团队苦不堪言。如果这时产品还有维护价值,组织自然会拨出更多人力物力,原来一个人的代码,可以5个人一起改。如果没价值,那就推倒重来。表面看很爽,可烂代码对新写代码的贡献可能也不大,无奈之举背后实则是大量成本的损耗(以前的资源白花了)。

代码质量一定是开发团队的问题吗?我觉得不全是。开发团队成员的素质自然很重要,可如果老大一定要把2个月的活,压到一个月来完成,工程师是怎样一种状态,想想也知道,能把功能做完就好,还谈什么思考高可扩展的设计;如果需求老是改来改去,工程师早上写的测试用例,晚上就要废掉,那还有什么动力去写新的测试。总之,”老大“或管理层要知道有代码质量这回事,它也不是免费的,要给足重视。

代码质量的标准是可调整的,而且允许”补交作业”。对一个初创公司,当某项目一个月不完成,公司就死了,代码质量的优先级当然就很低。公司这时要让团队知道,相信工程师也会理解此时是所谓非常时期,手法自然也要”非常“。但如果之后,继续忽视代码质量,没有把前期的技术债务清掉,当一个个隐患被相继埋下。等未来再遇到”2个月的活需一个月赶完“的危机,可能就无论如何都完成不了的了。优秀的团队会未雨绸缪,在项目开始时就把合适的代码质量的要求写进项目规约中,如多少单元测试覆盖,多少新增Major静态分析问题,多少平均函数复杂度。项目经理也要时常的监督质量的看板。

以下结合平时工作,总结几条团队如何提高”代码质量“的要点,

统一的代码书写规范

有时挺形式,可团队要共同遵守的规矩很多,书写的规矩就是起点。要在以前,我绝想不到书写规范会统一。可我们团队经过很长时间的努力,现在人人可以遵守,旧代码也在不断改进中。有了规矩,就似某种共同的价值观,作用潜移默化,不单单只是代码规整了,好读了这些简单。

一个题外话,书写习惯真是可以改变的,我在前面的博客就说过,现在看到”4字节Tab“就觉得不舒服,相信很多人看到“2字节Tab”也很不爽吧。

架构与设计

众所周知,好的设计非常重要,未来的好扩展性、好维护性很多来自好的设计。架构设计源于对需求的理解,根据项目需要,选择合适的主架构。架构定了,代码的主布局(大的职责划分)就被箍住了。功能细节的设计也要重视,多开几次评审会议讨论UML图,仔细分析类的职责和类与类的联系,多想想使用时的场景,并引入合适的设计模式。

代码重构

多年的经验告诉我,随着需求的变迁,像自然规律一样,代码会慢慢变烂发臭。可以与之对抗就是重构(Refactory)。Refactory并不是要把代码“重回工厂”,而是时常运用各种技巧对代码进行自省和改进,不断将对产品功能新的理解注入到代码模型中。详见《重构》。重构有时是小步快走,如重写的名字,提个函数啥的,这种最安全;有时动结构时,要大踏步,这时要小心,依靠团队找出好的方案。这时你也会看到高覆盖度Unit Test Cases的强大支撑。没Unit Test,那你要更小心了。

团队培训

团队人员经验不同,素质也参差不齐,没什么好办法,要加强培训。

培训并不是说一定要去找外部机构,便宜的公开课很多是套话,和实际情况有距离;高级的订制课又太贵。还是应该多依靠团队自身,老员工帮新员工,新员工请教老员工,没有比这再自然的作法了。新员工得到了知识,老员工也会有更多的思考,两者都加强了。时间长了,大家的能力都会提高。

团队Lead则应鼓励大家的加强沟通,组织各种形式的交流分享会。

代码评审

现在我对Code Review的理解,学习和交流为主,找BUG和问题在次。一个简单的道理,你的代码每天被一个有20年经验的人看,那会是种什么感觉,你肯定期待着一些高级的反馈。就是经验相当的人相互Review代码也会有帮助,想想当你把很烂的代码让别人看,难道不觉得丢人吗?

代码评审费时吗?当然。如果团队中所有人都找那个最牛的人看代码,估计再牛的人也扛不住。那就分散开好了,有些关键的、拿不准的、有技术难点的改动找牛人看,其它的就分散开,反正时间找了,牛人的经验总会慢慢流到组里所有人,不要急于求成,把牛人累死在半道上。一次代码提交就找一个Partner帮你看看。

杜绝Copy/Paste

不再累述,详见绝不要拷贝代码

TDD

单元测试无数次的帮助我们找到代码中的BUG、没有改全的地方、糟糕的设计(设计的不好,往往不好写测试)等等。Unit Test绝对值得每个团队拥有。

代码质量平台

Sonarqube是各种数据参数集成的地方。我时常把它比成一个苦口婆心的教练,只要你一上传有问题的代码他就在你背后絮叨,想不烦就老实改了吧。此外,Sonarqube还有很多很多强大的功能,详见它家主页吧。

在我们团队的引领下,公司很多团队都要使用Sonarqube,去检测Python,C/C++的代码。好工具就是好用。

 

以上文字皆有感而发,可能也没有总结全,以后想起来再补上吧! 😀

 

读《软件方法》(上册)

《软件方法》(上册)不是只是简单介绍如何使用UML和工具的书,更是教你思考软件的本质,是潘加宇多年工作实践的总结。区区几十元可以读到这样的好书,真是无比值得。

从研究生阶段的项目到现在,我参加软件的研发已有十余年,经历过各种返工,究其原因都是因为需求没有搞清,拍着脑袋写方案。程序员多数都是技术型的,有东西做就想着怎么能更聪明的把工作完成。设计模式、重构、单元测试等各种工具技能都练的烂熟,UML也多数用在设计阶段。时间长了,各种需求的问题就出来了。需求常常“变化”,确如书中所说,需求不是真的;没有Product Owner,需求没有统一管理,大量需求散落在Issue Tracking系统里,无从查起。

《软件方法》让我重新审视软件需求的重要性。UML有很多方法对需求进行建模,一步步的发现业务机会,为用户提供更大的价值。软件工程师一定要搞清什么才是最重要的,不然拍脑袋或“镀金“的情况就会有很多。此外书中关于”阿布思考法“的讲述也无比精彩。

书中的道理归道理,可一个组织的改变谈何容易! 🙁

 

老生常谈:绝不要拷贝代码!!

首先要说一句老话,拷贝是万恶之源,是最差实践之首。

前段时间,组里有个同事实现某个新功能,其实挺简单的,前后大约做了两周。最后在Code Review的时候,发现有很多没调用到的方法和变量,代码逻辑很奇怪,然后发现代码是从另一处Copy过来的,只是稍作加工。再然后,我就让另一名工程师加入一起清理代码,又花了4天才把逻辑理清楚。清理之后的代码比之前少了60~70%,更易于维护。这一切都是Copy Code惹的祸。

为什么拷贝代码?

省工夫省时间?

Copy/Paste, so fast! 这是非常非常短视的想法,甚至有时连短期的工夫和时间都没有节省到。因为老代码里有大量逻辑,不一定拷贝过去可以直接使用。这时必然Bug漫天飞,怎么能过的了QA那关。长远看就更加不可取,无数血泪的经验,大量重复代码是项目的灾难,不可能有好的设计,后期维护的工程师会叫苦连天,工期不断延后,质量只能是垃圾,不要期盼有什么保证。垃圾的代码也留不住好的程序员,学不到任何东西,他们的青春为什么拿来给别人擦屁股。

时间和工夫有时不能省的,要耐着性子看老代码里的逻辑,”慢就是快“。

”某种项目需要“!

还有另一种可能-项目需要!一些稍大的公司或组织会同时进行几个项目,新的项目可能会在老项目的代码上扩展。为了节省工期,有些Team就直接把老项目的代码在新项目的Branch上拷贝一份。开始一切很祥和,可新老项目同时继续,同时在修Bug,加Feature。时间长了,就有可能在不同的代码Branch做Merge,也是要花大量的时间和精力。究其根源有很多,可能真是工期紧,可能是老代码的设计太差。

我觉得设计的问题大一些。这不是理想的做法,应该把需要依赖的代码做提取,对于不同行为做抽象,再以注入等方式改变所依赖代码的行为。

如何避免代码里的Duplication?

  • 做为工程师应该了解,Code不单是为别人写的,也是给未来的自己写的。不想六个月之后砸键盘吧!时刻牢记”Duplication is evil!”
  • 做好培训,尤其是新手。大多新手带着从学校实验室的“恶习”(想想那些教授老板也被坑的不轻,还不自知),入职后老员工的”传帮带“很重要。
  • 鼓励做代码重构,罗马不是一天建成的,代码也不是一天就能变好。
  • 制定Team里的Coding Guideline,加强Code Review。大家都知道”破窗理论“,有规则才能遵守,不然只能越来越糟。
  • 组织里要有分享代码的意识,多做独立于产品的可复用的代码模块。假以时日就可形成客观的代码“资产”,大大加速日后的开发和团队效率。
  • 使用SonarQube实时掌握重复代码的情况。SonarQube是个非常强大的工具,帮助团队实时的监控代码质量的变化,Duplication就是其中的一个维度。

5-22-2015 5-37-39 PM总结

不要拷贝代码。That’s it!