逐包特征方法是否良好?

时间:2012-07-31 04:48:04

标签: java spring java-ee package-design

最近我偶然发现了这个关于java代码打包的javalobby帖子http://java.dzone.com/articles/how-changing-java-package

我喜欢这个想法,但我对这种方法几乎没有疑问。我问了我的问题,但没有得到满意的答复。我希望StackOverflow上的某个人可以澄清我的问题。

我喜欢逐个功能的想法,它可以大大减少编码时移动包的时间,所有相关的东西都在一个地方(包)。但是不同包中的服务之间的交互呢?

假设我们正在构建一个博客应用程序,我们将所有与用户相关的操作(控制器/服务/存储库)放在com.mycompany.myblog.users包中。以及com.mycompany.myblog.posts包中的所有博客文章相关操作(控制器/服务/存储库)。

现在我想显示用户个人资料以及他发布的所有帖子。我应该从myblog.posts.PostsService.getPostsByUser(userId)致电myblog.users.UserController.showUserProfile()吗?

包之间的耦合怎么样?

无论我在哪里阅读有关逐个功能的内容,每个人都说这是一个很好的做法。那么为什么许多书籍作者甚至框架都鼓励按层分组呢?只是好奇地知道: - )

3 个答案:

答案 0 :(得分:23)

看看鲍勃叔叔的Package Design Principles。他解释了这些原则背后的原因和动机,我在下面详细说明:

应该将重复使用的类打包在一起,以便可以将包视为一种可供您使用的完整产品。那些重复使用的应该与那些没有重复使用的那些分开。例如,您的日志记录实用程序类不一定与文件io类一起使用。所以打包所有记录它们分开。但是日志记录类可能彼此相关。因此,创建一种完整的日志记录产品,例如,为了更好的名称公共 - 将日志包装在一个(可重复使用的)jar中,另一个单独的完整产品用于io实用程序,再次为了更好的名称,比如公共 - io.jar。 如果你更新说commons-io库来说支持java nio,那么你可能不一定要对日志库进行任何更改。因此将它们分开会更好。

现在,假设您希望您的日志记录实用程序类支持结构化日志记录,以便通过splunk等工具进行某种日志分析。您的日志记录实用程序的某些客户端可能希望更新到您的新版本;其他人可能没有。因此,当您发布新版本时,请将所有需要的类打包并重复使用以进行迁移。因此,您的实用程序类的一些客户端可以安全地删除旧的commons-logging jar并移动到commons-logging-new jar。其他一些客户仍然可以使用旧罐子。但是,没有客户需要同时拥有这些罐子(新旧),只是因为你强迫他们为旧的包装jar使用一些类。

避免循环依赖。依赖于b; b; c;条件;但是d取决于a。这种情况显然是一种威慑,因为定义图层或模块等非常困难,而且你不能相互独立地改变它们。

此外,您可以打包您的类,以便在图层或模块更改时,其他模块或图层不必更改。因此,例如,如果您决定从旧的MVC框架转到其他API升级,那么只有视图和控制器可能需要更改;你的模型没有。

答案 1 :(得分:12)

除了用于包装设计的耦合之外还有许多其他方面我建议看一下OOAD原理,尤其是包装设计原理,如

REP释放重用等效原则重用的颗粒是释放的颗粒。

CCP共同关闭原则一起更改的类被打包在一起。

CRP共同重用原则将一起使用的类打包在一起。

ADP非循环依赖原则包的依赖关系图必须没有循环。

SDP稳定的依赖原则取决于稳定的方向。

SAP稳定的抽象原则抽象性随着稳定性的增加而增加。

有关详细信息,请参阅book“敏捷软件开发,原则,模式和实践”

答案 2 :(得分:11)

我个人喜欢“按功能打包”的方法,尽管你需要对绘制包边界的位置做出很多判断。在许多情况下,这当然是一种可行且明智的方法。

您应该使用公共接口实现包和模块之间的耦合 - 这样可以保持耦合的清洁和可管理性。

只要使用设计良好的公共界面,“博客帖子”包就可以调用“用户”包完全没问题。

如果你采用这种方法,可以提出一个很重要的建议:对你的依赖关系进行非常深思熟虑,特别是避免包之间的循环依赖。一个好的设计应该看起来像一个依赖树 - 具有更高级别的功能区域取决于一组依赖于效用函数库等的公共服务。在某种程度上,这将开始看起来像前面的架构“层”结束打包到后端服务的包。