曾经有一段垃圾代码放在我的面前,我没有拒绝,等我真正开始接手的时候我才后悔莫及,程序员最痛苦的事莫过于此!
每当接手别人的代码,都有一种想重新写一遍的感觉,等到别人再来接手你的代码时,同样的感觉。。。为什么会有这种现象存在?因为没有Code Review
衡量代码质量的唯一标准就是每分钟骂出“WTF” 的频率。(出自Martin(Bob大叔)《代码整洁之道》)当你的代码在做 Code Review 时,审查者要是愤怒地吼道:
“What the fuck, is this shit?” “Dude, What the fuck!” 等言辞激烈的词语时,那说明你写的代码是 Bad Code,如果审查者只是漫不经心的吐出几个:
“What the fuck?” 那说明你写的是 Good Code。
你说我的code需要review?
一些没采取过code review模式的资深工程师可能会有一些抵触情绪,但放眼业界,code reveiw的好处是毋庸置疑的。
Google内部人士的一段话。
The biggest thing that makes Google’s code so good is simple: Code Review.
At Google, no code, for any product, for any project, gets checked in until it gets a positive review.
1、保证项目质量、提高代码可读性
2、加速个人成长、突出团队价值
3、知识传播与共享
4、凝聚团队共识
5、不断提高团队的下限
but,良好的程序设计总是优于code review,做好设计才能减少review工作量。
Code Review的内容:编程素养、业务逻辑、架构设计、单元测试、性能、安全
master项目收回提交权限,由QA把控,develop到qa分支merge需要qa review确认。
feature分支往develop分支提pr必须遵循的游戏规则:
每次提交review代码修改行数不得超过1000行,一小时内review完(先试行,最终目标400行,Cisco开发团队研究显示,进行一次Code Review不要超过400行代码(LOC, Line of Code)。大脑一次只能有效处理这么多信息,超过400 行找到缺陷的能力减弱。)
至少每个周期(两周一个开发周期)提一次review,周五早上互相喊一下,最晚提交时间周五下午2点前,周五下午的时间用来修改review代码
需要保证单元测试覆盖到,功能点要拆分足够细
checkout feature分支后能编译运行正常
工作日可以上午11点前提pr,需要组内指派资深工程师两名, 至少一人review通过
提交pr两天内需要处理完毕,打回或通过
小步迭代,理论上每周自测完成就可以提交pr merge到develop分支
常规项
代码能够工作么?它有没有实现预期的功能,逻辑是否正确等。
所有的代码是否简单易懂?
代码符合你所遵循的编程规范么?这通常包括大括号的位置,变量名和函数名,行的长度,缩进,格式和注释。
是否存在多余的或是重复的代码?
代码是否尽可能的模块化了?
是否有可以被替换的全局变量?
是否有被注释掉的代码?
循环是否设置了长度和正确的终止条件?
是否有可以被库函数替代的代码?
是否有可以删除的日志或调试代码?
代码行数统计:查看feature分支提交了多少行代码? (exclude)掉idl目录 (java thrift项目)
git log --author="shenguanpu" --since='2019-04-22' --pretty=tformat: --numstat ":(exclude)idl" | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'
added lines: 17, removed lines: 15, total lines: 2
参考文献:
http://mp.weixin.qq.com/s/A7XlAliQL__RcpK4AzuacQ 从Code Review 谈如何做技术(陈皓)
http://mp.weixin.qq.com/s/jXT1-bC7dfvzhRmh47H69g 如何写出优雅的代码
http://mp.weixin.qq.com/s/n1B0wLicwQByYslz6hYwnw 你真的会Code Review吗?
http://mp.weixin.qq.com/s/YCw7OP3RKF1EJb064IHEXg code review 有用吗?
http://mp.weixin.qq.com/s/nWntcljELd5g98b8RFTjXg code review 那些事儿
http://mp.weixin.qq.com/s/XvSuLKADV17-uF8mZmYXnw 程序员必备的代码审查(Code Review)清单
http://mp.weixin.qq.com/s/6SoJP9BMRNyLMJjwSkctUw 如何高效的Code Review
http://mp.weixin.qq.com/s/sXwuMb8lQzijWTthnaeinw 论code review代码审查
http://mp.weixin.qq.com/s/YOhKriAtUz2VViJtJRhbBw 享用腾讯免费早餐一样自然的做Code Review,他们如何做的?
本文同步更新地址:https://dotnet9.com/11520.htmlhttps://terminalmacs.com/861.html阅读导航:一、功能说明二、代码实现三、源码获取四、参考资料五、后面计划一、功能说明完整思维导图:https://github.com/dotnet9/TerminalMACS/blob/master/docs/TerminalMACS.xmind本文介绍图中右侧画红圈处的功能,即使用Xamarin.Forms获取和展示Android和iOS的通讯录信息,下面是最终效果,由于使用的是真实手机,所以联系人姓名及电话号码打码显示。并简单的进行了搜索功能处理,之所以说简单,是因为通讯录列表是全部读取出来了,搜索是直接从此列表进行过滤的。下图来自:https://www.xamboy.com/2019/10/10/getting-phone-contacts-in-xamarin-forms/,本功能是参考此文所写,所以直接引用文中的图片。二、代码实现1、共享库工程创建联系人实体类:Contacts.csnamespaceTerminalMACS.Cli
一、数据库命令规范所有数据库对象名称必须使用小写字母并用下划线分割。所有数据库对象名称禁止使用MySQL保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来)。数据库对象的命名要能做到见名识意,并且最后不要超过32个字符。临时库表必须以tmp_为前缀并以日期为后缀,备份表必须以bak_为前缀并以日期(时间戳)为后缀。所有存储相同数据的列名和列类型必须一致(一般作为关联列,如果查询时关联列类型不一致会自动进行数据类型隐式转换,会造成列上的索引失效,导致查询效率降低)。二、数据库基本设计规范 所有表必须使用InnoDB存储引擎没有特殊要求(即InnoDB无法满足的功能如:列存储,存储空间数据等)的情况下,所有表必须使用InnoDB存储引擎(MySQL5.5之前默认使用Myisam,5.6以后默认的为InnoDB)InnoDB支持事务,支持行级锁,更好的恢复性,高并发下性能更好。数据库和表的字符集统一使用UTF8兼容性更好,统一字符集可以避免由于字符集转换产生的乱码,不同的字符集进行比较前需要进行转换会造成索引失效。所有表和字段都需要添加注释使用comment从句添加表和列的备注从
最近碰到个画热图的需求,以前一直用的pheatmap,但这次的图有些复杂,靠我的水平用pheatmap还是做不出来。早已听师兄推荐过ComplexHeatmap包的强大之处,今天有空就把他学了一下(虽然在前两天我已经用ggplot和Y叔的aplot搞定了)。安装if(!requireNamespace("BiocManager",quietly=TRUE))install.packages("BiocManager")BiocManager::install("ComplexHeatmap")复制热图组成在ComplexHeatmap中单个热图由热图主体和热图组件组成。热图主体可按行或列进行拆分。热图组件包括标题,进化树,矩阵名称和热图注释,可分别放置于热图主体的四个侧面上,这些组件也可根据热图主体的顺序进行重新排序或拆分。除了画单个热图之外,ComplexHeatmap还支持组合多个热图,即称之为热图列表heatmaplist,一系列热图和热图注释的集合。在热图列表周围,可设置全局级别的标题和图例。当然除了横向排列的热图列表
一、Weex简介大约两年前,为了写一本Weex的入门书籍,我花了几个月的时间学习了下Weex跨平台相关的知识。Weex是阿里前端技术团队开源的一套跨平台开发方案,能以Web的开发体验构建高性能、可扩展的Native应用。简单来说,在集成了WeexSDK之后,开发者就可以使用JavaScript语言和前端开发经验来开发移动应用。Weex渲染引擎与DSL语法层是分开的,Weex并不强依赖任何特定的前端框架。Weex应用的页面表示层使用Vue,并遵循W3C标准实现了统一的JSEngine和DOMAPI,Weex和ReactNative一样是当前流行的跨平台开发框架。Weex的另一个主要目标是跟进流行的Web开发技术并将其和原生开发的技术结合,实现开发效率和运行性能的高度统一。在开发阶段,一个Weex页面就像开发普通网页一样;在运行时,Weex页面又充分利用了各种操作系统的原生组件和能力。Weex的官方地址为:https://weex.apache.org/。Weex最简单的方法是使用PlaygroundApp和在dotWe编写一个HelloWorld的例子,开发者甚至不需要安装任何的开发环境
一、问题的由来学懂JavaScript语言,一个标志就是理解下面两种写法,可能有不一样的结果。varobj={ foo:function(){} }; varfoo=obj.foo; //写法一 obj.foo() //写法二 foo()复制上面代码中,虽然obj.foo和foo指向同一个函数,但是执行结果可能不一样。请看下面的例子。varobj={ foo:function(){console.log(this.bar)}, bar:1 }; varfoo=obj.foo; varbar=2; obj.foo()//1 foo()//2复制这种差异的原因,就在于函数体内部使用了this关键字。很多教科书会告诉你,this指的是函数运行时所在的环境。对于obj.foo()来说,foo运行在obj环境,所以this指向obj;对于foo()来说,foo运行在全局环境,所以this指向全局环境。所以,两者的运行结果不一样。这种解释没错,但是教科书往往不告诉你,为什么会这样?也就是说,函数的运行环境到底是怎么决定的?举例来说,为什么obj.foo()就是在obj环境执行,而一旦va
总第271篇2018年第63篇本文作者来自美团成都研发中心(是的,我们在成都建研发中心啦)。我们在成都有众多后端、前端和测试的岗位正在招人,欢迎大家投递简历:songyanwei@meituan.com。背景在日常开发中,我们经常会有发布需求,而且还会遇到各种环境,比如:线上环境(Online),模拟环境(Staging),开发环境(Dev)等。最简单的就是手动构建、上传服务器,但这种方式太过于繁琐,使用持续集成可以完美地解决这个问题,推荐了解一下Jenkins。Jenkins构建也有很多种方式,现在使用比较多的是自由风格的软件项目(Jenkins构建的一种方式,会结合SCM和构建系统来构建你的项目,甚至可以构建软件以外的系统)的方式。针对单个项目的简单构建,这种方式已经足够了,但是针对多个类似且又存在差异的项目,就难以满足要求,否则就需要大量的job来支持,这就存在,一个小的变动,就需要修改很多个job的情况,难以维护。我们团队之前就存在这样的问题。目前,我们团队主要负责开发和维护多个Android项目,而且每个项目都需要构建,每个构建流程非常类似但又存在一定的差异。比如构建的流程大
ab-n1000-c50http://test.xxxx.com/www/DocumentPath:/www/ DocumentLength:28625bytes#请求文档大小ConcurrencyLevel:50#并发数 Timetakenfortests:47.986seconds#全部请求完成耗时 Completerequests:1000#全部请求 Failedrequests:0#失败的请求 Writeerrors:0 Totaltransferred:29014000bytes#总传输大小 HTMLtransferred:28625000bytes#html内容传输量 Requestspersecond:20.84[#/sec](mean)#重要指标之一,每秒请求数(平均) Timeperrequest:2399.308[ms](mean)#重要指标之一,每次并发请求时间 Timeperrequest:47.986[ms](mean,acrossallconcurrentrequests)#每个请求实际运行时间,平均值 Transferrate:590.46[Kbytes/
高铁、支付宝、共享单车、网购,这新四大发明已经使我们的生活发生了翻天覆地的变化,这些新发明都有新技术在背后做支撑。技术改变生活,生活也在考验技术。技术使我们的生活便捷,技术也使我们的信息安全遭受着前所未有的威胁编辑|Sharon官网|www.datayuan.cn微信公众号ID|datayuancn创新工场董事长兼CEO李开复:未来世界即将迎来OMO“未来世界即将迎来‘OMO’(Online-Merge-Offline线上与线下融合)的时代,而中国的发展速度相当惊人,将有望在全球范围内首先实现OMO。”下一步,服务方将会实现线下与线上数据融合,提供精准的客户推荐,提升店内服务,并实现供应链自动化和即时库存管理。未来OMO和人工智能将推动消除线上与线下数据的区分,我们能够从中获得巨大的经济利益,享受前所未有的便利。但与此同时,我们也需要在这个全新的融合世界中保护个人隐私和安全。原文链接:http://www.datayuan.cn/article/14890.htm《灰犀牛》作者米歇尔·渥克:个人隐私数据只属于用户本人目前在数据赔偿上有争议,但我认为个人必须是其中一个非常重要的部分。个人
最近一段时间再看斯坦福大学几期学习的教学视频,有百度首席工程师、百度大脑以及百度研究院的负责人吴恩达教授讲述,内容深入浅出,推荐想踏入机器学习领域的童鞋观看。这儿为了加深对知识的认知,在这儿整理出来跟大家分享交流(中间活血有一些纰漏希望大家指出改正)。这个系列主要想能够用数学去描述机器学习,想要学好机器学习,首先得去理解其中的数学意义,不一定要到能够轻松自如的推导中间的公式,不过至少得认识这些式子吧,不然看一些相关的论文可就看不懂了,这个系列主要将会着重于去机器学习的数学描述这个部分,将会覆盖但不一定局限于回归、聚类、分类等算法。 回归与梯度下降:回归在数学上来说是给定一个点集,能够用一条曲线去拟合之,如果这个曲线是一条直线,那就被称为线性回归,如果曲线是一条二次曲线,就被称为二次回归,回归还有很多的变种,如locallyweighted回归,logistic回归,等等,这个将在后面去讲。用一个很简单的例子来说明回归,这个例子来自很多的地方,也在很多的opensource的软件中看到,比如说weka。大概就是,做一个房屋价值的评估系统,一个房屋的价值来自很多地方,比如说面积、房间的数量
一、Service介绍KubernetesService定义了这样一种抽象:一个Pod的逻辑分组,一种可以访问它们的策略,通常称为微服务。这一组Pod能够被Service访问到,通常是通过LabelSelector。Service能够提供负载均衡的能力,但是在使用上有以下限制:只提供4层负载均衡能力,而没有7层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的Service的网络类型ClusterIp:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IPNodePort:在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过:NodePort来访问该服务LoadBalancer:在NodePort的基础上,借助cloudprovider创建一个外部负载均衡器,并将请求转发到:NodePortExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有kubernetes1.7或更高版本的kube-dns才支持二、Service的代理模式分类VIP和Service代理
如果是以elementUI作后管系统的UI库的话,很多页面基本都会用到el-table和el-pagination这两个组件用于数据的表格显示和分页,但是这个两个组件相对独立,于是再写了N次的el-table和el-pagination之后,我觉得是是时候需要把这两个东西封装起来了。对于我个人来说,是不喜欢封装组件的,虽然个人用起来很舒服,html标签可以少写很多,但是代码有时不是为了自己而写,因为考虑到之后如果接手你项目的攻城狮不会用或是用不习惯,那你抽成组件就反而是画蛇添足了。哈哈,主要还是像我后端同事说的,不会用还不是因为文档没写清楚,写的详细不就好了,你就是懒。 按照产品经理说过的一致性原则,我们有些样式都可以css写好,反正是需要保持用户逻辑使用一致的。先上一个el-table-pagination组件的代码: <template> <div> <el-table :data="tableData" :height="$attrs['height']" :highlight-current-row="$attrs['highlight-
原题链接 240.Searcha2DMatrixII 题目描述 编写一个高效的算法来搜索 m x n 矩阵matrix中的一个目标值target。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例1: 输入:matrix=[[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]],target=5 输出:true 问题分析 首先,我们初始化一个指向矩阵左下角的(row,col)指针。然后,直到找到目标并返回true(或者指针指向矩阵维度之外的(row,col)为止,我们执行以下操作:如果当前指向的值大于目标值,则可以“向上”移动一行。否则,如果当前指向的值小于目标值,则可以移动一列。不难理解为什么这样做永远不会删减正确的答案;因为行是从左到右排序的,所以我们知道当前值右侧的每个值都较大。因此,如果当前值已经大于目标值,我们知道它右边的每个值会比较大。也可以对列进行非常类似的论证,因此这种搜索方式将始终在矩阵中找
1.Csrf攻击概念: csrf攻击(Cross-siterequestforgery):跨站请求伪造; 2.Csrf攻击原理: 用户是网站A的注册用户,且登录进去,于是网站A就给用户下发cookie。 从上图可以看出,要完成一次CSRF攻击,受害者必须满足两个必要的条件: (1)登录受信任网站A,并在本地生成Cookie。(如果用户没有登录网站A,那么网站B在诱导的时候,请求网站A的api接口时,会提示你登录) (2)在不登出A的情况下,访问危险网站B(其实是利用了网站A的漏洞)。 我们在讲CSRF时,一定要把上面的两点说清楚。 温馨提示一下,cookie保证了用户可以处于登录状态,但网站B其实拿不到cookie。 举个例子,前端事假你,微博网站有个api接口有漏洞,导致很多用户的粉丝暴增。 3.Csrf如何防御 方法一、Token验证:(用的最多) (1)服务器发送给客户端一个token; (2)客户端提交的表单中带着这个token。 (3)如果这个token不合法,那么服务器拒绝这个请求。 方法二:隐藏令牌: 把token隐藏在http的head头中。 方法二和方法一有点像,本质
王家林亲授《DT大数据梦工厂》大数据实战视频Scala深入浅出实战经典(1-87讲)完整视频、PPT、代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt6腾讯微云:http://url.cn/TnGbdC360云盘:http://yunpan.cn/cQ4c2UALDjSKy访问密码45e2土豆:http://www.tudou.com/programs/view/mm3eDHk3T5o/优酷:http://v.youku.com/v_show/id_XMTI5OTA5OTM3Ng==.html?from=s1.8-1-1.2爱奇艺:http://www.iqiyi.com/w_19rruxjz6t.html#vfrm=2-3-0-1腾讯视频:http://v.qq.com/boke/page/i/0/f/i01610qzd2f.html技术爱好者尤其是大数据爱好者可以加DT大数据梦工厂的qq群 DT大数据梦工厂①:462923555DT大数据梦工厂②:437123764DT大数据梦工厂③:418110145 微信公众账号:DT_Spark王家林老师微信
正在播放↘@音乐 文献检索↓ @假如宇宙中有时光穿梭机 1.记住一句话:不要亏待每一份热情,不要拒绝任何冷漠。攒够失望,就脱离。爱情如此,友情如是。点我加入群聊 2.愿2020,可以这样过,一心一意,不把人愧对,坚强乐观,不让心伤悲。活着,不留遗憾,人生,无怨无悔!相册摘要 3.希望2020,没有虚情假意的朋友,没有再也不见的离别,人和人之间真诚的处着,心和心之间炽热的爱着,有了误会很快澄清,有了矛盾笑着解决。Tag生活 4.原谅我的贪心,总是想留住身边每个对我好的人,最后才发现,有些人,无论怎样也留不住。?音乐空间 捐赠↓ 我都吃泡面了,求个打赏~(记得备注博客园id呀) 微信支付宝 .elevator_item.hd-time-limited{display:block;position:fixed;right:0;bottom:445px;width:40px;height:140px;background-color:rgba(135,206,235,1)} .elevator_item{position:fixed;right:0;botto
SpringBoot功能 本节将会介绍SpringBoot的一些细节。在这里,您可以了解您将要使用和自定义的主要功能。如果还没有准备好,您可能需要阅读第二部分“入门指南”和第三部分“使用SpringBoot”部分,以使您有基础的良好基础。 23.SpringApplication SpringApplication类提供了一种方便的方法来引导将从main()方法启动的Spring应用程序。在许多情况下,您只需委派静态SpringApplication.run()方法: publicstaticvoidmain(String[]args){SpringApplication.run(MySpringConfiguration.class,args);}复制 当您的应用程序启动时,您应该看到类似于以下内容: ._________/\\/___'_____(_)______\\\\(()\___|'_|'_||'_\/_`|\\\\\\/___)||_)|||||||(_||))))'|____|.__|_|
Maven 我的小站 SSM项目需要用Maven来管理依赖,所以我们需要先配置好Maven,Maven配置很容易,我就不演示了。 创建结构 首先,我们新建Maven项目,勾选archetype,选择archetype-webapp模板,然后创建。 这里耐心等待下载完成。 到这一步也许很多小白疑问为什么创建的web项目没有java文件夹。 可以看到,这里没用Java相关的文件夹。 我们直接在main文件夹上右键新建文件夹,下面会显示一个java,直接创建就可以。 创建分层结构 此时,我们按照规范来,创建一个包。 项目结构多种多样,比如三层架构啥的,按照你的需求来。 我这里就稍微演示一下。 这里这些结构都是可以自己按照规范命名,结构也有很多,分层架构方法也有很多,这里权当借鉴一下。 配置依赖 <dependencies> <!--dependency> <groupId>org.example</groupId> <artifactId>[theartifactidoftheblocktobemounted]&
1.磁盘分区格式说明 linux分区不同于windows,linux下硬盘设备名为(IDE硬盘为hdx(x为从a—d)因为IDE硬盘最多四个,SCSI,SATA,USB硬盘为sdx(x为a—z)),硬盘主分区最多为4个,不用说大家也知道…..所以主分区从sdb1开始到sdb4,逻辑分区从sdb5开始,(逻辑分区永远从sdb5开始…)设备名可以使用fdisk –l查看 2.分区详解 使用ssh远程连接工具登录到系统,使用fdisk -l命令查看磁盘状态 此处可以看到两块硬盘hda和hdb,第一块硬盘hda是装好系统的。hdb硬盘是未进行分区的。 本例将这个10G的硬盘分区,分区计划:分一个主分区 ,大小3G,文件格式ext3.三个逻辑分区,大小分别为2G,2G,3G。实际分区个数和大小可论情况所定。 下面就是分区的详细步骤,由于是每一步都进行了截图和说明,内容略显复杂,其实很简单。 输入 fdisk /dev/hdb 然后回车,给硬盘进行分区。如下图 输入n回车新
PersistentVolume可以有各种回收策略,包括Retain、Recycle和Delete。对于动态供应的持久卷,默认的回收策略是Delete。这意味着当用户删除相应的PersistentVolumeClaim时,动态供应的卷将自动删除。如果卷中包含宝贵的数据,这种自动行为可能不合适。在这种情况下,使用Retain策略更合适。使用Retain策略,如果用户删除PersistentVolumeClaim,则不会删除相应的PersistentVolume。相反,它被移动到Released阶段,在那里它的所有数据都可以手动恢复。 [root@k8s-master1opt]#kubectlgetpv--all-namespaces NAMECAPACITYACCESSMODESRECLAIMPOLICYSTATUSCLAIMSTORAGECLASSREASONAGE pvc-1a6ba283-b16a-4cb4-b4a7-b4506534a9a920GiRWODeleteBoundkube-system/prometheus-data-prometheus-0managed-nfs-