Michael Nygard writes in Release It!:

Have you ever checked in a commit that had bunch of new files like "Foo", "FooController", "FooFragment", "FooMapper", "FooDTO", and so on? That is evidence of bad layering.

This sounds pretty significant as almost every code base I saw so far looks exactly like this. For example a little web application (in Java implemented with Spring Boot - irrelevant):

└ FooApplication.java
└ controller
  └ FooController.java
  └ FooDTO.java
└ model
  └ Foo.java
  └ Foos.java
└ repository
  └ FooRepository.java

Looks like what Nygard is talking about.

What is a better approach here?

  • Use the model object Foo direct in the controller's input/output to eliminate FooDTO? Sounds not correct.
  • Do the domain logic direct in the controller to eliminate domain objects? Sounds horrible.
  • Do the persistence direct in the domain object to eliminate the repository? Maybe.

I still don't see an option how to eliminate the controller as a representative of the application layer.

Nygard writes futher in the same paragraph:

What appears as a class in one layer should be mere data to every other layer.

Is this not what FooDTO is all about?

So what would satisfy Nygard's concerns? Or is that just my misconception?

  • 3
    I would say these cites seem to be completely ripped out of context, and question where I have to buy a book first to answer them are pretty much unanswerable for me. – Doc Brown Nov 6 '19 at 6:42
  • They are written as a side note with no further explanation. – Barney Nov 6 '19 at 8:24
  • 1
    If those cites are a side note to "some text", one probably needs to know "some text" to answer this. – Doc Brown Nov 6 '19 at 12:13

The quote needs to be put in context.

  • Michael Nygard makes these claims to criticise the traditional layered architecture of enterprise software (he calls them UI/Session/Domain/Persistence);
  • His main issue is that the layers inhibit incremental change, probably because "Layers enforce vertical isolation, but they encourage horizontal coupling", the latter being a hindrance for incremental change.

The whole point is not about the packaging the files, nor about the naming of classes, but about the overall architecture of the application. And in particular undesired coupling that slows down incremental approach.

The drawbacks of the layered architectures in OOP are well known, and several other authors have addressed this topic, with new emerging architectures:

  • Domain objects (models), DTOs, repositories, and controllers all continue to be needed. For example DDD has proven to be a solid foundation to evolutive applications and it promotes the use of domain objects and repositories (in comparison, direct access to persistence layer would be counter-productive); as another example, DTOs are required in the context of distributed systems.
  • But the architecture models tend to become more concentric and avoid dependencies of the upper layers on the lower layers. The main challengers are nowadays the hexagonal architecture, and the clean architecture. Both put domain object at the core of the application, and see user interfaces, and database adapters on the (exchangeable) outer border of the system.

So in the end you will find the same kind of classes. But their dependencies are better thought and hence allow for more evolutivity. Finally, if you opt for breaking the monolith with microservices, you may end-up packaging a smaller amount of highly cohesive files, with fewer dependencies to the outside world.

  • Thank you for the answer, makes very much sense! "So in the end you will find the same kind of classes." Saying that, I still find the quote pretty misleading, why should this be an evidence of bad layering? Of course, a small microservices probably doesn't need any controller etc as the flow is so tiny, but this is an extreme case, microservices architecture is not the only one that is right. – Barney Nov 7 '19 at 14:18
  • @Barney I am not convinced about his arguments. His point is to say that if you'd change Foo, you'd have to change all the FooXxxx across the layers. He concludes by saying that a class of one layer should be data in another. Interesting thoughts, but perhaps overgeneralized. IMHO, the key remains the design and dependencies, not the naming of the files. But I could agree is on the controller. Because "controller" and "manager" classes are sometimes too quickly related to the domain objects, whereas ECB analysis may suggests that Entities are not bound one to one to Controllers. – Christophe Nov 7 '19 at 20:14
  • So your point is, one controller should/could orchestrate more than one entity, something like Domain Services in DDD, right? I can agree on that. – Barney Nov 7 '19 at 20:22

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