本篇文章来自我的小报童专栏,初步规划有以下几个系列:

  • 图数据库101系列
  • 每天学点数据库系
  • 体系好文推荐系列
  • 读书笔记系列
  • 数据密集型论文导读系列

会确保每周不低于两篇更新,订阅方法见这儿,欢迎喜爱我文章的朋友们的订阅支撑,鼓励我产出更多优质文章。

国内许多大学的计算机专业,比较偏重根底和理论的“灌注”(就我当年上学的体验,现在或许会好一些),对于代码才干,虽然也有一些课程试验,但往往不太够用。所以,在进入正式工作前,许多同学就会对自己代码水平不太自信。下面我就依据我本身的写代码阅历供给一些建议。

一些阅历

我是 2010 年上的北邮,其时也是很模糊的就进了计算机专业。自然的,在大学一开端也谈不上什么学习规划。只能是沿用着高中的学习方法,懵懂地跟着老师走——上课就听课,课余就自习做作业。结果便是,学习功率很低,上课听不太懂、标题做不通透。但总之,上完计算机导论后,编程作业都是自己啃出来的,跌跌撞撞的完成之后,渐渐地竟感触到了编程的乐趣。

咱们其时大作业最多的几门课,C++ 程序规划、算法和数据结构、操作体系、计算机网络、微机原理等,现在想来,大部分都都跟玩具相同。后来做了国外一些知名大学公开课的试验才知道,要打造好一个试验项目,是非常难的工作:

  1. 首先,得适配学生的水平,预备详尽的试验材料。

  2. 其次,得搭好代码框架,在适宜的当地“留白”,给学生“填空”。

  3. 最终,还得构建足够好的自动化测试渠道,进行打分。

假如从头开发,这儿面涉及到的复杂度、需求花的心思,并不比发一篇顶会论文简单。那作为教授来说,有这些时刻,我为什么不去发一篇论文呢?究竟国内高校都是科研榜首、教学老末。

因而,我在本科课内,代码水平也并没有打下太好的根底。在后面在读研和工作中,不断探索,代码水平才一点点进步。回头来看,对我代码才干提高有比较大影响的能够总结为 “Code”:LeetCodeWriting/Review Code LoopClean Code

LeetCode

在说 LeetCode 前,想先说说工作后,见到的一类奇特的人——打过算法比赛(通称 ACM,其实是 ICPC 和 CCPC)的同学的印象。这类同学的一大杰出特色,用最简单直接的语言来形容,便是:出活快。几年的比赛阅历,让他们只要在脑袋中对需求(标题)了解之后,就能在最短的时刻内转化为代码。

因为过分懵懂,我自然是没有打过比赛,等反应过来比赛的诸般好处时,现已大三下了。其时,校队也不会招这么“大龄”的队员了,就算招,门槛也非常高,也是大学许多憾事中的一件了。

后来读了研,在找工作前一年时,LeetCode 现已相当流行了,便也和同学组队,相互鼓励着刷了起来。其时标题还不是特别多,到研二暑假找实习时,大概把前两百多道刷了两遍。一开端,会不断考虑标题是什么意思,该用什么算法解,有时半响想不出来,便去看高票答案。许多高票解真的是精妙而简练,这大概也是其时 LeetCode 最吸引人的当地之一。渐渐的对各种类型标题有些感觉之后,就开端练速度和经过率。也便是上文说的,在了解标题后,能够迅速转变为 bug free 的代码。

因而,虽然没有打过比赛,但是经过 LeetCode 的训练,的确也有了相似比赛的收成。但自然,在深度、广度和速度上都远不及那些“身经百赛”的同学。不过于我现已是收成颇丰:

  1. 对常见数据结构和算法把握纯熟。比方现在说起六种排序,特色、运用场景、背面原理,能够做到如数家珍;比方说起树的各种递归非递归遍历,脑动模仿递归执行进程,也是信手拈来;再比方链表、行列、图等特色,也能在脑中边模仿,边换成代码。

  2. 学到了许多精巧的代码片段“构件”。比方怎样二分、怎样迭代、怎样处理链表头尾节点、怎样规划根本数据结构的接口等等。这些偏“原子”的构件,是我后来工作中写代码的血肉来源。

但只有这些,是远远不够的,一到大项目里,写出的代码就很简单——“有佳句无佳章”。

Writing/Review Code Loop

遇到上述窘境,往往是因为短少中大型项目的锻炼。表现在空间上,不知道怎样组织上万行的代码,怎样区分功能模块、构建层次体系;表现在时刻上,没有经过项目“起高楼、宴来宾、楼塌了”的构建-腐烂-重构循环。

工程中在了解代码和组织代码时有个矛盾:

  1. 可了解性。作为维护人员,咱们学习代码时,多喜爱顺着数据流操控流来了解,所谓依据某个头,一路追查究竟,是为纵向

  2. 可维护性。但作为架构人员,咱们组织代码时,为了简单维护,多是依照环绕模块来组织代码——把关联紧密的代码聚合到一块,是为横向

所以咱们在拿到一个大工程时,假如立即地毯式的看代码,肯定会昏昏欲睡、事倍功半。不幸的是,因为多年读书养成的强壮习惯,这个毛病,跟了我许多年。正确的打开方法是,要像对待团在一起的多条线相同,找到“线头”,然后渐渐往外揪。在项目中,这些线头是:service 的 main 函数、各种单测入口。

但咱们在构建一个大工程时,又得反着来:先建立一个揉在一起的主流程,然后逐渐迭代。就像盘古开天辟地相同,随着时刻而演化,让天渐渐地升高、地渐渐下降,让整体化为地上四极、山川河流、太阳月亮。如是迭代,将一个混沌的流程,渐渐地模块化。比方常用的工具模块(utils)、业务相关根底模块(common)、操控模块(controller、manager)、RPC HTTP 等回调处理模块(processor)等等。

但当然,假如你现已有了构建某种类型体系的阅历,则并不需求在构建初期阅历这个绵长进程,能够直接按阅历分出一些模块。更进一步,你现已构成了自己的一个代码库,比方时钟、网络、多线程、流控等等,能够直接拿来就用。

那剩下的问题便是细节的微调,咱们在进行分层时,边界处的功能,是往上升,仍是往下沉;某个较完整的结构,是拍平到运用类里,仍是独自拎出来;这些五花八门的决策,都没有一个定则,更多的仍是依据场景的需求、工期的长短等许多实际情况,便宜行事。而这种背面的决策,则是在长时刻对中大型项目的学习、对他人修正的 Review、自己上手摆架子和修修补补中,一点点构成的直觉。

就像股票市场有周期相同,工程代码也是有其周期。不阅历一个股市牛熊周期,咱们不敢轻言空多;不阅历过一个工程构建-老练-腐烂的周期,咱们也不敢轻言取舍。即,没办法在工程构建初期,预见到其最常用的打开方法,进而面向主要场景规划,献身次要场景的便利性。

单元测试的重要性,怎样着重都不为过。一方面,能不能写出的单元测试,意味着你代码的模块边界是否清楚;另一方面,经过规划好的输入和输出,测试能够确保某种“不变性”,之后无论你怎样微调、重构,只要能跑过之前的测试,那就能够放心一半。另一半,就要靠自己和他人不断 Review 、测试集群线上集群不断地迭代了。

所以,这个进程是一个无休止的 loop,不断的磨,尔后不断地提高。

Clean Code

最终说说对代码的品尝。末节标题是:Clean Code,是因为我对代码的品尝,最初是从 Clean Code: A Handbook of Agile Software Craftsmanship[1] 这本书建立起来的。其第二章对命名——这个工程中“最难”的工作——的阐述,给我印象很深。

举几个比方:

  1. 单一责任。假如你不能清晰的对你的类或许函数命名,说明你的类或许函数干的工作太多了。

  2. 命名替代注释。比方不要直接运用字面值常量,最好给其一个姓名;比方最好不要运用匿名函数,也要给其一个能看出意义的姓名。

工作中,咱们常说,某某对代码有“洁癖”。我也多少有一些,但我并不认为这是洁癖,而是一种对美的欣赏和追求。代码的美表现在哪里呢?我这儿略微抛个砖(当然,我之前也写文章就代码命名问题烦琐过,感兴趣的能够点这儿[2]能够去看看):

  1. 一致性。比方具有相同意义的实体,运用相同的命名;而需求区分的实体,则要经过命名阈、前缀来进行甄别。然后给读者形成最小的心智负担。

  2. 体系性。是指咱们在做一组相关接口时,要考虑其体系统性。比方增修改查,比方出产消费,比方预处理、处理、处理后,比方读取写入等等。体系性又包括对称性和逻辑性,让人在拿到一组接口时,就能最小本钱地了解其是怎样相互联络、又是怎样具有区别的。

  3. 没有赘肉。写代码,不要烦琐,不要烦琐,不要烦琐。假如不小心烦琐了,说明你或许没有想清楚所解决问题的实质。复杂的表象,在不断地剥离杂质后,往往有很简单的关窍。捉住这些关窍,再往其上附着骨血,一起理清楚1对1、一对多、多堆多等依赖联系,往往能化简为繁。

不同概念(对应代码中的类)间的联系,在了解代码组织的时分至关重要,最好在姓名上有所表现,比方1对1,一对多仍是多对多。每个概念的内涵,以及多个概念之间的包括、连接联系,是在做模块规划的时分最需求考虑的工作之一。

在审美之外,还要说说建模(在某种程度上和隐喻是相通的)。究竟,咱们在说构建时,本身便是借助的建筑学中的隐喻。软件工程中,相似的隐喻随处可见。

咱们大脑在认知新事物时,多建立在基于旧的模型推演上。因而,假如在处理模块时,假如能从经典的模型库中,找到一个相对适宜的抽象,往往能够极大降低用户了解门槛。比方经典的出产者顾客模型、树形组织模型、路由器模型、线程调度模型、内存模型等等。此外,也能够运用某种常见意象、隐喻来命名项目,往往也能在易了解性上收成奇效。比方监控体系,能够叫“鹰眼”;比方各种流水线管控,能够叫“富士康”(手动斜眼);再比方更常见一些的数据收集,咱们都知道他叫——“爬虫”。

The last Thing

世间的工作往往是多方印证、相互补足的——假如你想写好代码,就不能仅仅低头写代码,你得去读读前史、学学美术、写写文字、见见河山,建立一套你自己的审美偏好,然后将其理念平移到写代码里来,才干写出符合直觉、具有美感的好代码。

参考资料

[1]Clean Code: A Handbook of Agile Software Craftsmanship: book.douban.com/subject/419…

[2]好好写代码之命名篇——琢磨: www.qtmuniao.com/2021/12/12/…

题图故事

写好代码,我的三个 Code

最近回北邮西土城校区转了一圈,从教三看主楼和新科研楼