Search code examples
.netmicroservices

Microservice folder organization, using service with repository


I'm trying to understand and create best approach for my test microservice. Microservice is structured as follows:

  • MyTestService.API //represents application layer
  • MyTestService.Domain // represents domain layer
  • MyTestService.Infrastructure // represents infrastructure layer

Application layer coordinates tasks and delegates work. It has Commands, EventHandlers, Validations, ...

Infrastructure layer deals with data and other things. Here is implementation of the repositories, db context, ...

I have need to introduce a service (let's call it userService) which should be called from MyTestService.API. This service will use repository in order to get data.

Where this service should be stored?

In the infrastructure layer? If so, what is the use for this if I already use exposed repository here?

In the domain layer? Domain layer shouldn't know about outer things.

This leaves me application layer as only option. Since this is a web api project I would put this service in the Service folder.

How would you structure your microservice folder structure?


Solution

  • There are a lot of possibilities how you could structure a micro-service based project. I would suggest the following:

    • Each micro-service in a separate solution There are multiple benefits in having each micro-service in a separate solution. Some of them are: independent micro-service(or domain) teams, being able to use different technologies for each micro-service if needed, smaller code-bases and so on.

    • MyTestService.Infrastructure Extract Infrastructure code to a separate Project and create a library(nuget package) from it. If your infrastructure contains code for Database access, cache interaction, authentication and similar common functionalities then you can create a library and reuse it in multiple micro-services. In this case your infrastructure would be domain agnostic and would only focus on having common solution for multiple micro-services.

    Your micro-service could then have Projects inside that solution:

    1. MyTestService.Domain This should contain all your Domain/Business logic for one particular micro-service and its domain. Here you should put business logic code related to specific micro-service like validation, handlers for your commands and events and similar. This layer would use infrastructure as shared library in order to perform database access, cache interaction and similar. Keep in mind that each micro-service would have its own Domain project. You could separate this Domain project in multiple if you use DDD(Domain Driven Design). You can make a quick search online. There are a lot of examples how DDD Project could be structured.

    2. MyTestService.API This would be your WebApi project with your Rest api endpoints. Here you would have your Controllers, ApiModels and things you need for bootstrapping your Project like Dependency Injection composition root and similar. Things which you would use in multiple solutions for this Project you could extract to infrastructure as well and reuse it in multiple micro-services API(WebApi) project. This project would be your entry point to your micro-services for everyone trying to do direct call to your micro-service like using http. From here you would distribute the calls to particular code in your .Domain project.

    3. MyTestService.Domain.Test and MyTestService.API.Test. Anther one which you could add if you write tests is MyTestService.Domain.Test and/or MyTestService.API.Test. Here you could put your Unit and Integration tests for the your 2 projects. Again you can have some test setups and common test infrastructure which you could put in to the infrastructure library.

    Example

    Lets say you have 2 micro-services Users and Orders micro-services. You would have 2 solutions(one per micro-service) and a third one for intrastructure:

    1. Solution Users micro-service. This would have the following projects:

      • MyOrganisation.Users.Api
      • MyOrganisation.Users.Domain
      • MyOrganisation.Users.Test
    2. Solution Orders micro-service. This would have the following projects:

      • MyOrganisation.Orders.Api
      • MyOrganisation.Orders.Domain
      • MyOrganisation.Orders.Test
    3. Infrastructure

      • MyOrganisation.Infrastructure.Api - nuget package
      • MyOrganisation.Infrastructure.DataAccess - nuget package
      • MyOrganisation.Infrastructure.Cache - nuget package
      • MyOrganisation.Infrastructure.Test - nuget package

    Your micro-services would use these nuget packages to reuse common logic like data access and test infrastructure in order to avoid duplication and your micro-services would only focus on the business logic and not infrastructure related things. As you go and write new micro-services you don't have to duplicate infrastructure code in each and you can focus on the Domain. As you project grows you add more common and new things to the infrastructure libraries.

    Comming back to your question:

    I have need to introduce a service (let's call it userService) which should be called from MyTestService.API. This service will use repository in order to get data.

    Where this service should be stored?

    I am not quite sure what you mean here but let me try to answer. If your UserService should be part of another service then you should reconsider placing it into its own micro-service. If you are calling some other micro-service from your micro-service which is called and you are wondering where this call should happen. I would say in your .Domain project. Why? Because it communication to other micro-service to perform some business operation is still part of your Domain. Like "in order to place an order I need user data". Still this is part of order micro-service business operation even if it is calling another micro-service. Now the call to other micro-service and how it is done technically for this you can have a common infrastructure logic in one of the infrastructure libraries. Because calling one micro-service from another or using some sort of communication between them sync or async is something most of the micro-services need so you should extract this common part to infrastructure code.