论坛首页 Java企业应用论坛

一段弱智代码引发的一些思考(我们是不是该进行BDD了?)

浏览 31338 次
该帖已经被评为精华帖
作者 正文
   发表时间:2012-04-02  
没有对业务方法进行单元测试,理论上带点逻辑的,非set/get方法都应该做单元测试。
0 请登录后投票
   发表时间:2012-04-02  
有同感,对于某些项目,人员流动,人员处理模块的交叉比较大,在这种情况下,代码的可读性比效率神马的都要重要,本人不喜欢 for ( int a : a[5]) 这种写法(因为后面的人需要第几个的对象时需要修改较多代码);同理 if(条件) a=b; 这种执行语句没有大括号的语句,别人在增加语句时可能出错,即使不出错,需要加的也会变多。
0 请登录后投票
   发表时间:2012-04-02   最后修改:2012-04-02
谈谈我们公司现在采用的办法(20人左右的开放团队):

1. 首次提交单元测试分支覆盖率(Branch Coverage)要达到80%以上(采用Maven的Cobertura插件来保证)。在后续的开发中,如果单元测试的分支覆盖率有所提高,则把数值调为实际值,只准增加不准减少。Team Leader定期检查pom.xml中的设置是否被队员意外调低。

有些人可能觉得这种方式太迂腐。不过它最大的好处是能有效地引导程序员把包含复杂分支结构的程序段抽成独立的方法。原因是,象楼主写的那种复杂条件判断,为了达到完全分支覆盖,你要分别写 子判断*2 个测试用例。如果这种条件式嵌在一个100行的方法里,你就需要为这N*2个测试用例准备上下文环境。只要不算太笨的程序员,很快就会发现最省事的办法是把这个复杂判断式抽出来作为一个独立的短方法。而对于管理者来说,这种方式很容易操作,不用苦口婆心地劝程序员们不要写长方法了。一段时间之后,程序员们就会自动养成倾向于写短方法的习惯。

当然为了达到85%以上的分支覆盖,必须把编写单元测试的时间也算到进度里。现在我们并不对单元测试的代码质量作很高的要求,编写单元测试的时间大概是写相应功能代码时间的四分之一到三分之一。

2. 鼓励程序员之间非正式的交叉代码审查。鼓励程序员在维护代码时,如果发现有可疑或者不明白的地方,通过看历史记录和Blame信息,找到可疑代码的原作者私底下咨询。

3. 鼓励使用Git作为本地代码库(公司的主代码库使用svn,通过Git-svn与本地库整合)。这个规则主要是为了避免一次性提交大量代码,保证保持详细的历史记录和Blame信息(Blame信息加上正确的命名规则可以取代大量不必要的代码内注释)。而且Git的Bisect功能也是排错的一把利器。
0 请登录后投票
   发表时间:2012-04-02  
kidneyball 写道
谈谈我们公司现在采用的办法(20人左右的开放团队):

1. 首次提交单元测试分支覆盖率(Branch Coverage)要达到80%以上(采用Maven的Cobertura插件来保证)。在后续的开发中,如果单元测试的分支覆盖率有所提高,则把数值调为实际值,只准增加不准减少。Team Leader定期检查pom.xml中的设置是否被队员意外调低。

有些人可能觉得这种方式太迂腐。不过它最大的好处是能有效地引导程序员把包含复杂分支结构的程序段抽成独立的方法。原因是,象楼主写的那种复杂条件判断,为了达到完全分支覆盖,你要分别写 子判断*2 个测试用例。如果这种条件式嵌在一个100行的方法里,你就需要为这N*2个测试用例准备上下文环境。只要不算太笨的程序员,很快就会发现最省事的办法是把这个复杂判断式抽出来作为一个独立的短方法。而对于管理者来说,这种方式很容易操作,不用苦口婆心地劝程序员们不要写长方法了。一段时间之后,程序员们就会自动养成倾向于写短方法的习惯。

当然为了达到85%以上的分支覆盖,必须把编写单元测试的时间也算到进度里。现在我们并不对单元测试的代码质量作很高的要求,编写单元测试的时间大概是写相应功能代码时间的四分之一到三分之一。

2. 鼓励程序员之间非正式的交叉代码审查。鼓励程序员在维护代码时,如果发现有可疑或者不明白的地方,通过看历史记录和Blame信息,找到可疑代码的原作者私底下咨询。

3. 鼓励使用Git作为本地代码库(公司的主代码库使用svn,通过Git-svn与本地库整合)。这个规则主要是为了避免一次性提交大量代码,保证保持详细的历史记录和Blame信息(Blame信息加上正确的命名规则可以取代大量不必要的代码内注释)。而且Git的Bisect功能也是排错的一把利器。


谢谢建议。

我想再问个问题,比如需求不明确或业务经常变,单元测试进行测试粒度适合吗?还是大部分是集成测试? 有没有考虑使用BDD开发?

能否问下你们是否进行自动化的单元测试/集成测试。
0 请登录后投票
   发表时间:2012-04-02  
jinnianshilongnian 写道
言日星极 写道
jinnianshilongnian 写道
言日星极 写道
最大的问题还是在于个人编程习惯,也就是格式化代码这块,使你的条件判断清晰起来,我一向都是要求我的组员按照我的这种方式来格式化代码,而不是一味的使用的alt+shift+f。
     if(
          saleOrderList.size() == 0
            &&
          saleOrderList.get(0).getOrderUuid <=0
            &&
          saleOrder.getOrder().getState() != OrderStateEnum.wait_pay.getType()) 
        ){
        
        ActionContext.getContext().put("orderUuid", saleOrderList.get(0).getOrderUuid());
        return "redirectToPay";     
     }


并不是一味追求重构,要善于利用重构里面的“招式”,像楼主那样之后的重构只是无疑导致代码另外一种坏味道——“过长函数”

以上仅仅是我个人的一点见解。



自动格式化我也不推荐,这种方式是死的!可能并不能很好的符合团队的习惯!

“过长函数” 我们定义是超过80行才是过长的函数

我想表达的不是谁的好谁的坏,而是如何保证所有队员都能按照一致的约定编程?如使用checkstyle等工具自动化的检查。想学习一下相关的经验。



按照这样的重构手法是已经有倾向过长函数的趋势了,对于过长函数的理解也不必显的那么死板,根据Martin Flower大师说明的“过长函数”,我加以自己的理解:即过长函数的本质不是指多少行数,而是每行代码表示的意思,即如何用最少的代码实现更多的功能。至于规范问题,我所在的公司每日都有代码走查,没按照规范都是推翻重写,这种事发生一两次大家就认真了。再者定义了接口,大家各自实现自己的模块。


这个是,不以代码行来评论过长函数! 但应该是不好理解的/表达不清晰的就应该提取函数===通过函数名来表达目的。  这个确实不好评判! 呵呵,只能仁者见仁 智者见智。 

你们都有代码走查啊,那开发人员使用相关自动化检查工具吗? 如checkstyle,findbugs等,有好经验吗?


你说的不错。我们使用checkStyle,无非也就是按照项目组的规范写相应的正则表达式等等,配置到AST环境中使用就行了,有些涉及到公司信息安全,我也不方便细说。我也不贴代码了。

ps:AST = "IBM WebSphere Application Server Toolkit" IBM在eclipse的基础上做的变种IDE
0 请登录后投票
   发表时间:2012-04-02  
言日星极 写道
jinnianshilongnian 写道
言日星极 写道
jinnianshilongnian 写道
言日星极 写道
最大的问题还是在于个人编程习惯,也就是格式化代码这块,使你的条件判断清晰起来,我一向都是要求我的组员按照我的这种方式来格式化代码,而不是一味的使用的alt+shift+f。
     if(
          saleOrderList.size() == 0
            &&
          saleOrderList.get(0).getOrderUuid <=0
            &&
          saleOrder.getOrder().getState() != OrderStateEnum.wait_pay.getType()) 
        ){
        
        ActionContext.getContext().put("orderUuid", saleOrderList.get(0).getOrderUuid());
        return "redirectToPay";     
     }


并不是一味追求重构,要善于利用重构里面的“招式”,像楼主那样之后的重构只是无疑导致代码另外一种坏味道——“过长函数”

以上仅仅是我个人的一点见解。



自动格式化我也不推荐,这种方式是死的!可能并不能很好的符合团队的习惯!

“过长函数” 我们定义是超过80行才是过长的函数

我想表达的不是谁的好谁的坏,而是如何保证所有队员都能按照一致的约定编程?如使用checkstyle等工具自动化的检查。想学习一下相关的经验。



按照这样的重构手法是已经有倾向过长函数的趋势了,对于过长函数的理解也不必显的那么死板,根据Martin Flower大师说明的“过长函数”,我加以自己的理解:即过长函数的本质不是指多少行数,而是每行代码表示的意思,即如何用最少的代码实现更多的功能。至于规范问题,我所在的公司每日都有代码走查,没按照规范都是推翻重写,这种事发生一两次大家就认真了。再者定义了接口,大家各自实现自己的模块。


这个是,不以代码行来评论过长函数! 但应该是不好理解的/表达不清晰的就应该提取函数===通过函数名来表达目的。  这个确实不好评判! 呵呵,只能仁者见仁 智者见智。 

你们都有代码走查啊,那开发人员使用相关自动化检查工具吗? 如checkstyle,findbugs等,有好经验吗?


你说的不错。我们使用checkStyle,无非也就是按照项目组的规范写相应的正则表达式等等,配置到AST环境中使用就行了,有些涉及到公司信息安全,我也不方便细说。我也不贴代码了。

ps:AST = "IBM WebSphere Application Server Toolkit" IBM在eclipse的基础上做的变种IDE

对头,今天你不休息? 我还在坚持上班 
0 请登录后投票
   发表时间:2012-04-02  
jinnianshilongnian 写道
言日星极 写道
jinnianshilongnian 写道
言日星极 写道
jinnianshilongnian 写道
言日星极 写道
最大的问题还是在于个人编程习惯,也就是格式化代码这块,使你的条件判断清晰起来,我一向都是要求我的组员按照我的这种方式来格式化代码,而不是一味的使用的alt+shift+f。
     if(
          saleOrderList.size() == 0
            &&
          saleOrderList.get(0).getOrderUuid <=0
            &&
          saleOrder.getOrder().getState() != OrderStateEnum.wait_pay.getType()) 
        ){
        
        ActionContext.getContext().put("orderUuid", saleOrderList.get(0).getOrderUuid());
        return "redirectToPay";     
     }


并不是一味追求重构,要善于利用重构里面的“招式”,像楼主那样之后的重构只是无疑导致代码另外一种坏味道——“过长函数”

以上仅仅是我个人的一点见解。



自动格式化我也不推荐,这种方式是死的!可能并不能很好的符合团队的习惯!

“过长函数” 我们定义是超过80行才是过长的函数

我想表达的不是谁的好谁的坏,而是如何保证所有队员都能按照一致的约定编程?如使用checkstyle等工具自动化的检查。想学习一下相关的经验。



按照这样的重构手法是已经有倾向过长函数的趋势了,对于过长函数的理解也不必显的那么死板,根据Martin Flower大师说明的“过长函数”,我加以自己的理解:即过长函数的本质不是指多少行数,而是每行代码表示的意思,即如何用最少的代码实现更多的功能。至于规范问题,我所在的公司每日都有代码走查,没按照规范都是推翻重写,这种事发生一两次大家就认真了。再者定义了接口,大家各自实现自己的模块。


这个是,不以代码行来评论过长函数! 但应该是不好理解的/表达不清晰的就应该提取函数===通过函数名来表达目的。  这个确实不好评判! 呵呵,只能仁者见仁 智者见智。 

你们都有代码走查啊,那开发人员使用相关自动化检查工具吗? 如checkstyle,findbugs等,有好经验吗?


你说的不错。我们使用checkStyle,无非也就是按照项目组的规范写相应的正则表达式等等,配置到AST环境中使用就行了,有些涉及到公司信息安全,我也不方便细说。我也不贴代码了。

ps:AST = "IBM WebSphere Application Server Toolkit" IBM在eclipse的基础上做的变种IDE

对头,今天你不休息? 我还在坚持上班 



没上班啊,刚吃完饭,逛逛论坛啥的。
0 请登录后投票
   发表时间:2012-04-02  
jinnianshilongnian 写道
kidneyball 写道
谈谈我们公司现在采用的办法(20人左右的开放团队):

1. 首次提交单元测试分支覆盖率(Branch Coverage)要达到80%以上(采用Maven的Cobertura插件来保证)。在后续的开发中,如果单元测试的分支覆盖率有所提高,则把数值调为实际值,只准增加不准减少。Team Leader定期检查pom.xml中的设置是否被队员意外调低。

有些人可能觉得这种方式太迂腐。不过它最大的好处是能有效地引导程序员把包含复杂分支结构的程序段抽成独立的方法。原因是,象楼主写的那种复杂条件判断,为了达到完全分支覆盖,你要分别写 子判断*2 个测试用例。如果这种条件式嵌在一个100行的方法里,你就需要为这N*2个测试用例准备上下文环境。只要不算太笨的程序员,很快就会发现最省事的办法是把这个复杂判断式抽出来作为一个独立的短方法。而对于管理者来说,这种方式很容易操作,不用苦口婆心地劝程序员们不要写长方法了。一段时间之后,程序员们就会自动养成倾向于写短方法的习惯。

当然为了达到85%以上的分支覆盖,必须把编写单元测试的时间也算到进度里。现在我们并不对单元测试的代码质量作很高的要求,编写单元测试的时间大概是写相应功能代码时间的四分之一到三分之一。

2. 鼓励程序员之间非正式的交叉代码审查。鼓励程序员在维护代码时,如果发现有可疑或者不明白的地方,通过看历史记录和Blame信息,找到可疑代码的原作者私底下咨询。

3. 鼓励使用Git作为本地代码库(公司的主代码库使用svn,通过Git-svn与本地库整合)。这个规则主要是为了避免一次性提交大量代码,保证保持详细的历史记录和Blame信息(Blame信息加上正确的命名规则可以取代大量不必要的代码内注释)。而且Git的Bisect功能也是排错的一把利器。


谢谢建议。

我想再问个问题,比如需求不明确或业务经常变,单元测试进行测试粒度适合吗?还是大部分是集成测试? 有没有考虑使用BDD开发?

能否问下你们是否进行自动化的单元测试/集成测试。


我们不是TDD,而是先写功能代码再补上测试用例的传统做法。只要你能保证拿到30%的额外时间(例如本来要三天完成一个小目标,现在要四天,其中一天用来写前三天所开发内容的单元测试),那么需求变化和粒度都是伪命题。不管需求怎么变,单元测试反正就是把你的进度拖慢30%左右(如果框架完善的话可能会更少),至于粒度,单元测试能达到的最大粒度就是分别100%行覆盖和分支覆盖,其实工作量也不会大很多,但实践上有总会有一些代码不宜测试(例如调用了框架的静态方法),一定要覆盖这些代码显得有些得不偿失。我个人觉得达到85%的行覆盖和分支覆盖就可以了,主要是迫使程序员写出便于测试的代码。

集成测试我们有专门的QA,据我所知他们也不用什么自动化工具(跨浏览器支持也不容易自动测),就是人手测试,主要技能是文档和沟通。这样的话回归测试比较麻烦,所以我们要求发版(大概一个半月到两个月发一次版)前两个星期建分支,停止向发版分支上提交新功能,发版前一个星期停止修改重大bug(作为known issue留到下一版本修正)。

单元测试肯定是自动化的,整合到maven build里每次构建都跑一遍。
0 请登录后投票
   发表时间:2012-04-02  
kidneyball 写道
jinnianshilongnian 写道
kidneyball 写道
谈谈我们公司现在采用的办法(20人左右的开放团队):

1. 首次提交单元测试分支覆盖率(Branch Coverage)要达到80%以上(采用Maven的Cobertura插件来保证)。在后续的开发中,如果单元测试的分支覆盖率有所提高,则把数值调为实际值,只准增加不准减少。Team Leader定期检查pom.xml中的设置是否被队员意外调低。

有些人可能觉得这种方式太迂腐。不过它最大的好处是能有效地引导程序员把包含复杂分支结构的程序段抽成独立的方法。原因是,象楼主写的那种复杂条件判断,为了达到完全分支覆盖,你要分别写 子判断*2 个测试用例。如果这种条件式嵌在一个100行的方法里,你就需要为这N*2个测试用例准备上下文环境。只要不算太笨的程序员,很快就会发现最省事的办法是把这个复杂判断式抽出来作为一个独立的短方法。而对于管理者来说,这种方式很容易操作,不用苦口婆心地劝程序员们不要写长方法了。一段时间之后,程序员们就会自动养成倾向于写短方法的习惯。

当然为了达到85%以上的分支覆盖,必须把编写单元测试的时间也算到进度里。现在我们并不对单元测试的代码质量作很高的要求,编写单元测试的时间大概是写相应功能代码时间的四分之一到三分之一。

2. 鼓励程序员之间非正式的交叉代码审查。鼓励程序员在维护代码时,如果发现有可疑或者不明白的地方,通过看历史记录和Blame信息,找到可疑代码的原作者私底下咨询。

3. 鼓励使用Git作为本地代码库(公司的主代码库使用svn,通过Git-svn与本地库整合)。这个规则主要是为了避免一次性提交大量代码,保证保持详细的历史记录和Blame信息(Blame信息加上正确的命名规则可以取代大量不必要的代码内注释)。而且Git的Bisect功能也是排错的一把利器。


谢谢建议。

我想再问个问题,比如需求不明确或业务经常变,单元测试进行测试粒度适合吗?还是大部分是集成测试? 有没有考虑使用BDD开发?

能否问下你们是否进行自动化的单元测试/集成测试。


我们不是TDD,而是先写功能代码再补上测试用例的传统做法。只要你能保证拿到30%的额外时间(例如本来要三天完成一个小目标,现在要四天,其中一天用来写前三天所开发内容的单元测试),那么需求变化和粒度都是伪命题。不管需求怎么变,单元测试反正就是把你的进度拖慢30%左右(如果框架完善的话可能会更少),至于粒度,单元测试能达到的最大粒度就是分别100%行覆盖和分支覆盖,其实工作量也不会大很多,但实践上有总会有一些代码不宜测试(例如调用了框架的静态方法),一定要覆盖这些代码显得有些得不偿失。我个人觉得达到85%的行覆盖和分支覆盖就可以了,主要是迫使程序员写出便于测试的代码。

集成测试我们有专门的QA,据我所知他们也不用什么自动化工具(跨浏览器支持也不容易自动测),就是人手测试,主要技能是文档和沟通。这样的话回归测试比较麻烦,所以我们要求发版(大概一个半月到两个月发一次版)前两个星期建分支,停止向发版分支上提交新功能,发版前一个星期停止修改重大bug(作为known issue留到下一版本修正)。

单元测试肯定是自动化的,整合到maven build里每次构建都跑一遍。


嗯,比如有个紧急任务需要下午上线,是后来再补上单元测试?还是有些直接不写? 你们是做产品?

单元测试肯定是自动化的,整合到maven build里每次构建都跑一遍 : 每次跑是不是太慢了,你们为嘛不使用持续集成服务器呢? 我们一起通过teamcity来做自动化测试,如果测试失败,发邮件通知
0 请登录后投票
   发表时间:2012-04-02  
jinnianshilongnian 写道
kidneyball 写道
jinnianshilongnian 写道
kidneyball 写道
谈谈我们公司现在采用的办法(20人左右的开放团队):

1. 首次提交单元测试分支覆盖率(Branch Coverage)要达到80%以上(采用Maven的Cobertura插件来保证)。在后续的开发中,如果单元测试的分支覆盖率有所提高,则把数值调为实际值,只准增加不准减少。Team Leader定期检查pom.xml中的设置是否被队员意外调低。

有些人可能觉得这种方式太迂腐。不过它最大的好处是能有效地引导程序员把包含复杂分支结构的程序段抽成独立的方法。原因是,象楼主写的那种复杂条件判断,为了达到完全分支覆盖,你要分别写 子判断*2 个测试用例。如果这种条件式嵌在一个100行的方法里,你就需要为这N*2个测试用例准备上下文环境。只要不算太笨的程序员,很快就会发现最省事的办法是把这个复杂判断式抽出来作为一个独立的短方法。而对于管理者来说,这种方式很容易操作,不用苦口婆心地劝程序员们不要写长方法了。一段时间之后,程序员们就会自动养成倾向于写短方法的习惯。

当然为了达到85%以上的分支覆盖,必须把编写单元测试的时间也算到进度里。现在我们并不对单元测试的代码质量作很高的要求,编写单元测试的时间大概是写相应功能代码时间的四分之一到三分之一。

2. 鼓励程序员之间非正式的交叉代码审查。鼓励程序员在维护代码时,如果发现有可疑或者不明白的地方,通过看历史记录和Blame信息,找到可疑代码的原作者私底下咨询。

3. 鼓励使用Git作为本地代码库(公司的主代码库使用svn,通过Git-svn与本地库整合)。这个规则主要是为了避免一次性提交大量代码,保证保持详细的历史记录和Blame信息(Blame信息加上正确的命名规则可以取代大量不必要的代码内注释)。而且Git的Bisect功能也是排错的一把利器。


谢谢建议。

我想再问个问题,比如需求不明确或业务经常变,单元测试进行测试粒度适合吗?还是大部分是集成测试? 有没有考虑使用BDD开发?

能否问下你们是否进行自动化的单元测试/集成测试。


我们不是TDD,而是先写功能代码再补上测试用例的传统做法。只要你能保证拿到30%的额外时间(例如本来要三天完成一个小目标,现在要四天,其中一天用来写前三天所开发内容的单元测试),那么需求变化和粒度都是伪命题。不管需求怎么变,单元测试反正就是把你的进度拖慢30%左右(如果框架完善的话可能会更少),至于粒度,单元测试能达到的最大粒度就是分别100%行覆盖和分支覆盖,其实工作量也不会大很多,但实践上有总会有一些代码不宜测试(例如调用了框架的静态方法),一定要覆盖这些代码显得有些得不偿失。我个人觉得达到85%的行覆盖和分支覆盖就可以了,主要是迫使程序员写出便于测试的代码。

集成测试我们有专门的QA,据我所知他们也不用什么自动化工具(跨浏览器支持也不容易自动测),就是人手测试,主要技能是文档和沟通。这样的话回归测试比较麻烦,所以我们要求发版(大概一个半月到两个月发一次版)前两个星期建分支,停止向发版分支上提交新功能,发版前一个星期停止修改重大bug(作为known issue留到下一版本修正)。

单元测试肯定是自动化的,整合到maven build里每次构建都跑一遍。


嗯,比如有个紧急任务需要下午上线,是后来再补上单元测试?还是有些直接不写? 你们是做产品?

单元测试肯定是自动化的,整合到maven build里每次构建都跑一遍 : 每次跑是不是太慢了,你们为嘛不使用持续集成服务器呢? 我们一起通过teamcity来做自动化测试,如果测试失败,发邮件通知


是做产品。既然紧急下午上线,肯定是先不写,修改pom.xml先exclude改动的class(但不能调低覆盖率限制,便于审查),后面再补上。一般没做单元测试的程序员自己开一条JIRA来记录需要补上的单元测试,然后把JIRA号写在pom.xml的提交comment里。Leader同步代码时发现pom.xml被改动但Comment里没有JIRA号,就会要求这个程序员自己补上。

单元测试运行速度目前还好,我们这边开发机的标配是intel i7+8G RAM+固态C盘,本地用git,一般都把代码clone到内存虚拟盘里build,全构建一次大概1分多钟(其实直接在C盘构建也差不多)。而且一般就是同步代码后build一次,其余时间都是增量构建,不用跑test了。开发环境的服务器(包括SVN)归基础架构部门管,我们开发这边一般就不理了,有啥就用啥……
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics