The Package by Feature approach

The Package by FeatureΒ approach

β€’4 min read
The Package by Feature approach

How it can help you build scalable and manageable projects.How it can help you build scalable and manageable projects.Photo byBoliviaInteligenteonUnsplash

Introduction

Modularization is the process in software development that involves breaking down a system into smaller, manageable, and independent components or modules to improve maintainability and reusability.

Let's dive into some techniques. πŸš€

Package by layer

The Package by Layer structure is an architectural design pattern used in software development that organizes code files into separate layers, with each layer representing a specific functionality or responsibility within the application. Typically, these layers include the presentation layer (user interface), application layer (business logic), domain layer (domain-specific logic), and infrastructure layer (database and external services).

Check the example bellow.

.β”œβ”€β”€ src
 β”œβ”€β”€ controllers
 β”œβ”€β”€  β”œβ”€β”€ CompanyController
 β”œβ”€β”€  β”œβ”€β”€ CustomerController
 β”œβ”€β”€  └── ProductController
 β”œβ”€β”€ entities
 β”œβ”€β”€  β”œβ”€β”€ CompanyEntity
 β”œβ”€β”€  β”œβ”€β”€ CustomerEntity
 β”œβ”€β”€  └── ProductEntity
 β”œβ”€β”€ repositories
 β”œβ”€β”€  β”œβ”€β”€ CompanyRepository
 β”œβ”€β”€  β”œβ”€β”€ CustomerRepository
 β”œβ”€β”€  └── ProductRepository
 β”œβ”€β”€ services
 β”œβ”€β”€  β”œβ”€β”€ CompanyService
 β”œβ”€β”€  β”œβ”€β”€ CustomerService
 β”œβ”€β”€  └── ProductService
 β”œβ”€β”€ dtos
 β”œβ”€β”€  β”œβ”€β”€ CompanyDTO
 β”œβ”€β”€  β”œβ”€β”€ CustomerDTO
 β”œβ”€β”€  └── ProductDTO
 β”œβ”€β”€ daos
 β”œβ”€β”€  β”œβ”€β”€ CompanyDAO
 β”œβ”€β”€  β”œβ”€β”€ CustomerDAO
 β”œβ”€β”€  └── ProductDAO
 └── utils

The problems behind this approach

This approach brings some problems, including the high coupling and low cohesion.

  • Cohesion: It refers to the degree of logical relationship of package members to each other. High relationship between members ensures package independence. Low cohesion not only reduces independence but also significantly reduces reusability and understandability.
  • Coupling: It refers to the degree of interdependence between packages/classes. Low coupling significantly increases maintainability. How? Since changes made within a class due to the requirements will not affect other classes, side effects do not occur and maintenance becomes easier.

Also, we have a poor overview of all classes that belong to a feature and tendency to generic, reused and complex code, which is hard to understand and changes can easily break other use cases as the impact of a change is hard to grasp.

Package by feature

In this project structure, packages contain all classes that are required for a feature. The independence of the package is ensured by placing closely related classes in the same package. An example of this structure is given below:

.β”œβ”€β”€ src
 β”œβ”€β”€ company
 β”œβ”€β”€  β”œβ”€β”€ CompanyController
 β”œβ”€β”€  β”œβ”€β”€ CompanyEntity
 β”œβ”€β”€  β”œβ”€β”€ CompanyRepository
 β”œβ”€β”€  β”œβ”€β”€ CompanyService
 β”œβ”€β”€  β”œβ”€β”€ CompanyDTO
 β”œβ”€β”€  └── CompanyDAO
 β”œβ”€β”€ customer
 β”œβ”€β”€  β”œβ”€β”€ CustomerController
 β”œβ”€β”€  β”œβ”€β”€ CustomerEntity
 β”œβ”€β”€  β”œβ”€β”€ CustomerRepository
 β”œβ”€β”€  β”œβ”€β”€ CustomerService
 β”œβ”€β”€  β”œβ”€β”€ CustomerDTO
 β”œβ”€β”€  └── CustomerDAO
 β”œβ”€β”€ product
 β”œβ”€β”€  β”œβ”€β”€ ProductController
 β”œβ”€β”€  β”œβ”€β”€ ProductEntity
 β”œβ”€β”€  β”œβ”€β”€ ProductRepository
 β”œβ”€β”€  β”œβ”€β”€ ProductService
 β”œβ”€β”€  β”œβ”€β”€ ProductDTO
 β”œβ”€β”€  └── ProductDAO
 └──  └── utils

This structure removes the need for one package's class to rely on another package's class. It also ensures that the classes in the packages have strong associations with each other. Thus, there is high cohesion within packages and low coupling between packages.

In addition, this structure provides higher modularity. But how?

Let's assume there are 10 more domains, not just Company, Product and Customer. In the Package by Layer, Controllers, Services, and Repositories are placed in different single packages, so the whole application consists of three packagesβ€Šβ€”β€Šexcept utilsβ€Šβ€”β€Šand packages have a large number of members. However, in the Package by Feature style, the same application consists of 13 packages and thus, modularity is increased.

If a feature can be deleted in a single action, the application has maximum modularity.Advantages

  • Package by Feature has packages with high cohesion, low coupling and high modularity.
  • Package by Feature allows some classes to set their access modifier package-private instead of public, so it increases encapsulation. On the other hand, Package by Layer forces you to set nearly all classes public.
  • Package by Feature reduces the need to navigate between packages since all classes needed for a feature are in the same package.
  • Package by Feature is like microservice architecture. Each package is limited to classes related to a particular feature. On the other hand, Package By Layer is monolithic. As an application grows in size, the number of classes in each package will increase without bound.
  • Package by Feature offers better discoverability and overview from the domain point of view. Most of the code that belongs to a business feature is located together. This is crucial because we are approaching a codebase usually with a certain business requirement in mind.
  • Most of the code that a feature needs, is located in the package. So we are avoiding dependencies to other feature packages.
  • As we are avoiding generic and abstracted code, the code becomes simpler because it only has to handle a single use-case. Hence, it's easier to understand and to evolve the code.
  • Usually, a class in a feature package has fewer dependencies compared to a β€œgod-class” in a technical package that tries to fulfill all use-cases. So testing becomes easier as we have to create less test fixture.

The common things

One point of attention is the shared resources, like the utils directory, which contains files shared across the application. This is where we will have components, utilities, constants, and other resources that can be part of one or more features.

Conclusion

The Package by Feature makes the development process more organized and scalable, as each module can be developed, tested, and maintained independently. Additionally, the modularization promotes code reusability, simplifies debugging, and facilitates collaboration among team members, leading to increased overall productivity and efficiency.

References

Vitor Britto
Buy Me A Coffee
Senior Software Engineer

Hello, I'm Vitor Britto πŸ‘‹

With almost two decades of experience in software development, I have dedicated my career to creating elegant solutions for complex problems. Currently, I work as a Senior Software Engineer, focusing on web and mobile application development and best practices in software development.

I am passionate about sharing knowledge and contributing to the software development community. Through this blog, I share my experiences, learnings and insights about software development, architecture and modern technologies.

In addition to development, I am an enthusiast for clean code, design patterns and agile methodologies. I believe that the best software is not only functional but also sustainable and scalable.