Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

编写易维护的python项目

$
0
0

从实习到现在使用python也快两年了,虽然经验依旧不多,不过维护旧项目和开发新项目好歹也都经历过,记录下想法就当年终总结吧。

易编写,难维护

Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.- John Woods

python做项目给我的感觉就是易编写,难维护。一方面是动态语言本身的特性,比如没有类型声明,难以重构等;另一方面就是团队流程和规范的问题,没有严格的流程控制提交代码的质量。目前很多使用python的公司都是小公司,很多流程不正规,没有编码规范,没有文档,没有注释,没有code review,没有单元测试,没有持续集成等等,最终的代码质量可想而知,维护成本很高。

单元测试

测试只能证明缺陷存在,而无法证明缺陷不存在。

我之前写了两篇博客讲单元测试的重要性和flask单元测试的实践,很多东西也是在项目中自己慢慢摸索的,慢慢也摸索出了一点门道,单元测试对于减少缺陷还是很有帮助的,这里不再浪费口舌了。

但是遗憾的是,很多自学python的程序员似乎不怎么重视。要么是偷懒、要么是因为工期紧张不写。虽然我不是个处女座,但是我还是坚持不要因为工期违背原则,与其将来修修补补,不如现在就减少错误,我觉得这是个职业程序员的基本素养。当你改了代码捅娄子了才会发现单元测试对于保证旧代码正常执行多么重要。不要还停留在写个函数print下就觉得结果对了的阶段。

需求更改是怎样导致代码腐化的?代码黑洞

Keep knowledge in plain text. Plain text won’t become obsolete. It helps leverage your work and simplifies debugging and testing.

最近经常碰到的情况就是,很多需求的更改都是口头进行的,这些需求变更导致往代码里插入一些很tricky的逻辑。但是没有注释,需求文档又没有说明,这样就对维护代码的人产生了『代码黑洞』。我一直想强调的就是,需求文档及时更新,有迹可循,好让后来维护项目的人快速熟悉需求。

命名

计算机科学两大难题:缓存失败和命名。――Phil Karlton

不知道你是否遇到和我一样的问题,同样的命名”date”有些地方是个string,有些地方是个datetime.date对象。以至于我后来不得不用date_str和date_obj来区分,当然你也可以到处都用恶心的isinstance判断。

我一直怀疑鸭子类型是否真的那么有用,如果是的话,python3为何要加上type hint?有时候我觉得动态语言的命名真的恶心,尤其是你的词汇量匮乏的情况下,很难通过一个变量的命名看出其类型,之前维护的代码没有什么注释和文档,没有单元测试,几乎每个函数都要从头到尾看一遍才可以理解,维护起来相当吃力(尤其是中间复杂的数据结构)。我现在一直有个习惯,用data_obj_list, name_set等后缀命名,虽然冗余,至少看起来清晰。

灵活性与可读性

I think a lot of new programmers like to use advanced data structures and advanced language features as a way of demonstrating their ability. I call it the lion-tamer syndrome. Such demonstrations are impressive, but unless they actually translate into real wins for the project, avoid them. - Glyn Williams

python语言相对灵活,但是真的需要那么多技巧吗?很多新手初次尝试了args和kwargs的便捷之后,开始滥用,但是灵活的代价就是牺牲可读性。没有文档的话,对于这种函数我甚至传入什么参数都不知道。

还有经常见到偷懒使用幻数,而不是枚举,是啊,写个数字多方便。。。虽然我觉得不用幻数是个常识,但是甚至工作多年的工程师依旧偷懒这么写,你作为个刚入职场的人有些话又不被采纳,又没有老手给所有人code review改正。

灵活性与可读性,总得适当斟酌,合适的地方使用合适的技巧,google的python编码规范就特意规避了一些容易出错的特性。

为什么我不喜欢不规范的团队?

Organize teams around functionality. Don’t separate designers from coders, testers from data modelers. Build teams the way you build code.

可能我有些处女座的特质吧,但是我真不喜欢维护别人写的代码,尤其是没有注释,没有文档,没有单元测试,编码风格混乱的代码

老实说我不太清楚别人的团队如何,但是我个人不太喜欢不规范的团队,我觉得代码规范、codereview、单元测试是一个高质量团队最基本的东西,然而很多小团队并不是很重视,代码质量可想而知。(现公司代码后端代码规范还是我这个新手写的,不知道该高兴还是。。)

我一直觉得python适合构建小而美的团队,没有规范,就等着维护噩梦吧。

什么是程序员的职业素养?

A good programmer is someone who always looks both ways before crossing a one-way street. - Doug Linder

大部分招聘都是看算法,我也是这么做着笔试题进公司的。做了几个无聊的素数判断,合并列表,还有被问到千篇一律的快排。(我也因为基础不好被拒绝过很多)

我一直在想,究竟什么是程序员的职业素养?算法?数据结构?数据库?计算机网络?好像大部分时间用不到。

直到我工作了一年多,做了几个新项目同时也维护了个恶心的旧项目后,我的看法慢慢改变了。我发现有些东西只能说是知识,有些东西才能叫做素养。良好的规范,自解释的代码,主动写单元测试构建高质量项目等,我觉得除了基本知识外,这些才能称之为素养,不是每个人都是技术高手,但是还是可以做一个合格的代码工,完成功能,不捅娄子就好。

和不同类型的程序员协作

If programmers were electricians, parallel programmers would be bomb disposal experts. Both cut wires. - Bartosz Milewski

团队里什么人都有,经验丰富的工程师,技术高手,实习生,从别的语言转过来写python等,还有些混日子的老菜鸟,用过多年python却连pylint都不知道的。我的感觉就是,对于项目管理不善的团队,做好自己事,代码规范,docstring,单元测试等,别人不写你又无权强制要求的时候,写好自己的就行。改变自己远比改变他人容易,而且用python的时候大部分是小团队,小公司,可能还会遇到很多这种类似的问题。

为什么理解别人代码这么难?

Don’t use wizard code you don’t understand. Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project.

当我参与维护代码的坑后,我也遇到了这个问题,尤其是当你被告知『这些都是业务逻辑,就是这么写的』时候。遗憾的是当时的需求文档已经找不到,理解代码的唯一方式只能是一行行走查和断点调试(没有文档,注释,风格混乱)。我发现有时候不是理解代码困难,而是看到不好的代码产生的负面情绪让我压根没心思去维护别人的代码。后来我又养成了一个习惯,python函数和类的docstring里我会习惯性地把需求文档地址附上,如果解决问题的过程中参考了github或者哪个stackoverflow地址我也会附上,帮助理解代码的人快速上手(你需要消除为什么我TM自己能看懂,就是别人看不懂的幻觉)。我发现很多习惯都是我不断才坑才总结出来的,吃一堑,长一智。。。。。。

需求需要归档吗?

理解需求是我认为接手项目最难的地方之一,也是维护他人代码最难的地方之一。当然我不能奢求产品经理用版本控制维护需求文档,以便我查看频繁的需求变更,但是如果将来哪个人需要接手别人的代码了,我希望可以快速上手了解需求。有些项目的特点就是逻辑比较复杂,代码中间用了很多小trick,同时又随着频繁的需求变更修修补补,代码越写越难看,没有单元测试又不敢重构,即使是一坨屎一样的代码也只能继续堆逻辑。。。维护这种代码总有一种想离职的冲动。

docstring

English is just a programming language. Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on.

python有个特色的注释叫做docstring,怎么写docstring我之前也总结了,只是希望程序员都能重视下文档吧,这也是练习写作能力的好机会,说不定你就是将来的池建强。你看虽然我的写作能力拙劣,病句不断,但我就是脸皮厚,甚至之前我从我博客复制粘贴的答案还在知乎获得几百个赞呢,这就是写博客的好处。对于复杂函数的docstring,函数的意图、功能简介、传入和传出参数及类型最好要写上,即使函数内部很复杂,但是通过文档你能直接拿来用,docstring的目的就达到了。之前维护的代码经常传入一个dict,甚至是一个嵌套的dict都没有注释,通过命名又看不出类型,好家伙,几乎只能打断点然后每一步输出变量查看值,看别人代码和理解业务逻辑几乎就成了最困难的任务。如果不能写出自解释的代码,建议还是用java吧,python大项目不好维护。

什么是好code?

Don’t live with broken windows. Fix bad designs, wrong decisions, and poor code when you see them.

可以正确高效完成业务功能;格式规范,经过pylint和pep8检测;docstring较为完善,接口易用性高;易读易维护,控制复杂度。看似简单,人多了时候保证每个人都能做到是非常困难的。

敏捷就是快?

The Agile movement is not anti-methodology, in fact many of us want to restore credibility to the word methodology. We want to restore a balance. We embrace modeling, but not in order to file some diagram in a dusty corporate repository. We embrace documentation, but not hundreds of pages of never-maintained and rarely-used tomes. We plan, but recognize the limits of planning in a turbulent environment. Those who would brand proponents of XP or SCRUM or any of the other Agile Methodologies as “hackers” are ignorant of both the methodologies and the original definition of the term hacker. ― Jim Highsmit

很多团队学到的敏捷除了”快”以外,诸如TDD,结对编程,代码复查等好的实践似乎都没学到。当然敏捷这个词也是我走出校门之后才知道的,我没管理过项目,只是最近学了点TDD的东西才开始用pytest在最近做的项目上尝试,自我感觉还是比较良好的。用个监控文件的命令行工具,每次代码更改通过了就能看到齐刷刷的绿线,多了点心理安慰。当然单元测试还有个好处,我可以『破坏性』重构,之前没有单元测试的时候,再恶心的地方你都不敢改,但是现在我敢放肆地改代码,快速修正恶心到我的地方。

客户思维

真正行动之前,考虑多个可能的方案,权衡利弊,根据对需求的理解和客户提供的信息给出可操作的、有价值的建议,而不是立马闷头写代码,后来却发现需求理解有误,导致无意义的返工。接到一个新需求,首先要思考为什么有这个需求产生,它解决了什么问题,提供了什么价值。

代码之外还是有很多需要学习的吧,有时候技术问题反而不是主要问题,很多坑只有亲自踩一踩才知道。


Viewing all articles
Browse latest Browse all 9596

Trending Articles