另一种风格是按特征划分命名:
com.blah.painting
com.blah.buyer
com.blah.seller
com.blah.auction
com.blah.webmaster
com.blah.useraccess
com.blah.util
这里,成员不按行为划分,而是按照不同特征的类划分,每个成员都关联不同的特征。这种方法下包在最初使用是被定义。
例如:在Web应用程序中,“com.blah.painting”包可能由下列成员组成:
Painting.java: 一个model对象
PaintingDAO.java: 一个数据存取对象Dao
PaintingAction.java: 一个控制或者行为对象
statements.sql: Dao对象使用的SQl文件
view.jsp: Jsp文件
需要特别说是的是,这种划分方法,每一个包都包含所有成员有关的特征文件,而不仅仅是Java源文件。这种按特征划分包的方法,要求在做删除操作时要注意,删除一个特征时要删掉它的整个目录,不能保存在源码中。
这种方法优于按层次划分包的方法,表现在以下几点:
● 包是高内聚的,并且模块化,包与包之间的耦合性被降到最低。
● 代码的自描述性增强. 读者只需看包的名字就对程序有些什么功能或特征有了大概的印象。在《代码大全》中, Steve McConnell 将自描述性的代码比作 "易读的圣杯",来表达它的易读性。
● 把类按照每个特征和功能区分开可以很容易实现分层设计。
● 相关的成员在同一个位置。不需要为了编辑一个相关的成员而去浏览整个源码树。
● 成员的作用域默认是包内私有。只有当另外的包需要访问某个成员的时候,才把它修改为public. (需要注意的是修改一个类为public,并不意味着它的所有类成员都应该改为public。public成员和包内私有(package- private)成员是可以在同一个类里共存的。)
● 删除一个功能或特征只需要简单的删除一个文件夹。
● 每个包内一般只有很少的成员,这样包可以很自然的按照进化式发展。如果包慢慢变的太大,就可以再进行细分,把它重构为两个或者更多新的包,类似于物种进化。而按照层次划分的方式,就没办法进化式发展,重构也不容易。
一些框架推荐使用层层定义包的传统的方式做为包的命名方法:由于使用传统的包命名,开发者总能知道在哪个位置可以找到这些项目,但是为什么避免人们这样做呢?使用另一种按特征定义包的风格,就不需要这种单调的操纵,因此,按特征定义完全超越了任何其它命名约定。约书亚布洛赫在《高效的Java》一书中说到:区分一个设计好坏的唯一重要因素是模块内部隐藏的数据和其它模块中涉及的实现过程的程度。