Clean Architecture – Should Each Layer Have Its Own Entity/Model Class?

androidArchitectureclean codejavalayers

BACKGROUND :

I'm trying to use Uncle Bob's clean architecture in my android app. I studied many open source projects that are trying to show the right way to do it, and I found an interesting implementation based on RxAndroid.

WHAT I NOTICIED :

In every layer (presentation, domain and data), there's a model class for the same entity (talking UML). Plus, there are mapper classes that take care of object's transformation whenever the data is crossing the boundaries (from layer to another).

QUESTION :

Is it required to have model classes in every layer when I know that they'll all end up with the same attributes if all CRUD operations are needed? Or, is it a rule or a best practice when using the clean architecture?

Best Answer

In my opinion, that's absolutely not how it's meant. And it's a violation of DRY.

The idea is that the entity / domain object in the middle is modeled to represent the domain as good and as convenient as possible. It is in the center of everything and everything can depend on it since the domain itself doesn't change most of the time.

If your database on the outside can store those objects directly, then mapping them to another format for the sake of separating layers is not just pointless but creating duplicates of the model and that is not the intention.

To begin with, the clean architecture was made with a different typical environment / scenario in mind. Business server applications with behemoth outer layers that need their own types of special objects. For example databases that produce SQLRow objects and need SQLTransactions in return to update items. If you were to use those in the center, you were to violate the dependency direction because your core would depend on the database.

With lightweight ORMs that load and store entity objects thats not the case. They do the mapping between their internal SQLRow and your domain. Even if you need put an @Entitiy annotation of the ORM into your domain object, I'd argue that this does not establish a "mention" of the outer layer. Because annotations are just metadata, no code that isn't specifically looking for them will see them. And more importantly, nothing needs to change if you remove them or replace them with a different database's annotation.

In contrast, if you do change your domain and you made all those mappers, you have to change a lot.


Amendment: Above is a little oversimplified and could even be wrong. Because there is a part in clean architecture that wants you to create a representation per layer. But that has to be seen in context of the application.

Namely the following here https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html

The important thing is that isolated, simple, data structures are passed across the boundaries. We don’t want to cheat and pass Entities or Database rows. We don’t want the data structures to have any kind of dependency that violates The Dependency Rule.

Passing entities from the center towards the outer layers does not violate the dependency rule, yet they are mentioned. But this has a reason in the context of the envisioned application. Passing entities around would move the application logic towards the outside. Outer layers would need to know how to interpret the inner objects, they would effectively have to do what inner layers like the "use case" layer is supposed to do.

Besides that, it also decouples layers so that changes to the core don't necessarily require changes in outer layers (see SteveCallender's comment). In that context, it's easy to see how objects should represent specifically the purpose they are used for. Also that layers should talk to each other in terms of objects that are made specifically for the purpose of this communication. This can even mean that there are 3 representations, 1 in each layer, 1 for transport between layers.

And there is https://blog.8thlight.com/uncle-bob/2011/11/22/Clean-Architecture.html which addresses above:

Other folks have worried that the net result of my advice would be lots of duplicated code, and lots of rote copying of data from one data structure to another across the layers of the system. Certainly I don’t want this either; and nothing I have suggested would inevitably lead to repetition of data structures and an inordinate of field copying.

That IMO implies that plain 1:1 copying of objects is a smell in the architecture because you're not actually using the proper layers and /or abstractions.

He later explains how he imagines all the "copying"

You separate the UI from the business rules by passing simple data structures between the two. You don’t let your controllers know anything about the business rules. Instead, the controllers unpack the HttpRequest object into a simple vanilla data structure, and then pass that data structure to an interactor object that implements the use case by invoking business objects. The interactor then gathers the response data into another vanilla data structure and passes it back to the UI. The views do not know about the business objects. They just look in that data structure and present the response.

In this application, there is a big difference between the representations. The data that flows isn't just the entities. And this warrants and demands different classes.

However, applied to a simple Android application like a photo viewer where the Photo entity has about 0 business rules and the "use case" that deals with them is nearly non-existing and is actually more concerned about caching & downloading (that process should IMO be represented more explicitly), the point to make separate representations of a photo starts to vanish. I even get the feeling that the photo itself is the data transfer object while the real business-logic-core-layer is missing.

There is a difference between "separate the UI from the business rules by passing simple data structures between the two" and "when you want to display a photo rename it 3 times on the way".

Besides that, the point where I see those demo applications fail at representing the clean architecture is that they add huge emphasis on separating layers for the sake of separating layers but effectively hide what the application does. That is in contrast to what is said in https://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html - namely that

the architecture of a software application scream about the use cases of the application

I don't see that emphasis on separating layers in the clean architecture. It's about dependency direction and focusing on representing the core of the application - entities and use cases - in ideally plain java without dependencies towards the outside. It's not so much about dependencies towards that core.

So if your application actually has a core that represents business rules and use cases, and / or different people work on different layers, please separate them in the intended way. If you're on the other hand just writing a simple app all by yourself don't overdo it. 2 layers with fluent bounds may be more than enough. And layers can be added later on as well.