mehdihadeli / go-food-delivery-microservices

πŸ• A practical and imaginary food delivery microservices, built with golang, domain-driven design, cqrs, event sourcing, vertical slice architecture, event-driven architecture, and the latest technologies.
MIT License
837 stars 85 forks source link
bdd boilerplate clean-architecture cqrs cqrs-pattern ddd distributed-systems domain-driven-design event-driven-architecture event-sourcing eventsourcing go golang grpc integration-test integration-testing microservice microservices microservices-architecture vertical-slice-architecture

πŸ• Go Food Delivery Microservices

GitHub Workflow Status Go Version Commitizen friendly

Open in GitHub Codespaces

Go Food Delivery Microservices is an imaginary and practical food delivery microservices, built with Golang and different software architecture and technologies like Microservices Architecture, Vertical Slice Architecture , CQRS Pattern, Domain Driven Design (DDD), Event Sourcing, Event Driven Architecture and Dependency Injection. For communication between independent services, We use asynchronous messaging using RabbitMQ, and sometimes we use synchronous communication for real-time communications using REST and gRPC calls.

You can use this project as a template to build your backend microservice project in the Go language

πŸ’‘ This application is not business-oriented and my focus is mostly on the technical part, I just want to implement a sample using different technologies, software architecture design, principles, and all the things we need for creating a microservices app.

πŸš€ This Application is in progress and I will add new features and technologies over time.

For your simplest Golang projects, you can use my go-vertical-slice-template project:

For more advanced projects, with two microservices and modular monolith architecture, check the C# version:

Features

Technologies - Libraries

Project Layout and Structure

Each microservices are based on these project structures:

System Architecture

Application Structure

In this project I used vertical slice architecture or Restructuring to a Vertical Slice Architecture also I used feature folder structure in this project.

Also here I used CQRS to decompose my features into very small parts that make our application:

By using CQRS, our code will be more aligned with SOLID principles, especially with:

Here instead of some Technical Splitting for example a folder or layer for our services, controllers, and data models which increase dependencies between our technical splitting and also jump between layers or folders, We cut each business functionality into some vertical slices, and inner each of these slices we have Technical Folders Structure specific to that feature (command, handlers, infrastructure, repository, controllers, data models, ...).

Usually, when we work on a given functionality we need some technical things for example:

Now we could have all of these things beside each other and it decrease jumping and dependencies between some layers or folders.

Keeping such a split works great with CQRS. It segregates our operations and slices the application code vertically instead of horizontally. In Our CQRS pattern each command/query handler is a separate slice. This is where you can reduce coupling between layers. Each handler can be a separated code unit, even copy/pasted. Thanks to that, we can tune down the specific method to not follow general conventions (e.g. use custom SQL query or even different storage). In a traditional layered architecture, when we change the core generic mechanism in one layer, it can impact all methods.

High Level Structure

TODO

Formatting

In this app, I use Conventional Commit and for enforcing its rule I use conventional-changelog/commitlint and typicode/husky with a pre-commit hook. To read more about its setup see commitlint docs and this article and this article.

For applying golangci-lint in IDE level I use intellij-plugin-golangci-lint plugin.

For formatting, I used mvdan/gofumpt, goimports-reviser, golines and golangci-lint in my GoLand and for each package, there is a guide for how to set it up in your IDE, for example. here is the configuration for goimports-reviser.

Also, you can control this formatting with husky automatically before any commit by installing husky in your dev environment:

  1. Install Tools:

    make install-tools
  2. Install NPM:

npm init
  1. Install CommitLint:
npm install --save-dev @commitlint/config-conventional @commitlint/cli
  1. Create the commitlint.config.js file with this content:
module.exports = { extends: '@commitlint/config-conventional']};
  1. Install Husky:
npm install husky --save-dev
  1. Add prepare command for installing and activating husky hooks that we will add in the next steps, in the package.json file:
npm pkg set scripts.prepare="husky install"
  1. Create the Husky folder:
mkdir .husky
  1. Adding hooks for linting and formatting before commit:
npx husky add .husky/pre-commit "make format && git add -A ."
npx husky add .husky/pre-commit "make lint && git add -A ."
  1. Adding CommitLint to the husky before commit:
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
  1. Activate and installing all husky hooks with this command:
npm run prepare

Live Reloading In Development

For live reloading in dev mode I use air library. for a guide about using these tools, you can read this article.

For running each microservice in live reload mode, inner each service folder type the bellow command after installing air:

air

Contribution

The application is in development status. You are feel free to submit a pull request or create the issue according to Contribution Guid.

License

The project is under MIT license.

References