DEV Community

Anh Trần Tuấn
Anh Trần Tuấn

Posted on • Originally published at tuanh.net on

Package by Layer vs Package by Feature

1. What Is Package by Layer?

Package by Layer (PBL) is a traditional way of structuring a Java project. In this approach, classes are grouped by their technical role or responsibility. The typical layers include:

  • Controller Layer (handles HTTP requests and responses)
  • Service Layer (contains business logic)
  • Repository Layer (handles database interactions)

Image

By layering your packages this way, you separate the technical concerns, ensuring each layer has a clear responsibility.

1.1 Example of Package by Layer Structure

Here’s what a typical "Package by Layer" project structure might look like:

com.example.myapp
│
├── controller
│ ├── UserController.java
│ ├── OrderController.java
│   
├── service
│ ├── UserService.java
│ ├── OrderService.java
│   
├── repository
│ ├── UserRepository.java
│ ├── OrderRepository.java
Enter fullscreen mode Exit fullscreen mode

In this example, the classes are organized by their role in the application. Each package corresponds to a technical layer—controllers in one package, services in another, and repositories in a third.

1.2 Pros of Package by Layer

  • Simplicity : Especially for small projects, Package by Layer is intuitive and easy to follow. Developers can quickly understand the role of each class based on where it resides.
  • Consistency : When every layer is consistent across different features, the project maintains a uniform structure.
  • Separation of Concerns : Each layer focuses on a single responsibility, making the code easier to test and maintain.

1.3 Cons of Package by Layer

  • Scalability Issues : As the project grows, layers can become bloated. For example, a service package with 100+ classes is hard to navigate.
  • Tight Coupling : In large-scale applications, changes in the business logic can affect multiple layers, leading to tight coupling between layers.
  • Feature Management : It can be hard to identify where all the components related to a single feature are located, as they are spread across multiple layers.

1.4 When to Use Package by Layer

This approach works best for small to medium-sized applications or monolithic applications where the focus is on technical roles and the project structure is not expected to grow excessively. It’s also ideal for teams that prefer a more traditional, separation-of-concerns mindset.

2. What Is Package by Feature?

Package by Feature (PBF) takes a different approach: Instead of organizing classes by their role (controller, service, repository), they are grouped by functionality or feature. Each package represents a feature of the application, making it easier to manage features independently.

Image

2.1 Example of Package by Feature Structure

Here’s how a "Package by Feature" structure might look:

com.example.myapp
│
├── user
│ ├── UserController.java
│ ├── UserService.java
│ ├── UserRepository.java
│
├── order
│ ├── OrderController.java
│ ├── OrderService.java
│ ├── OrderRepository.java
Enter fullscreen mode Exit fullscreen mode

In this structure, each feature—such as "user" or "order"—gets its own package, containing all the necessary classes (controllers, services, repositories) for that specific feature.

2.2 Pros of Package by Feature

  • Feature Isolation : All components related to a feature are located together. This makes it easier to manage, modify, and extend features.
  • Scalability : The project structure scales well as new features are added. Instead of bloating existing layers, you create new packages for each feature.
  • Team Collaboration : For large teams working on different features, this approach simplifies collaboration. Each team can focus on their feature without interfering with other parts of the codebase.

2.3 Cons of Package by Feature

  • Learning Curve : Developers accustomed to the traditional Package by Layer approach might take time to adjust to this structure.
  • Technical Duplication : Sometimes, you might need to duplicate certain utility classes or configurations across feature packages, increasing redundancy.
  • Granularity : Deciding what counts as a "feature" can sometimes be subjective, leading to inconsistencies in package organization.

2.4 When to Use Package by Feature

Package by Feature is best suited for large, complex applications, especially those following microservice or modular architectures. It shines in scenarios where independent teams are responsible for different features, and the application is expected to evolve over time. It also works well in Agile environments where new features are frequently added.

3. Comparison Between Package by Layer and Package by Feature

Both approaches offer unique benefits, and choosing between them depends on the project’s requirements and the team’s needs.

Image

3.1 Scalability

  • Package by Layer : As the application grows, layers may become difficult to manage.
  • Package by Feature : Highly scalable; new features can be added without affecting the rest of the project structure.

3.2 Separation of Concerns

  • Package by Layer : Offers clean separation by technical roles (e.g., controllers, services), making each class’s responsibility clear.
  • Package by Feature : Separation by functionality allows for better feature management but may result in some redundancy.

3.3 Flexibility

  • Package by Layer : Easier for small teams or when the application scope is clear from the beginning.
  • Package by Feature : Ideal for larger teams and projects that are expected to evolve or scale.

4. Hybrid Approach: The Best of Both Worlds?

Some teams prefer a hybrid approach, blending the two methods. In this structure, the project is primarily organized by feature, but each feature can still have internal layers to separate concerns.

4.1 Hybrid Structure Example

com.example.myapp
│
├── user
│ ├── controller
│ │ ├── UserController.java
│ ├── service
│ │ ├── UserService.java
│ ├── repository
│ │ ├── UserRepository.java
│
├── order
│ ├── controller
│ │ ├── OrderController.java
│ ├── service
│ │ ├── OrderService.java
│ ├── repository
│ │ ├── OrderRepository.java
Enter fullscreen mode Exit fullscreen mode

In this example, the project is structured by feature, but within each feature, classes are still grouped by technical layer. This provides the advantages of both approaches—feature isolation and separation of concerns.

4.2 When to Use a Hybrid Approach

A hybrid approach works well in projects that need flexibility for scaling but also require a clear separation of concerns within each feature. It’s suitable for teams transitioning from a Package by Layer mindset to Package by Feature but not yet ready to fully commit to either.

5. Conclusion

Choosing between Package by Layer and Package by Feature isn’t about finding the "right" or "wrong" approach. It’s about understanding the nature of your project and your team’s needs. Small, straightforward applications might benefit from the simplicity of Package by Layer, while larger, feature-heavy applications thrive with Package by Feature. And for teams who want the best of both worlds, a hybrid approach offers flexibility and scalability.

Still unsure which approach fits your project best? Leave a comment below, and let’s discuss how to tailor your project structure to your specific needs!

Read posts more at : Package by Layer vs Package by Feature

Top comments (0)