54

I make use of an AngularJS style guide. Within this guide there is a style called folder-by-feature, instead of folder-by-type, and I'm actually curious what's the best approach (in this example for Java)

Let's say I have an application where I can retrieve Users & Pets, using services, controllers, repositories and ofcourse domain objects.

Taking the folder-by-..... styles, we have two options for our packaging structure:

1. Folder-by-type

com.example
├── domain
│    ├── User.java
│    └── Pet.java
├── controllers
│    ├── UserController.java
│    └── PetController.java
├── repositories
│    ├── UserRepository.java
│    └── PetRepository.java
├── services
│    ├── UserService.java
│    └── PetService.java
│   // and everything else in the project
└── MyApplication.java

2. Folder-by-feature

com.example
├── pet
│    ├── Pet.java
│    ├── PetController.java
│    ├── PetRepository.java
│    └── PetService.java
├── user
│    ├── User.java
│    ├── UserController.java
│    ├── UserRepository.java
│    └── UserService.java
│   // and everything else in the project
└── MyApplication.java

What would be a good approach, and what are the arguments to do so?

  • 5
  • 1
    I don't know @Laiv. Does the language/framework really affect the answer? Regardless, the other question is certainly relevant. – RubberDuck Dec 21 '16 at 12:39
  • 1
    Then I have to edit my answer. And yest, it's a possible duplicate – Laiv Dec 21 '16 at 12:41
  • 2
    I never understood the benefit of folder-by-type. If i'm working on a ticket pertaining to the Pet feature, I would probably benefit from locality of Pet, the controller, the repository, and the service. In what situation would I ever need all controllers, but non of the views, repos or services? – Alexander Dec 22 '16 at 5:50
  • 2
    No one seems to have mentioned that packages in Java aren't just folders; they also affect access for the contained classes. For this reason, package-by-layer/type can actually provide some semantic value in Java. – Angus Goldsmith Dec 24 '16 at 17:41
63

Folder-by-type only works on small-scale projects. Folder-by-feature is superior in the majority of cases.

Folder-by-type is ok when you only have a small number of files (under 10 per type lets say). As soon as you get multiple components in your project, all with multiple files of the same type, it gets very hard to find the actual file you are looking for.

Therefore, folder-by-feature is better due to its scalability. However if you folder by feature you end up losing information about the type of component a file represents (because its no longer in a controller folder lets say), so this too becomes confusing. There are 2 simple solutions for this.

First, you can abide by common naming conventions that imply typeness in the file name. For example John Papa's popular AngularJS style guide has the following:

Naming Guidelines

  • Use consistent names for all components following a pattern that describes the component's feature then (optionally) its type. My
    recommended pattern is feature.type.js. There are 2 names for most
    assets:

    • the file name (avengers.controller.js)
    • the registered component name with Angular (AvengersController)

Second, you can combine folder-by-type and folder-by-feature styles into folder-by-feature-by-type:

com.example
├── pet
|   ├── Controllers
│   |   ├── PetController1.java
|   |   └── PetController2.java
|   └── Services
│       ├── PetService1.java
│       └── PetService2.java
├── user
|   ├── Controllers
│   |   ├── UserController1.java
│   |   └── UserController2.java
|   └── Services
│       ├── UserService1.java
│       └── UserService2.java
  • 1
    The johnpapa style guide was exactly the one I was fakking about :-) – Jelle Dec 21 '16 at 14:18
  • 1
    Some times (oftener than we think) we add too complexity to things that were supposed to be easy. Naming and packaging are some of these things. The best advice is keep it simple. Mixing both have either the advantages and the disadvantages of both approaches. – Laiv Dec 21 '16 at 14:24
  • 1
    @Laiv In the example I gave I agree its overkill, but in most of my real business cases where each type-folder can easily have 10-20 files I think its very useful because the overall feature-folder would have on the order of 50 files otherwise. – David Grinberg Dec 21 '16 at 14:32
  • 5
    fakking, thanks iPhone auto-correct! I meant 'talking'. – Jelle Dec 21 '16 at 14:56
  • 2
    @Chaotic This example is too trivial to start talking specifics, but in such cases where you have pieces that are used across multiple components, then that should probably be a component of its own that other components depend on. – David Grinberg Dec 21 '16 at 19:40
24

This really has nothing to do with the technology in question, unless you use a framework that forces folder-by-type on you as part of a convention-over-configuration approach.

Personally, I am strongly of the opinion, that folder-by-feature is far superior and should be used everywhere as much as possible. It groups together classes that actually work together, whereas folder-by-type just duplicates something that is usually already present in the class name.

  • 8
    I would add that in folder-by-feature makes easier to play with classes and methods scopes (protected, package,...). – Laiv Dec 21 '16 at 11:37
  • For smaller projects you may only have one feature. It is much easier to organize by type in that scenario. – aaaaaa Dec 21 '16 at 18:59
  • As an example, Grails does force folder-by-type for your domains, controllers, services, etc. – tylerwal Sep 19 '18 at 12:13
15

Working with packages-by-feature stands out in high modularity and cohesion. It allows us to play with the components' scope. For example, we can use the access modifiers to enforce LoD and the dependency inversion for integrations or/and extensions.

Other reasons are:

  • Easier code navigation
  • A higher level of abstraction
  • Minimize scopes (bounding contexts)
  • Vertical modularization

Folder-by-layer puts too much emphasis on the implementation details, (as @David mentioned) what doesn't tells too much about the application we are working on. Unlike package-by-feature, package-by-layer encourage horizontal modularization. This sort of modularization makes working with cross-cutting components hard and tedious.

Finally, there's a 3rd option. "Package by component" which, in words of Uncle Bob, seems better aligned with his package principles. If Uncle's Bob opinion matters or not, I leave it to you to decide. I find it interesting since this convention is aligned with his Clean Architecture, which I like.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.