Search code examples
androidarchitectureclean-architecture

Clean Architecture Entities


As I understand it, Clean Architecture entities are laid out as a layer on which all upper layers depend directly or indirectly, based on the assumption that the data and business rules residing in entitas are the most stable part of the architecture.

At the same time entities contains data classes on which the parent layer depends, and the rest if no mappers are used for data.

But data in reality is often not stable enough.

Here's an example: Let's say you have an app for selling cars. The car data is described by a structure, which contains parameters such as description, brand, price and other things. Requirements are changing, and now, mixed with cars in the application, there should be ads for the sale of motorcycles. Some of the fields are the same with the car, for example, price and description, and some are different.

You can't put data about cars and motorcycles into one structure, because then any type of ads can be added, and the structure will swell like a cancerous tumor.

It will also not work to implement polymorphic behavior at higher levels, since this will generate either dependencies in the structure itself + cyclic dependencies in the hierarchy, or dependencies from the upper layers to this structure directly, which is also bad. You can, of course, duplicate this behavior throughout the entire chain of mappers, but this takes a long time and inflates the amount of code.

It remains to create a separate data type and the entire branch through which this data is forwarded, and this is just as inconvenient and adds a dependency at the top level.

The impression is that Clean Architecture is fragile when data changes.

Perhaps I don't understand something basic, and this problem can be easily solved? If so, write plz what exactly, if not - can you do something about it?)


Solution

  • I think you confuse data entities with business entities or domain entities. Your term "stable" is also confusing. It seems you are talking about extensibility: the degree to which your application allows to be extended with new features or business rules or how modifications will break your application.

    Clean Architecture is about application architecture and not primarily about class design. Your mentioned polymorphic behavior or data types are class level details.

    Software architecture describes the structure of an application and does not deal with implementation details or data. It's like when constructing a building, architecture does not deal with interiors, but the buildings structure.
    This means the data itself, that is handled by the application has no influence on the architecture.

    I think the key of Clean Architecture is the clean structure of the application, where dependencies between the components are directed from outside to inside (see image below). The goal is to create a robust application with a robust business logic.
    In other words: changing the UI or the database does not affect the business logic. This makes the architecture quite "stable" (robust in terms of extensibility/modifications).
    Considering an architecture, where the business logic directly interacts with/depends on the UI or database, we can say the architecture is very fragile, as a modification of the UI would also require to modify the business logic as well i.e. the modification would break the business logic. Clean Architecture solves this problem.

    You have to distinguish between data entities and business entities.
    Data entities hold the data that your business logic operates on.
    Domain entities encapsulate the actual business rules of the application (enterprise level).

    enter image description here

    Example: an application is designed to sell cars.

    A Car class is clearly a data model with your described attributes like description, brand, price. You typically call this data entity as it's the vessel for the data your business logic operates on. You fill this vessel e.g. with data from a data base and transport it to the view layer for display and manipulation. The user manipulates this data entity, which is then returned to the business layer.

    The business entities of such a car selling application could be a RentalAgreement which encapsulates the rules for renting the car, a LeaseAgreement and a PurchaseAgreement and more (depending on the actual enterprise business). Those classes also contain the related logic e.g., to actually execute the purchase according to the rules like restrictions, taxing, special offers or bonuses. These entities may reflect enterprise level business processes.

    The use cases represent the actual business logic. The logic that combines or operates on the business entities in order to service the several use cases (or user stories). E.g. trade a used car for a new.
    Following Clean Architecture, the use cases depend on the entities, but not the other way around (from outside to the center - see image above). Therefore the use cases don't depend on the e.g. presenter component. It is used by the presenter.

    The use cases require the data entities in order to do their work. The use case "trade the old car for a new" requires a Car entity to store the relevant data of the old car and a second Car to store the data of the new car.
    Polymorphism are concepts you apply when designing those data entities.

    You could introduce an abstract base type Vehicle. Then realize this type by deriving a Car and a Motorcycle.
    Ads should be a dedicated type e.g. Ads which is not part of the Vehicle type hierarchy.
    You can create a container type e.g. Offer, which aggregates a Vehicle and a Ads instance.

    On top you create an e.g. OfferCreator, which creates the Offer instance and also selects the appropriate Ads.

    This is just a very raw example. Following its pattern provides a high degree of extensibility, when certain principles are followed (e.g. SOLID). This means, adding new types of Vehicle or Ads won't break the business logic. Also extending the business logic itself won't break the application.