Skip to content

ntorga/clean-ddd-full-stack-go-poc

Repository files navigation

Full Stack Go with Clean Architecture and DDD: A Proof of Concept

Introduction

The center of your application is not the database. Nor is it one or more of the frameworks you may be using. The center of your application is the use cases of your application - Unclebob (source)

This project builds upon the principles demonstrated in the PHP version of our Clean Architecture and Domain-Driven Design (DDD) Proof of Concept (PoC). Before diving into this Go implementation, we recommend familiarizing yourself with the PHP version to grasp the foundational concepts that drive this project.

Architecture

Disclaimer

This project is NOT intended for a production environment. It is a proof of concept (PoC) that does not meet traditional requirements in terms of availability nor scalability.

Not all concepts mentioned here were followed to the letter. The idea is to comply with the known design principles and patterns, but not to be dogmatic about them.

Objective

The primary aim with this Go-based PoC is to demonstrate how Clean Architecture and DDD principles can be effectively implemented in a full stack Go project. However, you'll also find a few additional features that were not present in the PHP version:

  • Database: Data needs to be in an actual database. SQLite was chosen for its simplicity;
  • CLI: A command-line interface (CLI) to interact with the application;
  • Front-end: A server side rendered (SSR) HTML application with reactivity, but without a framework such as Next.js (React) or Nuxt.js (Vue);
  • Hot Reload: The browser will reload automatically when changes are made to the application thanks to air, xdotool and tmux.
  • No Exceptions/Panic: The application does not use exceptions or panic. Instead, errors are dealt with gracefully;

Technologies

  • Go: the programming language;
  • Echo: the HTTP framework used for the REST API;
  • Cobra: the CLI framework;
  • GORM: the ORM used to interact with the database;
  • SQLite: the database;
  • Templ: the templating engine;
  • HTMX: the library used to add AJAX to the HTML;
  • Alpine.js: the library used to add reactivity to the HTML;
  • Tailwind CSS (via UnoCSS): the CSS framework;

Deploy

The binary files are available for download on the releases page.

To run the application, you just need to execute the binary file. The application will be available at http://localhost:8080.

For instance on Linux:

chmod +x poc-linux-amd64
./poc-linux-amd64 serve

Although the binary files are available, only the linux/amd64 version is tested. If you face any issues with the compiled binaries, please report on the issues page.

Development

  1. Install xdotool and tmux. For Ubuntu, you can install them with sudo apt install xdotool tmux.

  2. Install air and templ:

go install github.com/cosmtrek/air@latest
go install github.com/a-h/templ/cmd/templ@latest

The tailwind.config.js file is not used, it is present just to make the VSCode Tailwind CSS extension work. The Tailwind CSS is deployed in this application using UnoCSS (no CLI needed).

  1. Install the following VSCode extensions:
golang.go
streetsidesoftware.code-spell-checker
esbenp.prettier-vscode
bradlc.vscode-tailwindcss
Trapfether.tailwind-raw-reorder
a-h.templ
hbenl.vscode-test-explorer
yy0931.vscode-sqlite3-editor
be5invis.toml
  1. Run the following command to start the application:
make dev

The application will be available at http://localhost:8080 and will hot reload your browser active tab if changes are made to .templ files on the last 60 seconds.

Q&A

Why not use React, Vue or Svelte?

I wanted to decrease as much as possible the usage of JavaScript to reduce the complexity of the project. HTMX and Alpine.js adds the necessary DOM manipulation tools without the need for a opinionated framework and with very little JavaScript. In fact, the only JavaScript in the project is the state management (why isn't there an official standard for that yet?) and a event listener/dispatcher inside the HTML tags.

Why not Next.js (React), Astro or Nuxt.js (Vue)?

To fully understand why, I recommend reading the article "What it’s like to run HTMX in Production - Stories from Experienced Software Engineers" to understand the benefits of using HTMX and Alpine.js.

To put it simply, I didn't want the loop of DB -> Backend Logic -> JSON -> Frontend Logic -> HTML. I wanted to go from DB -> Backend Logic -> HTML and then add reactivity with HTMX and Alpine.js. That way I can reduce the tooling and the complexity of the project.

Why not use Tailwind CSS CLI to build the CSS?

I don't intent on using plugins or custom configurations for Tailwind CSS. I want just the basics and UnoCSS gives you Tailwind CSS without the need for a build process.

Why not PostgreSQL, MySQL or MongoDB?

SQLite is more than enough for a PoC. The focus is on the architecture, not the database. However, since we are using GORM, it would be easy to switch to another database if needed or you could try Turso with a few modifications to GORM.

Why not Rust, Python, Ruby, PHP or JavaScript/TypeScript?

Go has a great standard library and it's easy to learn. The deployment is very simple, just a single binary. The performance is great and the language is very stable. No need for a runtime or a virtual environment. The entire project is a single binary. REST API, CLI and HTML with a single command.

However, why don't you try to implement this PoC in another language? It would be a great learning experience for sure. (:

Documentation

The REST API documentation follows the OpenAPI v2 specification.

Generating the Documentation

To generate the documentation, you need to have composer and the dependencies installed. Then, run the following command:

swag init -g src/presentation/api/api.go -o src/presentation/api/docs

You must run this command every time you update the controllers or the domain.

Viewing the Documentation

The src/presentation/api/docs/swagger.json file contains the documentation in the OpenAPI v2 specification.

To see the documentation, you can use any tool that supports this specification, such as the Swagger Online Editor.

When using the Swagger Online Editor, you can import the swagger.json file by clicking on the File menu and then on Import file.

The swagger file is also available in the API itself. To see it, just access the /api/swagger/ endpoint.

Resources

Contacts

For any question or feedback feel free to contact me: