分享让人折服的优秀代码基因

简介:

1 背景

 

近来参与一个较大团队的项目实施,项目的金额两千万,人数近百。但是,项目实施后,暴露出以下几个问题:

(1)质量不佳,团队成员水平参差不齐,软件外部质量、内部质量一致性差;

(2)需求不确定,时间非常紧,代码频繁修改,越来越丑,效率变低。

 

为了保证项目按时按质交付,质量改善刻不容缓。因此,在项目的初中期开始,做了以下三件事情:

(1)制定统一的界面规范,制定了统一参考实例,为所有成员进行定期界面规范的培训和评审;

(2)制定统一的代码规范,制定了《评审文化构建》、《代码之丑》PPT,培养团队的质量文化和评审文化,实施评审;

(3)引入管理工具ReviewBoard。

 

项目统一构建了标准、规范,有效保证了界面的一致性,但是代码质量的提高却不是那么简单的事情。在这里,我暂不分享项目的情况,未来会通过更加详细的文章来介绍标准、规范化软件开发方法对于项目的重要性。

 

2 ReviewBoard介绍

 

这里倒是引出了一款优秀工具ReviewBoard。这款工具简单易用,功能强大。通过它来实施代码评审非常有效。代码评审分为提交前评审(Pre-Review)和提交后评审(Post-Review)两种方式。提交前评审,即开发人员代码变更后,需要提交到ReviewBoard,经过评审通过后,才能提交到SVN源码服务器,如果没有通过评审,则代码提交会失败,一行都无法提交;提交后评审,即开发人员先提交代码,然后再提交变更到ReviewBoard,如果评审未通过,则修改代码,更新评审直到通过为止。这两种方式,各有优劣,我们采用的是后一种,它不阻塞开发人员提交代码,无法100%控制所有质量,但是可以达到80%以上。

 

ReviewBoard设计之初更多考虑的是支持Pre-Review方式,因此,存在以下问题:(1)提交通过后,Review无法自动进行状态变更为关闭,会与所有通过评审的ReviewRequest混在一起;(2)无法看出未通过评审的请求进行再次更新,因为如果再次更新后,意味着要进行第二次评审。在管理过程中,会查询哪些请求没有通过评审,定期给开发人员发送通知。

 

因此,我决定对ReviewBoard进行订制来支持以上功能。不过,ReviewBoard是基于Python语言和基于Django框架开发,我从来没有学习过Python,更没有学习过Django,那如何来修改?所以,我开始对ReviewBoard做研究。ReviewBoard最新版本只能在非Windows运行,我在Ubuntu 14.04安装部署,同时使用MySQL数据库。因此,我开始来尝试做修改。

 

3 尝试修改ReviewBoard

3.1 探索第一步:数据库

 

首先,研究数据库,惊讶发现其数据库设计非常的整齐,压根不需要查看任何文档即可知道数据库的表、字段的意义。我找到了几个关键的表,分别是reviews_reviewrequest,看看其字段,与界面显示几乎一致,一下子就明白什么意思,顺着字段意思,找到了另外的两个关键表diffviewer_diffsethistory、diffviewer_diffset。查询一下这些表的数据,我很容易来解决第一个问题,通过一条SQL语句即可将通过评审的ReviewRequest关闭,这样就不需要查看到这些评审请求了。

 

3.2 学习Python并修改代码

 

接下来的第二个问题,需要修改代码,我花了3个小时学习了Python,通过在线的英文帮助,直接在控制台做实验,学习基本语法结构、学习类与对象编程、学习了Python模块与编译,对Python初步熟悉之后,我决定开始来进行代码修改。

 

因此,我先通过相似列“Submitter”对所有文件进行查询,通过它很快找到了columns.py和grids.py这两个文件,看了代码之后,发现ReviewBoard的评审请求通过这两个文件来实现,进行再次查询名称没有再发现关联文件了。通过这两个文件,可以发现,columns.py用于定义要显示的所有的列,grids.py进行列的组合和显示。那么接下来可以简单的进行模仿添加一个列了。该列定义为Diffs。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class  DiffSetCountColumn(Column):
     """Shows the diff set count of published reviews for a review request."""
     def  __init__( self * args,  * * kwargs):
         super (DiffSetCountColumn,  self ).__init__(
             label = _( 'Diffs' ),
             detailed_label = _( 'Number of Diffs' ),
             shrink = True ,
             sortable = True ,
             link = False ,
             * kwargs,  * * kwargs)
 
     def  render_data( self , state, review_request):
         if  review_request.mydiffsetcount >  1 :
             return  ( '<span class="issue-count">'
                     ' <span class="issue-icon">!</span> %s'
                     '</span>'
                     %  review_request.mydiffsetcount)
         else :
             return  ''
 
     def  augment_queryset( self , state, queryset):
         return  queryset.extra(select = {
             'mydiffsetcount' """
                 SELECT COUNT(*)
                   FROM diffviewer_diffset
                   WHERE diffviewer_diffset.history_id =
                         reviews_reviewrequest.diffset_history_id
             """
         })

  

简单说明一下,我定义了DiffSetCountColumn类,继承于Column类,类初始化方法为__init__,相当于构造器。这里的self是以前经常使用的this,定义了两个方法,一个是augment_queryset,用于当前列的数据显示,定义名称为mydiffsetcount,另外定义一个方法render_data,即在表格中展现数据。这里参考了其它列定义。

 

接下来在grids.py中声明对该列的使用,非常简单。

 

25行新增:

DiffSetCountColumn,

99行新增:

diffset_count = DiffSetCountColumn()

 

接着重启Apache服务器,可以简单测试,惊讶发现可以工作了。

 

3.3 再进一步添加功能

 

有了这次尝试,我接下来想再进一步来定制。目前各个小组提交到不同的SVN地址,通过SVN可以区分各个组提交情况。但是ReviewBoard没有针对SVN地址的过滤。

 

首先修改columns.py,修改Repository列。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class  RepositoryColumn(Column):
     """Shows the name of the repository the review request's change is on."""
     def  __init__( self * args,  * * kwargs):
         super (RepositoryColumn,  self ).__init__(
             label = _( 'Repository' ),
             db_field = 'repository__name' ,
             shrink = True ,
             sortable = True ,
             link = True ,
             link_func = self .link_to_object,
             css_class = 'repository-column' ,
             * args,  * * kwargs)
 
     def  augment_queryset( self , state, queryset):
         return  queryset.select_related( 'repository' )
 
     def  render_data( self , state, obj):
         return  super (RepositoryColumn,  self ).render_data(state, obj)  or  ''
 
     def  link_to_object( self , state, obj, value):
         import  urllib
         return  local_site_reverse( 'all-review-requests' ,
                                   request = state.datagrid.request)  +  '?'  +
                urllib.urlencode({ 'repository' :obj.repository_id})

  

 在这里更改该列支持Link,接着定义link_to_object函数,这里找了一段时间,发现local_site_reverse可以用于获取需要的url,然后再与url组合,一开始没有使用urlencode,一直无法正常呈现。由于原来在ASP.NET中,使用过urlencode,知道这里面有坑,就网上查询了Python的urlencode,然后解决之,发现可以工作了。不过,下一个问题来了,即链接后,如何进行过滤?这里发现其“show closed”过滤功能,通过代码查询,知道在grids.py中,如何工作,那么,添加过滤也就不难了。如下。

 

grids.py 第116行

 

self.repository_query = ‘'

 

grids.py 第133行

 

        self.repository_query = self.request.GET.get('repository', '')

        

        if len(self.repository_query) > 0:

             self.queryset = self.queryset.filter(repository_id=int(self.repository_query))

 

4 ReviewBoard令人震惊的优秀代码基因

 

顺利修改之后,我大为震惊,为ReviewBoard这款优秀的软件说叹服。为什么能够在1天时间里面,从Python学习到对一个完全黑盒子的软件进行修改?答案就是ReviewBoard具有非常整洁的代码。也就是说,ReviewBoard拥有非常优秀的内外部质量。

 

数据库设计,简单清晰,结构非常清晰,可读性很强,根本不需要任何数据库文档。文档是多余的!!!

 

代码风格非常一致,我们发现ReviewBoard的注释非常少,Bob大叔的《代码整洁之道》强调了注释是代码意图表现失败的补充,最好的代码是一行注释都不要。ReviewBoard的命名,从前到后都非常一致,大小写、下划线、类名、方法名规则统一,命名准确无误,没有不专业的命名,没有不专业的缩写。ReviewBoard的类都非常简单,在columns.py这个文件,你可以发现每一个Column基本都在50行以内,每一个方法也非常简单。ReviewBoard非常完美的践行了单一职责,清晰的告诉我,要完成什么任务可以通过哪些类、哪些方法、写什么样代码来完成。ReviewBoard代码风格非常优秀,没有丑陋的缩进,没有丑陋的拥挤,在该有空格的时候空格,在该有空行的时候空行,在该缩进的时候缩进。这里,我看不出任何代码腐败的味道。跟着这种优秀的软件“混”,我也很难写出差的代码。

 

在写代码这件小事上,可能很多人眼里只有架构、框架这类东西,可是实际上,很多工作多年的程序员,代码依然是狗屎一样,没有规范的风格,没有良好的编码习惯。很多人能够去完成一件工作,但是,不漂亮。在没有意识的情况下,随着时间推移,只是做的丑事更多而已。从我的编码经验,可以总结出一个程序员现状,1~3年的开发人员,处于混乱状态,他们能完成功能就不错了;3~5年的开发人员,有些抽象意识,但是,一种是走向黑客,代码抽象的只有自己和上帝看得懂,一种是变得专业,倾向编写一些让团队其他人员看得懂的代码,还有一种就是保持现状;5年之后,开发人员又是三类,一类走向管理,也是不错选择,一类走向更高的技术路线如架构师或者专家,还有一类,就是变成废物,随着时间的推移,他们越来越没有空间,越来越没有价值。一般而言,通过培养,年纪越轻的人,成长越快,越有前途,要提升他们的水平,代码评审是最有效的方法,通过评审和培训让他们知道什么是美、什么是丑,什么是优秀、什么是低劣。

 

5 致敬

 

再次致敬ReviewBoard!ReviewBoard既是提升我们整体实力的有效工具,也是一款值得学习的软件,感谢ReviewBoard!(我激动的想给它捐款时,竟然找不到按钮~~)

 

另外,我们使用了TaoReviewBoard、FindBugs、JSHint这些工具,感谢你们~~。

 

在代码评审,我大量引用Bob大叔的两本著名书籍《代码整洁之道》、《程序员的职业素养》,非常好的书,感谢Bob大叔!


本文转自道法自然博客园博客,原文链接:http://www.cnblogs.com/baihmpgy/p/4753679.html,如需转载请自行联系原作者

目录
相关文章
|
18天前
|
数据挖掘 数据库
略微学习一下二区4.5分纯生信,单基因肺结核叶酸基因集+泛癌分析
研究摘要: 一项发表于2023年《MEDIATORS OF INFLAMMATION》杂志的文章发现,RTP4基因可能成为诊断肺结核的新生物标志物。研究者通过分析GEO数据库中的多个微阵列数据集,使用WGCNA方法识别与肺结核和叶酸生物合成相关的基因模块。RTP4在健康与肺结核患者间的表达有显著差异,并且在抗结核治疗前后表达量变化。泛癌分析显示,RTP4在不同肿瘤类型中的表达与预后关联不一,提示其可能在多种癌症中具有重要功能。这些发现支持RTP4作为诊断工具的潜力,并为进一步研究其在结核病和癌症中的作用奠定了基础。
20 1
|
1天前
|
数据可视化 数据挖掘
singleCellNet(代码开源)|单细胞层面对细胞分类进行评估,褒贬不一,有胜于无
`singleCellNet`是一款用于单细胞数据分析的R包,主要功能是进行细胞分类评估。它支持多物种和多分组分析,并提供了一个名为`CellNet`的类似工具的示例数据集。用户可以通过安装R包并下载测试数据来运行demo。在demo中,首先加载查询和测试数据,然后训练分类器,接着进行评估,包括查看准确率和召回率的曲线图、分类热图和比例堆积图等。此外,`singleCellNet`还支持跨物种评估,将人类基因映射到小鼠直系同源物进行分析。整体而言,`singleCellNet`是一个用于单细胞分类评估的综合工具,适用于相关领域的研究。
15 6
|
3月前
|
芯片
基因测序的原理是什么
基因测序的原理是什么
|
10月前
|
Shell Python Perl
宏基因组之基因预测
12年有篇BMC的文献对几款预测的软件做了评估,其实参考大多数的文献中最常见的俩个软件也就是Prodigal和Metagenemark这俩个软件,分析过程中我这俩个软件都感受一下,现在将过程记录一下~~有兴趣的话可以看看这篇文献哦。
194 0
|
10月前
|
存储 算法 数据可视化
利用TCseq包进行基因表达趋势分析
TCseq包提供了一个统一的套件去处理不同时序类型的数据分析,可以应用于转录组或者像ATAC-seq,Chip-seq的表观基因组时序型数据分析。该包主要的集中于不同时间点的差异分析,时间趋势分析及可视化作图。
235 0
|
10月前
|
数据库 网络架构 索引
宏基因组之基因丰度计算
目前有两种方式可计算宏基因组基因的丰度,一种是基于比对,比如bwa,bowtie,soapaligner等主流的比对软件,另一种是不比对快速估计基因丰度,可以用近俩年来流行的salmon软件,这个软件在转录组的数据比对中也经常用到,可以直接计算出原始的Counts值和标准化的TPM值,此外由于是基于非比对,计算的速度得到很大的提升,同时也节省了部分的内存(少了庞大的sam/bam文件),可以说是多快好省,但是目前的高分文章中也还是不少用基于比对的方法去计算宏基因组的基因丰度的,下面我就分别简单介绍一下基于比对的soapaligner和不比对快速估计的samlon俩个软件的操作流程!!
552 0
|
10月前
|
算法 索引 Python
宏基因组之基因组装
宏基因组组装,即把短的reads拼装成连续的序列contig,再根据PE等关系将contig拼装成scaffold。与单个基因组组装不同,宏基因组组装最终得到的是环境样品中全部微生物的混合scaffold。理想情况下一条scaffold对应一个物种的全基因组。但由于序列太短或者覆盖度不够,很难拼出一条完整的基因组。针对高通量测序数据,出现了多种拼接算法和软件。
419 0
|
10月前
|
Shell 数据库 Perl
从NCBI获取物种线粒体基因信息
本分分享了一种从 NCBI获取物种基因组信息页面提取其线粒体基因信息的操作指南,以供参考
432 0
|
10月前
|
数据采集 设计模式 存储
全基因组重测序流程【超细致!!】
全基因组重测序流程【超细致!!】
|
11月前
|
机器学习/深度学习 人工智能 计算机视觉
吉林大学团队使用 AI 分析大量生物数据,探索蛋白质变构过程的动态相互作用
吉林大学团队使用 AI 分析大量生物数据,探索蛋白质变构过程的动态相互作用
107 0