andistoev / onion-architecture-with-spring-boot

Example of how you can apply onion architecture with Spring Boot
GNU General Public License v3.0
22 stars 8 forks source link

Quick question #1

Open bojanv55 opened 2 years ago

bojanv55 commented 2 years ago

Hi. Was reading article at https://blog.mimacom.com/onion-architecture-spring-boot/ and have 1 question regarding:

If your app consumes REST services for example, this module should have no knowledge of the application layer (aka api);

so if app consumes REST service, it for example calls e.g. http://someotherservice/some/api inside the infra layer as in your table. But from there - in order to run some logic on the data, it has to forward to application services (api) and then possibly to core - isn't it?

The thing that I guess is problematic here is possibility to consume some REST endpoint as a side-effect of some existing api call (e.g. someone calls /currentTime endpoint on our service and then we go and consume http://atomclock/time -> this seems like infra) and there is also a possiblity to consume REST api as some scheduled task (e.g. every 10 minutes got to http://atomclock/time and if time is divisible with 10, save to db). I guess first case is infra second should be infra-api (even though this is actually not API, but needs to access core for logic)?

bojanv55 commented 2 years ago

Again when thinking of it, scheduler could be treated as a API call but only internal, so in theory it should probably go to infra-api in this case...

andistoev commented 2 years ago

Hi @bojanv55

so if app consumes REST service, it for example calls e.g. http://someotherservice/some/api inside the infra layer as in your table. But from there - in order to run some logic on the data, it has to forward to application services (api) and then possibly to core - isn't it?

The thing that I guess is problematic here is possibility to consume some REST endpoint as a side-effect of some existing api call (e.g. someone calls /currentTime endpoint on our service and then we go and consume http://atomclock/time -> this seems like infra) and there is also a possiblity to consume REST api as some scheduled task (e.g. every 10 minutes got to http://atomclock/time and if time is divisible with 10, save to db). I guess first case is infra second should be infra-api (even though this is actually not API, but needs to access core for logic)?

Let me put the case you mentioned graphically, so that I could explain you how to maintain the constraints in the table:

/1/ UI (app) --> /2/ rest-api (infra-api) --|--> /3/ service with BL doing orchestration (api) --|--|--> /3.1./ call external rest-api (infra rest) --|--|--> /3.2./ do something with the data. Could call other services (api) and use the domain model (core) --|<--|-- /3.3/ give service response <-- /2/ give rest response

As you see: 1) In point 3.2. there is a data elaboration internally in a service layer with access to other services (api) and to the domain logic (core) 2) In point 3.1. in infra-rest layer has been implemented the bare minimum to make a rest call (in a role of rest client) without elaboration. Here it's important to not have dependency to other infra-layers or to api, so that the module is easy "upgradable" technologically (if you want to replace it with other technology) and architecturally (minimum dependencies for easy of code maintainability or extension)

Again when thinking of it, scheduler could be treated as a API call but only internal, so in theory it should probably go to infra-api in this case...\

yes, correct. The scheduler is under infra-api in a meaning that all program inputs/triggers are infra-api for the backend logic. If kafka event has arrived, or rest api was invoked, or scheduler has been activated ---> all this triggers change in the backend. As a such putting it in infra-api makes the intention visible.

Did that sound reasonable to you? Let me know

Take care Andrey

bojanv55 commented 2 years ago

why don't you use maven modules as:

api, core etc. ?

also, why don't you group under infra submodule jpa etc. ?

Did you have some problems with this module naming strategy? That is my question is, why you have always to repeat onion-arch-service- part?

One more thing, where do you store your DTOs? In infra-api-rest, or in api? I guess if DTOs could be reused between different infra-apis (e.g. rest, rabbit, etc.) it makes sense to go to api. Otherwise if it is rest specific then in infra-api-rest? For me it looks more like api. And also this thing should probably map DTOs to entities as needed.