PMD检查

3 views
Skip to first unread message

Peter Tung

unread,
Oct 12, 2009, 7:44:19 AM10/12/09
to nutzam
我用PMD查了一下代码, 在下载里面, 能够看到1级和2级的警报.
1,2级表示高危......

可以看看里面报出的问题, 点击链接可以看到问题的详细解释.
很多问题是可以回避的.

Wendal Chen

unread,
Oct 12, 2009, 8:08:47 AM10/12/09
to nut...@googlegroups.com
哦? 你打算加上这些代码检查工具吗?
我不久前才帮公司的一个项目搭建自动构建服务, 里面使用PMD,Findbug,CPD,CheckStyle等

2009/10/12 Peter Tung <mas...@gmail.com>

张志昊

unread,
Oct 12, 2009, 8:26:23 AM10/12/09
to nut...@googlegroups.com
我曾经用 FindBug 查过一次,有些问题我认为不是问题,又懒得研究 FindBug 的规则,所以我就把 FindBug 卸载了
TH 
你帮忙总结一下,用哪些工具检查代码比较好。先贴几个高危的例子看看。
总之 Code Review 的工作,你来领导吧,我们听你的

zozoh

2009/10/12 Wendal Chen <wenda...@gmail.com>



--
    Best Regard

zozoh @ 2009
-----------------------------------------

唐浩

unread,
Oct 12, 2009, 12:19:06 PM10/12/09
to nut...@googlegroups.com
为什么很多代码都是直接从虚类继承, 而不是从接口呢? 比如: Pager
这样的设计怎么考虑的? 我认为这违反了基于接口设计的原则.

这样会有碍团队协作.比如:
1. 我想研究一下代码, 我看到的是虚类, 但是我并不知道虚类之间, 哪些方法是契约方法, 哪些不是. 徒增了我看代码的量, 因为最开始, 我可能只是想从整个大架构开始.
2. 由于很多是虚类, 如果我想自己实现一个子类的话, 我并不知道, 到底我需要实现多少方法才算完.
3. 同时, 很多虚类里面的方法, 直接返回的null什么的, 在PMD里面, 建议是直接抽象该方法的. 不然, 很多的继承类, 会忘记实现这个方法. 但是, 很可能这个方法是不可用的.(这也说明接口的必要性)

加一个PMD的规则
比如有这么一个规则: ConstructorCallsOverridableMethod
http://pmd.sourceforge.net/rules/design.html#ConstructorCallsOverridableMethod

如果我有继承类, 实现了:
Application的addCmd
FileSqlManger的refresh
...
我检查了这些方法, 都只在构造的时候被调用了, 所以, 外部不用的话, private them.

2009/10/12 张志昊 <zozo...@gmail.com>

张志昊

unread,
Oct 13, 2009, 12:14:59 AM10/13/09
to nut...@googlegroups.com


2009/10/13 唐浩 <mas...@gmail.com>

为什么很多代码都是直接从虚类继承, 而不是从接口呢? 比如: Pager
这样的设计怎么考虑的? 我认为这违反了基于接口设计的原则.
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 继承的好处是,如果子类大多类似,只是某些具体的行为有点偏差,那么继承一个共同的父类,可以共享很多代码,非常划得来。 我程序设计的原则只有一个:代码写的少。
至于是不是要继承,还是实现接口,如果继承能让我代码少很多,我就会用继承。
具体到 Pager, 我通过继承,让子类完成不同数据库特殊的分页方式。 而父类则编写和数据库无关的代码即可。暂时,我还想不到更好的结构,让这簇代码变的更少。
如果你增加一个 Pager 的接口,哇,我估计代码又会变多一些吧。
---------------------------------------------------------------------------------------------------------------------------------------------

这样会有碍团队协作.比如:
1. 我想研究一下代码, 我看到的是虚类, 但是我并不知道虚类之间, 哪些方法是契约方法, 哪些不是. 徒增了我看代码的量, 因为最开始, 我可能只是想从整个大架构开始.
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 虚类的原则就是: 继承的子类一定会对。  就是说,我在虚类里写一个虚方法。你子类只要把这个虚方法实现正确,你就正确了
需方法需要详实的注释。 这样你看虚类代码就行了,基本不太需要仔细看子类代码。 当然,我现在代码里,虚类通常是没有注释的。
另: 啥叫 ”契约方法“ 啊?
--------------------------------------------------------------------------------------------------------------------------------------------- 
2. 由于很多是虚类, 如果我想自己实现一个子类的话, 我并不知道, 到底我需要实现多少方法才算完.
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 理想的虚类设计应该做到这个效果: 通过 Eclipse New Class 的对话框,生成的子类,会自动填充虚方法的实现。你把这些实现写完,你的虚类就完成了。
---------------------------------------------------------------------------------------------------------------------------------------------  
3. 同时, 很多虚类里面的方法, 直接返回的null什么的, 在PMD里面, 建议是直接抽象该方法的. 不然, 很多的继承类, 会忘记实现这个方法. 但是, 很可能这个方法是不可用的.(这也说明接口的必要性)
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 能举个具体的类吗?  写个方法返回 null 的确不太友好。 我通常是,如果子类 A,B,C  。 A,B 需要返回 null,C 需要返回别的。 我一般会把这个方法写在父类里
让 C 来重载即可。 这样做有点不好。所以一般是我假设你不会继承的那些实现类,我会这么做。如果我开发给使用者继承的类,则不会这么做的。
实际上,我要开放给使用者扩展,通常会用接口。 个别的会有虚类,比如 Pager
---------------------------------------------------------------------------------------------------------------------------------------------   

加一个PMD的规则
比如有这么一个规则: ConstructorCallsOverridableMethod
http://pmd.sourceforge.net/rules/design.html#ConstructorCallsOverridableMethod

如果我有继承类, 实现了:
Application的addCmd
FileSqlManger的refresh
...
我检查了这些方法, 都只在构造的时候被调用了, 所以, 外部不用的话, private them.
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 这两个函数帮助使用者把他的程序变得更动态的。
你可以再运行时,为你的 Application 添加/移除命令,这个会不会很酷?
在运行时,你可以修改你的 SQL 文件,然后用 dao.sqls().refresh() , 就能得到修改的内容。这个会不会有用呢?
---------------------------------------------------------------------------------------------------------------------------------------------   
 

2009/10/12 张志昊 <zozo...@gmail.com>
我曾经用 FindBug 查过一次,有些问题我认为不是问题,又懒得研究 FindBug 的规则,所以我就把 FindBug 卸载了
TH 
你帮忙总结一下,用哪些工具检查代码比较好。先贴几个高危的例子看看。
总之 Code Review 的工作,你来领导吧,我们听你的

zozoh

2009/10/12 Wendal Chen <wenda...@gmail.com>

哦? 你打算加上这些代码检查工具吗?
我不久前才帮公司的一个项目搭建自动构建服务, 里面使用PMD,Findbug,CPD,CheckStyle等

2009/10/12 Peter Tung <mas...@gmail.com>

我用PMD查了一下代码, 在下载里面, 能够看到1级和2级的警报.
1,2级表示高危......

可以看看里面报出的问题, 点击链接可以看到问题的详细解释.
很多问题是可以回避的.









--
    Best Regard

zozoh @ 2009
-----------------------------------------





唐浩

unread,
Oct 13, 2009, 3:45:25 AM10/13/09
to nut...@googlegroups.com


2009/10/13 张志昊 <zozo...@gmail.com>



2009/10/13 唐浩 <mas...@gmail.com>

为什么很多代码都是直接从虚类继承, 而不是从接口呢? 比如: Pager
这样的设计怎么考虑的? 我认为这违反了基于接口设计的原则.
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 继承的好处是,如果子类大多类似,只是某些具体的行为有点偏差,那么继承一个共同的父类,可以共享很多代码,非常划得来。 我程序设计的原则只有一个:代码写的少。
至于是不是要继承,还是实现接口,如果继承能让我代码少很多,我就会用继承。
具体到 Pager, 我通过继承,让子类完成不同数据库特殊的分页方式。 而父类则编写和数据库无关的代码即可。暂时,我还想不到更好的结构,让这簇代码变的更少。
如果你增加一个 Pager 的接口,哇,我估计代码又会变多一些吧。
---------------------------------------------------------------------------------------------------------------------------------------------

这样会有碍团队协作.比如:
1. 我想研究一下代码, 我看到的是虚类, 但是我并不知道虚类之间, 哪些方法是契约方法, 哪些不是. 徒增了我看代码的量, 因为最开始, 我可能只是想从整个大架构开始.
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 虚类的原则就是: 继承的子类一定会对。  就是说,我在虚类里写一个虚方法。你子类只要把这个虚方法实现正确,你就正确了
需方法需要详实的注释。 这样你看虚类代码就行了,基本不太需要仔细看子类代码。 当然,我现在代码里,虚类通常是没有注释的。
另: 啥叫 ”契约方法“ 啊?
--------------------------------------------------------------------------------------------------------------------------------------------- 
[th]: "契约方法"就是本应该定义在接口里面, 和其他的程序约定的. 你不定义那些方法将会被外部调用, 而基本上方法都是public, 我哪里知道, 到底有多少方法是属于和其他类交互的, 多少方法不是. 比如下面提到的addCmd和refresh. 我在项目的代码里面没有发现其他类用到. 我本能的认为就是内部方法了.

2. 由于很多是虚类, 如果我想自己实现一个子类的话, 我并不知道, 到底我需要实现多少方法才算完.
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 理想的虚类设计应该做到这个效果: 通过 Eclipse New Class 的对话框,生成的子类,会自动填充虚方法的实现。你把这些实现写完,你的虚类就完成了。
[th]:是呀, 我知道. 但是, 你也没有遵循这样的原则. 举个例子: Pager里面,
    protected abstract String getLimitString(Entity<?> entity);

    public String getResultSetName(Entity<?> entity) {
        return null;
    }
这2个方法我认为都是虚方法....... 都应该在子类实现的. 可是, 我不确定还有多少没有abstract的需要我自己来实现. 我得看你的代码. 这就是问题.
---------------------------------------------------------------------------------------------------------------------------------------------  
3. 同时, 很多虚类里面的方法, 直接返回的null什么的, 在PMD里面, 建议是直接抽象该方法的. 不然, 很多的继承类, 会忘记实现这个方法. 但是, 很可能这个方法是不可用的.(这也说明接口的必要性)
--------------------------------------------------------------------------------------------------------------------------------------------- 
[zzh:] 能举个具体的类吗?  写个方法返回 null 的确不太友好。 我通常是,如果子类 A,B,C  。 A,B 需要返回 null,C 需要返回别的。 我一般会把这个方法写在父类里
让 C 来重载即可。 这样做有点不好。所以一般是我假设你不会继承的那些实现类,我会这么做。如果我开发给使用者继承的类,则不会这么做的。
实际上,我要开放给使用者扩展,通常会用接口。 个别的会有虚类,比如 Pager
[th]:见上面的例子. 哦. 这么说来, 就是差文档了, 如果不用开发给使用者扩展的, 建议, 类加上final, 其他人也就少折腾了.

唐浩

unread,
Oct 13, 2009, 4:20:46 AM10/13/09
to nut...@googlegroups.com
我觉得哈, 可以看看这2篇, 我刚找了找~~
说得和总结得比我好:
http://developer.51cto.com/art/200909/151932.htm
http://bulargy.javaeye.com/blog/167618

2009/10/13 唐浩 <mas...@gmail.com>

唐浩

unread,
Oct 13, 2009, 4:32:03 AM10/13/09
to nut...@googlegroups.com
给点英文的, 当然哈, 这些是我在学校学的~~
书本上的东西, 不一定适用的~
老师一直念叨着的5个原则:
http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod


2009/10/13 唐浩 <mas...@gmail.com>

唐浩

unread,
Oct 13, 2009, 4:53:46 AM10/13/09
to nut...@googlegroups.com
不好意思, 在infoQ上看到了视频~~
觉得很爽, 分享一下.
http://www.infoq.com/presentations/principles-agile-oo-design

2009/10/13 唐浩 <mas...@gmail.com>

张志昊

unread,
Oct 13, 2009, 12:43:31 PM10/13/09
to nut...@googlegroups.com
看了视频,“老爹” 的演讲很不错啊,虽然部分听不大懂:
写上读后感:
====================================================================
Add function by new code
 -- 依靠抽象层做到这一点

软件中的任何问题,都可以通过增加一个中间层来解决
何时构建这个中间层是一个难于抉择的问题
* 增加这个中间层会让程序变得复杂
* 抚平这个中间层会让程序变得僵硬
* 程序设计中的奥妙尽在于此
所谓 OO 不过是构建中间层的一种思考方式
* 面向对象的编程语言,提供了更多的中间层的形式
* 函数式编程,让你构建更细碎的中间层成为可能
Class 改变的唯一理由,是要变成一个中间层
* 重构就是重写,不过用旧代码检验测试用例,用测试用例来检验新代码
经典:软件工程的一切思想就是为了做到:只写一次
延伸:算法设计的一切公式就是为了做到:只跑一次
====================================================================

2009/10/13 唐浩 <mas...@gmail.com>

张志昊

unread,
Oct 13, 2009, 12:51:35 PM10/13/09
to nut...@googlegroups.com
在这里,我总结一下 Nutz 的编码原则:

在不影响阅读的前提下,代码行数越少越好,变量名,类名,包名越短越好
Nutz 每次主版本号变化(现在是 1.x),就意味着代码重写(不是重构)
在不改变功能的前提下作的代码修改,修改后的代码必须比修改前的代码更精练
在此基础上,修改多少代码都成,只要通过 JUnit 测试。

zozoh

2009/10/14 张志昊 <zozo...@gmail.com>

zozoh

unread,
Oct 13, 2009, 2:20:20 PM10/13/09
to nutzam
public String getResultSetName(Entity<?> entity) {
return null;
}

这个方法似乎是没用了,我似乎是在一次重构以后忘记删除了 :P

Reply all
Reply to author
Forward
0 new messages