clean-protobuf

module
v0.0.0-...-67e434f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2023 License: MIT

README

Clean-Protobuf

A heavily modified, clean architecture version of https://github.com/grpc/grpc-go/tree/master/examples/route_guide.

The project layout is based on https://github.com/golang-standards/project-layout.

The architecture is influenced by https://github.com/evrone/go-clean-template, and a little bit https://github.com/Creatly/creatly-backend.

Features

  • Protocol Buffers
    • Connect
    • gRPC
    • Streaming
    • REST reverse-proxy
  • Clean architecture
  • PostgreSQL
    • Migration
  • Generics
  • Code generation
    • gRPC servers (protoc)
    • GORM models (gorm.io/gen)
    • Initial user defined models (template)
    • Repository interfaces (template)
    • Initial repository implementation (template)
    • OpenAPI v3 (protoc-gen-openapi)
  • Containers
  • De facto standard layout

Getting Started

make run-server
make run-client

Layout

/api

The API definition files (like .proto).

/assets

Non-Go related data. Usually things like images, but here it is test data.

/cmd

The mains.

/internal

The implementation not meant to be used by external systems.

/internal/app

The starting points of the systems. Basically extensions of the mains.

/internal/config

The global configurations.

/internal/entity

The entities of the system. Sometimes named as domain.

The package contains definitions of the common types and their methods.

/internal/entity/model

The models. Methods for manipulating models also resides here.

/internal/entity/repository

The repository interfaces.

Actual implementation requires communication with the outside world (a database, etc) thus resides in /internal/infrastructure/repository.

/internal/infrastructure

The implementation which directly communicates with the outside world and does conversion into entities.

Basically gateways/mediators between the business logic (use cases) and the outside world that translates "their" data into "ours".

/internal/infrastructure/controller

The controllers/handlers of the server.

/internal/infrastructure/repository

The database logic. It reads/writes data from/to the databases or alike. The structs here implement interfaces in /internal/entity/repository.

You can have multiple implementation here to support different versions, mocks, different ORMs, anything.

/internal/pkg

The internal packages. The generated API code resides here.

The packages are independent of the rest of the implementation.

/internal/tools

Tools that only have specific internal purposes.

/internal/usecase

The business logic. The part which is not "chores".

It does not have direct external dependencies like database or API definitions. All those dependencies must be abstracted to be used here.

/tools

Tools that can be configured and reused.

Code Generation

Code generation is used for:

  • gRPC servers (protoc)
  • GORM models (gorm.io/gen)
  • initial user defined models (template)
  • repository interfaces (template)
  • initial repository implementation (template)

They are all programmatically generated by /tools/db-code-generator, so you can modify the code or templates for customization.

To re-generate code, run the following command:

make generate-db-code
Promoted Fields

Models and repositories use generated models or generics promoted to minimize the amount of code to be hand-written. It does not affect GORM behaviors.

Model Customization

If you want to add fields that do not exist on the database for your convenience, the following would work:

type Feature struct {
	generated.Feature

    AdditionalField string `gorm:"-"`
}

Other GORM tags should work similarly.

Use Case Callbacks

Use cases call a callback function when an important event occurs. Callbacks act as output ports, abstraction of the outside world, and thus are supposed to be implemented and provided by the infrastructure layer.

This style is rather rigorous and cumbersome. Moreover, majority of the times, it can be replaced by simple return values. However, it provides a lot more flexibility to the infrastructure layer. The examples are shown in the streaming RPC controllers where we still achieve practically one-to-one port from the original single handler implementation to infrastructure-usecase-entity implementation.

Database Migration

To add a new migration in one command, run the following

make create-new-postgres-migration NAME=new_migration_file_name

To migrate up/down, use one of the make migrate-* targets.

Other differences from the Original

  • Use PostgreSQL as the data store instead of a slice and a map.
    • RouteChat (route.PostMessage) does not use a transaction to make saving a new message and reading existing messages atomic while the original is.
      • Although the behavior is slightly different, there's no practical disadvantage (your new message might not be the latest message, but who cares?)
  • Use environment variables instead of flags.
    • Having a struct felt cleaner while providing /internal/config example.

Directories

Path Synopsis
cmd
grpc/client
Package main implements a simple gRPC client that demonstrates how to use gRPC-Go libraries to perform unary, client streaming, server streaming and full duplex RPCs.
Package main implements a simple gRPC client that demonstrates how to use gRPC-Go libraries to perform unary, client streaming, server streaming and full duplex RPCs.
grpc/original-server
Package main implements a simple gRPC server that demonstrates how to use gRPC-Go libraries to perform unary, client streaming, server streaming and full duplex RPCs.
Package main implements a simple gRPC server that demonstrates how to use gRPC-Go libraries to perform unary, client streaming, server streaming and full duplex RPCs.
internal
pkg/data
Package data provides convenience routines to access files in the data directory.
Package data provides convenience routines to access files in the data directory.
pkg/protobuf/routeguide/v1
Package routeguidev1 is a reverse proxy.
Package routeguidev1 is a reverse proxy.
tools

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL