java 按功能打包的方法好吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11733267/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is package by feature approach good?
提问by K. Siva Prasad Reddy
Recently I came across this javalobby post http://java.dzone.com/articles/how-changing-java-packageon packaging java code by feature.
最近我遇到了这篇关于按功能打包 java 代码的javalobby 帖子http://java.dzone.com/articles/how-change-java-package。
I like the idea, but i have few questions on this approach. I asked my question but didn't get a satisfactory reply. I hope someone on StackOverflow can clarify my questions.
我喜欢这个想法,但我对这种方法几乎没有疑问。我问了我的问题,但没有得到满意的答复。我希望 StackOverflow 上的某个人可以澄清我的问题。
I like the idea of package by feature which greately reduces the time for moving across the packages while coding and all the related stuff will be at one place(package). But what about interactions between the services in different packages?
我喜欢按功能打包的想法,它极大地减少了在编码时跨包移动的时间,并且所有相关的东西都将在一个地方(包)。但是不同包中的服务之间的交互呢?
Suppose we are building a blog app and we are putting all user related operations(controllers/services/repositories) in com.mycompany.myblog.users
package. And all blog post related operations(controllers/services/repositories) in com.mycompany.myblog.posts
package.
假设我们正在构建一个博客应用程序,并将所有与用户相关的操作(控制器/服务/存储库)放在com.mycompany.myblog.users
包中。以及所有与博客文章相关的操作(控制器/服务/存储库)com.mycompany.myblog.posts
。
Now I want to show User Profile along with all the posts that he posted. Should I call myblog.posts.PostsService.getPostsByUser(userId)
from myblog.users.UserController.showUserProfile()
?
现在我想显示用户个人资料以及他发布的所有帖子。我应该叫myblog.posts.PostsService.getPostsByUser(userId)
从myblog.users.UserController.showUserProfile()
?
What about coupling between packages?
包之间的耦合呢?
Also wherever I read about package by feature, everyone says its a good practice. Then why many book authors and even frameworks encourage to group by layers? Just curious to know :-)
此外,无论我在哪里阅读按功能打包的内容,每个人都说这是一个很好的做法。那为什么很多书作者甚至框架都鼓励按层分组呢?只是想知道:-)
采纳答案by Atul
Take a look at uncle Bob's Package Design Principles. He explains reasons and motivations behind those principles, which I have elaborated on below:
看看大叔鲍勃的包装设计原则。他解释了这些原则背后的原因和动机,我在下面进行了详细说明:
Classes that get reused together should be packaged together so that the package can be treated as a sort of complete product available for you. And those which are reused together should be separated away from the ones those are not reused with. For example, your Logging utility classes are not necessarily used together with your file io classes. So package all logging them separately. But logging classes could be related to one another. So create a sort of complete product for logging, say, for the want of better name commons-logging package it in a (re)usable jar and another separate complete product for io utilities, again for the want of better name, say commons-io.jar. If you update say commons-io library to say support java nio, then you may not necessarily want to make any changes to the logging library. So separating them is better.
一起重用的类应该打包在一起,以便可以将包视为一种可供您使用的完整产品。一起重用的和不一起重用的要分开。例如,您的 Logging 实用程序类不一定与文件 io 类一起使用。因此,将所有日志记录单独打包。但是日志记录类可能彼此相关。因此,创建一种用于日志记录的完整产品,例如,为了获得更好的名称 commons-logging 将其打包在一个(可重复使用的)jar 和另一个用于 io 实用程序的单独完整产品中,同样是为了获得更好的名称,比如 commons- io.jar。如果您更新 say commons-io 库以说支持 java nio,那么您可能不一定要对日志记录库进行任何更改。所以分开比较好。
Now, let's say you wanted your logging utility classes to support structured logging for say some sort of log analysis by tools like splunk. Some clients of your logging utility may want to update to your newer version; some others may not. So when you release a new version, package all classes which are needed and reused together for migration. So some clients of your utility classes can safely delete your old commons-logging jar and move to commons-logging-new jar. Some other clients are still ok with older jar. However no clients are needed to have both these jars (new and old) just because you forced them to use some classes for older packaged jar.
现在,假设您希望日志实用程序类支持结构化日志记录,例如通过 splunk 等工具进行某种日志分析。您的日志实用程序的某些客户端可能想要更新到您的较新版本;有些人可能不会。因此,当您发布新版本时,请将所有需要的类打包并一起重用以进行迁移。因此,您的实用程序类的某些客户端可以安全地删除旧的 commons-logging jar 并移动到 commons-logging-new jar。其他一些客户仍然可以使用较旧的 jar。但是,客户端不需要同时拥有这两个 jar(新的和旧的),因为您强迫它们对旧的打包 jar 使用某些类。
Avoid cyclic dependencies. a depend on b; b on c; c on d; but d depends on a. The scenario is obviously deterring as it will be very difficult to define layers or modules, etc and you cannot vary them independly relative to each other.
避免循环依赖。a 依赖于 b;b 对 c;条件; 但 d 取决于 a。这种情况显然令人望而却步,因为定义层或模块等将非常困难,并且您不能相对于彼此独立地改变它们。
Also, you could package your classes such that if a layer or module changes, other module or layers do not have to change necessarily. So, for example, if you decide to go from old MVC framework to a rest APIs upgrade, then only view and controller may need changes; your model does not.
此外,您可以打包您的类,这样如果一个层或模块发生变化,其他模块或层就不必更改。因此,例如,如果您决定从旧的 MVC 框架升级到其余 API,那么可能只有视图和控制器需要更改;你的模型没有。
回答by Jigar Parekh
There many other aspect other than coupling for package design i would suggest to look at OOAD Priciples, especially package design priciples like
除了包装设计的耦合之外,还有许多其他方面我建议查看 OOAD Priciples,尤其是包装设计原则,例如
REP The Release Reuse Equivalency PrincipleThe granule of reuse is the granule of release.
REP Release Reuse Equivalency Principle重用颗粒就是释放颗粒。
CCP The Common Closure PrincipleClasses that change together are packaged together.
CCP Common Closure Principle Principle一起变化的类被打包在一起。
CRP The Common Reuse PrincipleClasses that are used together are packaged together.
CRP 将共同使用的通用重用原则类打包在一起。
ADP The Acyclic Dependencies PrincipleThe dependency graph of packages must have no cycles.
ADP 无环依赖原则包的依赖图必须没有循环。
SDP The Stable Dependencies PrincipleDepend in the direction of stability.
SDP 稳定依赖原则依赖于稳定的方向。
SAP The Stable Abstractions PrincipleAbstractness increases with stability.
SAP 稳定抽象原则抽象性随着稳定性的增加而增加。
for more information you can read book"Agile Software Development, Principles, Patterns, and Practices"
有关更多信息,你可以阅读的书“敏捷软件开发,原则,模式与实践”
回答by mikera
I personally like the "package by feature" approach, although you do need to apply quite a lot of judgement on where to draw the package boundaries. It's certainly a feasible and sensible approach in many circumstances.
我个人喜欢“按功能打包”的方法,尽管您确实需要对在何处绘制包边界进行大量判断。在许多情况下,这当然是一种可行且明智的方法。
You should probably achieve coupling between packages and modules using public interfaces - this keeps the coupling clean and manageable.
您可能应该使用公共接口实现包和模块之间的耦合——这可以保持耦合的整洁和可管理。
It's perfectly fine for the "blog posts" package to call into the "users" package as long as it uses well designed public interfaces to do so.
只要“博客帖子”包使用设计良好的公共接口来调用“用户”包,就完全没问题。
One big piece of advice though if you go down this approach: be very thoughtful about your dependencies and in particular avoid circular dependenciesbetween packages. A good design should looks like a dependency tree - with the higher level areas of functionality depending on a set of common services which depend upon libraries of utility functions etc. To some extent, this will start to look like architectural "layers" with front-end packages calling into back-end services.
但是,如果您采用这种方法,那么一个重要的建议是:对您的依赖关系非常周到,尤其要避免包之间的循环依赖关系。一个好的设计应该看起来像一个依赖树 - 更高级别的功能区域取决于一组依赖于实用功能库等的公共服务。在某种程度上,这将开始看起来像具有前端的架构“层”-调用后端服务的结束包。