2

I've read and enjoyed the "Clean Architecture" book. So the first thing I tried to do is to implement my project with it.

Where I work we follow a design method called IDesign in which the architecture is broken into:

  1. "clients" - encapsulate communication with consumers (e.g. UI)
  2. "managers" - manages business flows (drives use cases)
  3. "engines" - stateless computational components (not always needed)
  4. "resource accesses" - encapsulates accesses to data sources

A component of each type is logically a service so I was trying to treat each one as a component in "Clean Architecture". What I'm having a hard time with is this.

RA (Resource access) component is clearly low level so manager for instance should not depend on it.

We can have multiple managers and engines using the same RA so according to my favorite uncle each should define its own interface and the RA component should implement all of them.

What I cannot understand is, if I'll want to make the RA component into a micro-service, how would its API look?

I'm trying to follow this approach in a NodeJS project which makes it even harder for me to grasp how to implement such a solution..

The best I could up with so far is to have a single API for the RA and on each engine/manager to have internal onion architecture approach in which a repository layer class is implementing a "Use Case" layer interface and calls the RA API (in memory at first stage, through network potentially in the future).

Another thing I struggled with is the entity objects. should the RA service map to them when returning response? Again it makes sense when this is the same process but between micro services I'm not so sure...

5
  • Is RA's function to map a request to a resource that can fulfill it or something more? Commented Mar 25, 2019 at 0:00
  • RA's responsibility is to encapsulate everything related to to data access. It could handle for instance - throttling, transactions, query building, data scoping, auditing, connection to DB etc.
    – Tal Joffe
    Commented Mar 25, 2019 at 8:00
  • 1
    Just a question. Is it your intention to make this "service" the data source for the others (services)? If yes, it would be good for you to re-think why you want to do this in this way, It's very contrary to the MS philosophy because this service will become into a point of heavy coupling. On the other hand, I would not trust any answer that basically suggests swinging against the current.
    – Laiv
    Commented Mar 25, 2019 at 10:05
  • I'm with laiv. That's too much for a micro service. It's too much for a component. It reminds me of the service locator pattern. Unless you're being crippled by some framework that forces you to work this way consider a redesign. Commented Mar 25, 2019 at 13:13
  • "Component" is a vague and relative term. A microservice is a component in the overall architecture, but a microservice also can be made up out of components (i.e. what's in the microservice's codebase). Similarly, the entire microservice architecture of your company could be a component of another larger platform. There is no singular level of granularity to which the word "component" applies. It just means "part of a larger whole".
    – Flater
    Commented Feb 13, 2022 at 20:34

1 Answer 1

1

I found this quote online when searching "Clean Architecture component dependency" since I wasn't familiar with it:

When working with clean architecture, the dependencies in an application are designed for stability. This means that less-stable components should only depend on components that are more stable.

For understanding the IDesign method, I usually refer to this blog as a cheat sheet.

My understanding is that IDesign encourages you to encapsulate things that will change (ie. volatility based decomposition). Which elements are most likely to change is dependent on the project you are building.

In my experience, the Resource Access layer changes the most slowly, with the business logic (Managers) being most likely to change. This is compatible with the clean architecture quote above, since the Manager layers call down to the lower layers.

I have found that it is not necessary to use separate microservices for each of the components unless operating at high scale, and if interfaces are well defined then it is easy to split along the component lined at a later date if it becomes necessary. So I would suggest avoiding separated microservices until it becomes a business requirement for your system to perform at a certain level.

What has worked for me is for the Resource Access layer to expose a single interface, and for the higher layers to depend on that interface. It sounds like that goes against the advice you've understood but I have found it to be pragmatic. Resource Access code then becomes its own component, not split among the Managers as it sounds from the original post.

If those interfaces are only data transfer objects (DTOs) then separating components can be done by each higher layer redefining the same interface that was used before from the lower layer, then implementing that interface by making a call to the separated component (eg. over HTTP).

The Resource Access interface may not correspond precisely with the data in the resource itself, for example mapping ints in the database to enum values, or linking together tables into a class with appropriate properties.

2
  • Thanks for the answer. Actually i have progressed a lot with how I approach design since posting this question. My conclusion was similar to yours. I stopped using IDesign as a method and more as an inspiration. So I don't treat IDesign services as if they are microservies rather as components in the same service and separate into microservies by domain (each will include all the layers it needs).
    – Tal Joffe
    Commented Jan 15, 2022 at 22:59
  • Regarding how I use the RA, what I do is to have an interface defined on the RA level but using something similar to the specification pattern, the component in the business logic layer will build the options passed to the RA get/create/update/delete methods so the RA actually depends on the business logic and not the other way around. The class responsible for building the options will be used by any Manager/Engine (business logic) that needs to use the RA
    – Tal Joffe
    Commented Jan 15, 2022 at 22:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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