Skip to content

Commit

Permalink
Refactoring with DDD Lite
Browse files Browse the repository at this point in the history
  • Loading branch information
roblaszczak committed Jul 1, 2020
1 parent 3d2ce60 commit 0249977
Show file tree
Hide file tree
Showing 20 changed files with 959 additions and 247 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Wild Workouts

*The idea for this series, is to apply DDD by refactoring. This process is in progress! Please check articles, to know the current progress.*

Wild Workouts is an example project that we created to show how to build Go applications that are **easy to develop, maintain, and fun to work with, especially in the long term!**

No application is perfect from the beginning. With over a dozen coming articles, we will uncover what issues you can find in the current implementation. We will also show how to fix these issues and achieve clean implementation by refactoring.
Expand All @@ -11,7 +13,8 @@ No application is perfect from the beginning. With over a dozen coming articles,
3. [**Robust gRPC communication on Google Cloud Run (but not only!)**](https://threedots.tech/post/robust-grpc-google-cloud-run/?utm_source=github.com)
4. [**You should not build your own authentication. Let Firebase do it for you.**](https://threedots.tech/post/firebase-cloud-run-authentication/?utm_source=github.com)
5. [**Business Applications in Go: Things to know about DRY**](https://threedots.tech/post/things-to-know-about-dry/?utm_source=github.com)
6. *More articles are on the way!*
6. [**When microservices in Go are not enough: introduction to DDD Lite**](https://threedots.tech/post/ddd-lite-in-go-introduction/?utm_source=github.com)
7. *More articles are on the way!*

### Directories

Expand Down
7 changes: 3 additions & 4 deletions api/protobuf/trainer.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import "google/protobuf/timestamp.proto";

service TrainerService {
rpc IsHourAvailable(IsHourAvailableRequest) returns (IsHourAvailableResponse) {}
rpc UpdateHour(UpdateHourRequest) returns (EmptyResponse) {}
rpc ScheduleTraining(UpdateHourRequest) returns (EmptyResponse) {}
rpc CancelTraining(UpdateHourRequest) returns (EmptyResponse) {}
rpc MakeHourAvailable(UpdateHourRequest) returns (EmptyResponse) {}
}

message IsHourAvailableRequest {
Expand All @@ -19,9 +21,6 @@ message IsHourAvailableResponse {

message UpdateHourRequest {
google.protobuf.Timestamp time = 1;

bool has_training_scheduled = 2;
bool available = 3;
}

message EmptyResponse {}
2 changes: 1 addition & 1 deletion docker/app/start.sh
Original file line number Diff line number Diff line change
@@ -1 +1 @@
go run *.go
go run .
151 changes: 103 additions & 48 deletions internal/common/genproto/trainer/trainer.pb.go

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

74 changes: 74 additions & 0 deletions internal/trainer/domain/hour/availability.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package hour

import "github.com/pkg/errors"

// Availability is enum.
//
// Using struct instead of `type Availability string` for enums allows us to ensure,
// that we have full control of what values are possible.
// With `type Availability string` you are able to create `Availability("i_can_put_anything_here")`
type Availability struct {
a string
}

// Every type in Go have zero value. In that case it's `Availability{}`.
// It's always a good idea to check if provided value is not zero!
func (h Availability) IsZero() bool {
return h == Availability{}
}

var (
Available = Availability{"available"}
NotAvailable = Availability{"not_available"}
TrainingScheduled = Availability{"training_scheduled"}
)

var (
ErrTrainingScheduled = errors.New("unable to modify hour, because scheduled training")
ErrNoTrainingScheduled = errors.New("training is not scheduled")
ErrHourNotAvailable = errors.New("hour is not available")
)

func (h Hour) IsAvailable() bool {
return h.availability == Available
}

func (h Hour) HasTrainingScheduled() bool {
return h.availability == TrainingScheduled
}

func (h *Hour) MakeNotAvailable() error {
if h.HasTrainingScheduled() {
return ErrTrainingScheduled
}

h.availability = NotAvailable
return nil
}

func (h *Hour) MakeAvailable() error {
if h.HasTrainingScheduled() {
return ErrTrainingScheduled
}

h.availability = Available
return nil
}

func (h *Hour) ScheduleTraining() error {
if !h.IsAvailable() {
return ErrHourNotAvailable
}

h.availability = TrainingScheduled
return nil
}

func (h *Hour) CancelTraining() error {
if !h.HasTrainingScheduled() {
return ErrNoTrainingScheduled
}

h.availability = Available
return nil
}
Loading

0 comments on commit 0249977

Please sign in to comment.