Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
# go-ddd
# go-arch-patterns

This repository showcases the Ports and Adapters architectural pattern (also known as Hexagonal Architecture) and Domain-Driven Design (DDD) methodology, with a focus on fundamental concepts such as value objects. For more details about the software architecture, see [Software Architecture](docs/software_architecture.md).
This repository demonstrates various architectural patterns and design principles for building scalable backend systems in Go. The codebase showcases architectural patterns, database design techniques, and SaaS-specific implementations through a practical car rental platform example.

The system represents a SaaS platform for car rental companies. For more details about the system, see [Entity Relationship Diagram](docs/er-diagram.md).
For more details about the architecture, see [Software Architecture](docs/software_architecture.md).
For the data model and relationships, see [Entity Relationship Diagram](docs/er-diagram.md).

## Key Implementation Examples

This repository demonstrates the following software engineering concepts:

### Domain-Driven Design & Architecture

- **Value Object**:
- *Definition*: See [Email value object](internal/domain/model/value/email.go) with [tests](internal/domain/model/value/email_test.go)
- *Usage*: See [Individual entity](internal/domain/model/individual.go) using the Email value object

### Database Design Patterns

- **Class Table Inheritance**: See [Renter model](internal/domain/model/renter.go) as the base class with [Company](internal/domain/model/company.go) and [Individual](internal/domain/model/individual.go) as specialized subclasses

### SaaS & Microservices Patterns *(Coming Soon)*

- **PostgreSQL Row-Level Security**: Multi-tenant data isolation
- **Outbox Pattern**: Reliable event publishing for distributed systems

## Documentation

Find specific documentation in the [docs/](docs/) folder:
Expand Down
6 changes: 3 additions & 3 deletions docs/installation_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
## Clone the repository

```bash
git clone https://github.com/jp-ryuji/go-ddd.git
cd go-ddd
git clone https://github.com/jp-ryuji/go-arch-patterns.git
cd go-arch-patterns
```

## Set up environment variables with direnv
Expand Down Expand Up @@ -97,7 +97,7 @@ docker compose down
You can access the PostgreSQL database using the following command:

```bash
PGPASSWORD=$POSTGRES_PASSWORD docker exec -it go-ddd-postgres-1 psql -U $POSTGRES_USERNAME -d $POSTGRES_DBNAME
PGPASSWORD=$POSTGRES_PASSWORD docker exec -it go-arch-patterns-postgres-1 psql -U $POSTGRES_USERNAME -d $POSTGRES_DBNAME
```

This command uses the environment variables loaded by direnv to connect to the database.
2 changes: 1 addition & 1 deletion docs/software_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Structure:

## Go `internal` Directory

The `internal` directory is a special directory in Go that restricts access to its contents. Only code within the same module (in this case, `go-ddd`) can import packages from `internal` directories. This prevents other projects from importing and depending on our internal implementation details, which helps maintain a clean public API and allows us to change internal implementations without breaking external dependencies.
The `internal` directory is a special directory in Go that restricts access to its contents. Only code within the same module (in this case, `go-arch-patterns`) can import packages from `internal` directories. This prevents other projects from importing and depending on our internal implementation details, which helps maintain a clean public API and allows us to change internal implementations without breaking external dependencies.

In this project, all core business logic, domain models, use cases, and infrastructure implementations are placed under the `internal` directory to enforce this encapsulation and prevent accidental exposure of internal details as part of the public API.

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/jp-ryuji/go-ddd
module github.com/jp-ryuji/go-arch-patterns

go 1.25.0

Expand Down
4 changes: 2 additions & 2 deletions internal/domain/model/factory/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package factory
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-ddd/internal/pkg/id"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/pkg/id"
)

// NewCompany creates a new Company for testing purposes
Expand Down
6 changes: 3 additions & 3 deletions internal/domain/model/factory/individual.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"time"

"github.com/aarondl/null/v9"
"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-ddd/internal/domain/model/value"
"github.com/jp-ryuji/go-ddd/internal/pkg/id"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model/value"
"github.com/jp-ryuji/go-arch-patterns/internal/pkg/id"
)

// NewIndividual creates a new Individual for testing purposes
Expand Down
4 changes: 2 additions & 2 deletions internal/domain/model/factory/renter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package factory
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-ddd/internal/pkg/id"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/pkg/id"
)

// NewRenter creates a new Renter for testing purposes
Expand Down
4 changes: 2 additions & 2 deletions internal/domain/model/factory/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package factory
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-ddd/internal/pkg/id"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/pkg/id"
)

// NewTenant creates a new Tenant for testing purposes
Expand Down
2 changes: 1 addition & 1 deletion internal/domain/model/individual.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/aarondl/null/v9"
"github.com/oklog/ulid/v2"

"github.com/jp-ryuji/go-ddd/internal/domain/model/value"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model/value"
)

// Individuals is a slice of Individual
Expand Down
2 changes: 1 addition & 1 deletion internal/domain/model/individual_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"time"

"github.com/aarondl/null/v9"
"github.com/jp-ryuji/go-ddd/internal/domain/model/value"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model/value"
"github.com/stretchr/testify/require"
)

Expand Down
4 changes: 2 additions & 2 deletions internal/domain/model/renter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package model_test
import (
"testing"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-ddd/internal/domain/model/factory"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model/factory"
)

// TestRenterCreation ensures that we can create renters
Expand Down
2 changes: 1 addition & 1 deletion internal/domain/repository/car.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package repository
import (
"context"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

//go:generate go run go.uber.org/mock/mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock_repository
Expand Down
2 changes: 1 addition & 1 deletion internal/domain/repository/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package repository
import (
"context"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

//go:generate go run go.uber.org/mock/mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock_repository
Expand Down
2 changes: 1 addition & 1 deletion internal/domain/repository/mock/car.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/domain/repository/mock/company.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/domain/repository/mock/renter.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/domain/repository/mock/tenant.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/domain/repository/renter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package repository
import (
"context"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

//go:generate go run go.uber.org/mock/mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock_repository
Expand Down
2 changes: 1 addition & 1 deletion internal/domain/repository/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package repository
import (
"context"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

//go:generate go run go.uber.org/mock/mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock_repository
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"entgo.io/ent/dialect"
entsql "entgo.io/ent/dialect/sql"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/jp-ryuji/go-ddd/internal/infrastructure/postgres/entgen"
"github.com/jp-ryuji/go-arch-patterns/internal/infrastructure/postgres/entgen"
)

// Connection pool settings with defaults
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/dbmodel/car.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dbmodel
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

// Car represents the database model for Car
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/dbmodel/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dbmodel
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

// Company represents the database model for Company
Expand Down
4 changes: 2 additions & 2 deletions internal/infrastructure/postgres/dbmodel/individual.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"time"

"github.com/aarondl/null/v9"
"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-ddd/internal/domain/model/value"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model/value"
)

// Individual represents the database model for Individual
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/dbmodel/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dbmodel
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

// Option represents the database model for Option
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/dbmodel/rental.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dbmodel
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

// Rental represents the database model for Rental
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/dbmodel/rental_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dbmodel
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

// RentalOption represents the database model for RentalOption
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/dbmodel/renter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dbmodel
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

// Renter represents the database model for Renter
Expand Down
2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/dbmodel/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dbmodel
import (
"time"

"github.com/jp-ryuji/go-ddd/internal/domain/model"
"github.com/jp-ryuji/go-arch-patterns/internal/domain/model"
)

// Tenant represents the database model for Tenant
Expand Down
4 changes: 2 additions & 2 deletions internal/infrastructure/postgres/entgen/car.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/entgen/car/where.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions internal/infrastructure/postgres/entgen/car_create.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/infrastructure/postgres/entgen/car_delete.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions internal/infrastructure/postgres/entgen/car_query.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions internal/infrastructure/postgres/entgen/car_update.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/infrastructure/postgres/entgen/caroption.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/infrastructure/postgres/entgen/caroption/where.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading