如何防止代码变成 SHIT

最近发现之前写过的很多项目,不管是 python/go/cpp 的,最终回看起来代码都变的很难看,尤其是多人合作的时候。 这是一个很头疼的问题。自己平时很在意这个,但是代码最终确都变成了 shit。 问题 当一个人开发的时候,问题主要在于一个人的自律性不够强,不管是代码注释等都是随意写的,即使偶尔意识到了问题,但也难以保证能一直坚持下去。 而当人多的时候,问题经常处在多人风格的不同上。如果没有工具来强制大家遵守一定的规则,那么大家每个人自己的风格放在一起的时候,就成了垃圾代码。 避免代码变成 shit 的唯一方法,就是让大家写的代码看起来都一个样。而这个工作除了由开发人员的 Code Review 之外,还需要工具来约束。 解决方法 CI/CD 最开始接触 CI/CD,我只是认为它主要是用于部署方面的一个工具。现在发现,它对于代码质量的改进也是意义巨大的。所有代码通用规范上的约束,静态分析,复杂度分析等都可以通过自动化工具来执行。 一方面,我们可以组合尽可能多的代码静态分析工具,来约束提交代码的错误,提供代码改进的建议,形成统一的代码风格。另一方面,最于 Code Review 来说,不再需要关注基本的代码风格以及基础部分,而只用关注于具体的业务以及代码架构层面的问题。 静态分析 Python 这样的代码,在多人合作的大型项目上,如果没有非常严格的代码约束,最终出来的项目时非常难以维护的。可能经常部署出来的代码连跑都跑不起来。相对来说,静态类型语言在这方面的优势是巨大的,编译器在编译代码阶段能发现大多数比较明显的问题,最终线上的问题一般都是需要人来参与分析的。 代码的静态分析是一个非常古老但是重视程度不够的技术。静态类型语言的代码分析技术能够极大地减少代码中可能存在的 bug,并给出很多的建议。以 Golang 为例,目前已经有几十款静态分析工具。 而像golangci-lint这样的工具,可以将多种分析工具结合起来,在各个层面给出代码改进的建议。比如: 代码的简化写法 可能的 bug Dead Code 未使用的或者被覆盖的变量 … SonarQube 其实是类似的产品,只不过是 Client/Server 的架构,提供了诸如复杂度分析,单元测试覆盖率等指标。良好的 UI,以及插件式的架构,与普通的 cli 工具结合起来之后,对于代码质量的提高是非常有益的。 总之,工具能处理的事情越多,人的精力就更多的能去关注更上的层面和业务层面。 Code Review Code Review 虽然成为一个共识,但真正的效率确实难以保证的。莫名其妙的改动,形式化的 approve,现有工具的局限等等问题都造成了参与的人在这方面的低效率。所以总是需要有各种规范来指导人们如何进行 Code Review。一般来讲,我们可以将代码的改动拆分为三个问题 Why? 为什么要做这个改动 How? 怎么做这个改动 What? 具体做了哪些改动。 这几个问题,工具能参与的只是What的一部分。其他的部分都需要人来 review。一般的 Code Review 提交的模板也都要求提交 PR 的人尽量说清楚 Why,通过文档 link 或者文字等形式。具体的 How 以及 What,则需要具体的人来参与 review。 ...

2019-05-01 · 1 分钟 · 94 字 · 涯余

Google 的经验

看了一篇讲谷歌公司内部的软件管理的论文,虽然对很多东西已经很熟悉了,但还是觉得有了一些新的启发。 业内对 Google 其实大多数都是一种追随者的态度。单说最近这些年的几大热门产业,大数据由 Google 的三篇论文起始,云计算由 Kubernetes 引领热潮, Alphago 在 AI 领域让人震撼。Google 比其他公司更早面临了很多技术发展的瓶颈之处,解决之后在某个时机将部分成果开源出来共享给业内。技术问题大家很容易采纳学习,但能解决这些问题的软件工程模式, 则不是那么容易学习的。 Single Repo Google 在公开这种模式之后,大部分人的态度是震惊的。因为这跟大部分人的使用模式差别很大。不管是大公司小公司,不同功能的 Repo 对应不同的功能,非常便于维护,便于划清职责。Google 的单一 Repo 模式,尤其在其规模之上,初看起来是非常难以理解的。上 Tb 的仓库数据,每天上万次的 Commit,它是如何管理的呢? 问题的答案自然是一套更为复杂的 CI/CD 系统,每一次的提交,自动化的构建、自动化的测试、自动化的 Review Check 等等,有了这些之后,代码的基本质量就有了保证,其他的就靠更为严格,精确的 Code Review 流程了。之所以大部分公司无法这样做,因为基础的 CI/CD 系统从来都不是一个公司在成长过程中优先考虑的问题,功能 -> 性能 -> Bug, 这些问题解决的差不多了,才有考虑其他的空闲。而往往此时,开发模式已经固定下来,没有了往 Single Repo 迁移的动力。 另一方面,Single Repo 带来的优势初看起来也是比较模糊的。它更多的不是一个技术上的问题,而是一个管理模式,或者企业文化上的问题。 是否能允许员工查看几乎所有的源码 Repo 如何在 Single Repo 中划分各个项目的职责边界 对 Google 来讲,去掉这个边界是必须的。他希望员工能够熟悉整个系统,不受限于自己所主要维护的组件的束缚,保持一个开放的心态。每个人都有创造的天性,当他发现有一个其他项目的问题或者优化他很想修复,或者有更好的解决方式,没有了项目的边界,他很自然地认为可以这样做也应该这样做。这种开放的模式保证了 Google 的所有项目能受惠于公司所有人的才智,也造就了 Google 在技术和商业上的成功。 Personal Time 这也是人人熟知,但几乎没有任何经常自称有 Google 背景的管理人员愿意尝试的模式。给员工留一些时间,让他做自己想做他任何想做的事。对于 Google 来说,有很多项目和改善都是来自于员工在这个时间的 Side Project。 ...

2019-04-14 · 1 分钟 · 78 字 · 涯余

Github 与编程语言

一个语言的流行程度与多种因素相关,语法的简易性,package 的数量,性能,适用的场景等等。Perl 因为语法的怪异而逐渐无人问津,ROR因性能等问题也用的人越来越少。 一向处于主流地位的 C/CPP 在这几年也比不上 JavaScript 以及 Golang 的热度。在 Github 上,我们可以看到热门的项目中,JS 以及 Golang 等热门语言占据了相当瞩目的位置。 语言之间的较量从来就不是在单纯的语言层面本身,而是整个生态系统的对比。而不知不觉间,Github 也成了每个语言生态体系的一部分。 当代的主流程序员中,大多数都有 C/CPP 的语言背景。但在大部分的工作选择上,python 与 Golang 的数量越来越多,也越来越占主流。究其原因,一方面是在语法层面上,采用了与 C 相似而更简单的表达方式。但更重要的是,从一开始,他们就考虑到了包管理系统的重要性,因为它是语言生态系统的发动机,而 C/CPP 等语言到现在仍未有一个内建的实现。 对 Python 而言,在 Github 流行之前,pip 已经非常成熟。这让他成为了一个在任何需求面前都是被优先选择的语言之一。http 请求、web 框架、爬虫、图片解析等等,只要你想要的任何功能,都可以在 pip 里找到已经有的实现。有了 Github 之后,python 的 package 的数量的扩充进一步加快。代码在 github,二进制包在 pip,文档在 readthedocs,这是一个非常完善而让人信任的体系。 对于 Golang 来说,它就是生于 Github,流行于 Github 的。从一开始 docker/kubernetes 项目的流行,以及整个容器生态的成熟,给了 golang 一个良好的开端。go 内置的对于 github 上代码仓库的支持,即使有很多小问题,但总体来讲,这让 golang 以极快的速度建立起来了超越于 c/cpp 甚至能赶上 python/pip 的生态体系。在常规的开发场景以及业务需求上,golang 以及没有短板了。 而反观 c/cpp,在 github 之前,假设我们想要去找一个 package,只能借助于搜索引擎。也许在某些奇怪的网站上,能找到一个实现方案。但是相比于 golang/github 模式,这样的方式有明显的缺陷: ...

2019-04-12 · 1 分钟 · 112 字 · 涯余

Emacs is drugs

每个程序员都会遇到这一天,他要做一个决定,vim 还是 emacs,还是 IDE。 近来一直主要用 Golang, 早已不再年轻的我自然是选择功能强大的 Goland, 日常工作无压力。即使没有免费的注册码了,我也毫不犹豫地买了正版。只是,它太慢了,太卡了,16GB 内存的 Mac 跑起来都不轻松。 在无数次的痛苦的等待中,我终于决定换一个 Editor 试一试。Atom 也慢,Code 看起来都很不错,插件多,界面舒服,速度也快,但我面对它总有一种无所适从的感觉。我偶尔会用它来做些零碎的工作,但从来没法把它当作 一个主要的开发工具。 这几天偶然翻起来一直装在电脑里确很久没有打开的 Emacs, 才明白了 Code 的问题在哪。 Code 是一个优秀的 Editor, 但也仅此而以。我们用它来写代码,代码和 Editor 是两个东西。我们要学习怎么去使用这个软件,这个学习的过程和写代码是两套系统。它像 PS,像 Word,是一个精巧的软件,是编程的产物。 而 Emacs 不同,它是一个 Editor, 但又和任何的 Editor 不同。它即是一个精巧的软件,也是一个操作系统,也是编程本身。 首先,它基于 Elisp 编写,是 lisp 到今天少有的面向大众的软件产品。他的所有扩展也都是 lisp 代码。lisp 良好的可读性能让人很容易理解一个扩展是怎么写出来的,你可以如何修改它,照着它写一个新的。你在用它的时候,能明确地感觉到你在写的代码和编辑器不是分离的两个东西。它不是一个服务于你的黑盒子,而是一个对你透明的软体。你可以随时打开它看看他的内在,修改它,调整它,让他的形态更适用于你的需求。在很多人使用 emacs 的时候,会经常发现,你打开的文件列表经常会有 lisp 代码。好像他们属于一个项目似的。 elisp 主要的功能都是面向文本编辑的,所以它比普通的 editor 有更多的概念: 缓冲区/ring buffer/minibuf/mode-line 等等。这些概念加起来,造就了最为精准丰富的文本处理和表现系统。无数在其他 editor 无法实现或者很难实现的功能,在这里都可以很容地用代码写出来。是的,就是用 elisp 代码。最终,是 elisp 代码组成了 emacs, 而对其他的 editor 来说,组成他们的是基本功能 + 扩展。 Editor/IDE 的分化,是因为用常规的软件设计思路,无法作出一个满足以下功能的开发工具: ...

2019-03-28 · 1 分钟 · 150 字 · 涯余

istio

整个容器化浪潮诞生了三个胜利者,分别是 docker, kubernetes, istio。 一个额外的胜利者是 golang。 Docker docker 的作用是: 用标准语法描述出一个服务的静态/运行时环境,无关语言与操作系统 资源隔离 被打死的是 lxc, 它有资源隔离的功能,但是缺点太明显: 没有上面的 docker 提供的第一个功能 架构不如 docker 的 cli/server 的简洁明了,易于学习 受威胁的是 VM 太慢了 性能损耗大 无法 API 化 Kubernetes 真正的 DCOS,核心优势: 统一资源模型 统一 API 模型 (引导业务 API 向其靠拢) Node 横向扩展 插件化 被打死的是 Mesos/Marathon,缺点 两层架构的低效率 (仁慈独裁与低效民主) C++ C++ 导致的难以 debug 难以扩展以增加新功能 另一个被打死的是 swarm/compose, 缺点 架构不清晰 自下而上地缓慢地堆功能 受威胁的是 YARN, 不如 kubernetes 通用性强 Istio 微服务相比于单体服务的一切问题都应该在这层解决, trace, 限流, metrics 等等 不需要修改业务代码 比手工的实现更完善,功能更强 受影响的:微服务业务代码 ...

2019-03-25 · 1 分钟 · 73 字 · 涯余