Most of the enterprise Java applications share some similarities in their design. Mostly the packaging of these applications are driven by the framework used by them like Spring, EJBs or Hibernate etc. Alternatively you can group you packages by features. Like any other item regarding modeling this is not free from any issues. Lets discuss some trade-off and how get around them. In this post we will discuss the pros and cons of both approaches against common usage scenarios.
Package By Layer (PBL)
This is a the first thing that developers do when the create an enterprise application in to split it to number of layers like DAO, SERVICE, VIEW etc.. This gives nice
separation of code when we use different frameworks at different layers. For example if I were to use Hibernate, Spring and JSF, then I will have all my Hibernate dependent code in the DAO layer and JSF related code in the VIEW Layer. This is sort of good in case I need to migrate to a new framework only at the view layer or DAO Layer.
Package By Feature (PBF)
Package-by-feature uses packages to reflect the feature set. It places all items related to a single feature (and only that feature) into a single directory/package. This results in packages with high cohesion and high modularity, and with minimal coupling between packages. Items that work closely together are placed next to each other. They aren’t spread out all over the application. This also increases coherence as a large percentage of a the dependencies of a class are located close to that class.
Comparing the approaches
Let me compare both the approaches in below dimensions.
1. Adding a new Feature.
In case of PBL code has to be added to VIEW, SERVICE and DAO Layers and it can be tedious. PBF solves this problem by grouping all the code related to same feature in to a single directory.
2. Changing a framework used.
As discussed already PBL makes it easier to change a framework as all the related code are kept at same place. Here we know exactly the scope of the change and its impact. In case of PBF we need to dig into all the feature set to see the framework related classes. If you choose to migrate the framework module by module, then it could be argued that PBF is better than PBL.
3. Code Navigation.
As developers needs to work on the features most of the time using PBF is easier for code navigation. When you know exactly know what has to be done its not much advantage.
4. Keeping the Common Code.
Every application will have some components which will be reused across the features ie, the features are not always exclusive. In such case if we package all the features separately the interactions between them can be quite messy. As a general principle we need to reduce such interactions and increase the cohesion inside the package. We can get around the situation be adding such entities to a common package. This approach is used in many projects including Hibernate.
Most application will have 4 types of classes. ie,
- Domain Objects
- Business Services
- Data Retrieval Logic
- Data Representation Logic
If we use PBF it gives us a good structural representation but does not give any functional representation. We need our architecture to resemble the problem domain. So its better to use Package By Feature style. We could internally classify the classes by using naming conventions like MyFeatureDAO or MyFeatureService . This way we could communicate the intend of the classes.
I have found some discussions on this topic and hope that might also help you choose.
- Java Practices Article
- Lessons to Learn from the Hibernate Core Implementation
- How Changing Java Package Names Transformed my System Architecture
- Presentation By Kostis Kapelonis
- The Principles of OOD By Uncle Bob
- Article says its Better to Use Package By Layer
- Question on SO Is package by feature approach good?
Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code
Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!
To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.