From cb4ec30d1b74e1d43292af539da3b2b6da8b9b85 Mon Sep 17 00:00:00 2001 From: agiledragon Date: Mon, 4 Jun 2018 01:15:50 +0800 Subject: [PATCH] init commit --- .gitignore | 19 ++++++++ LICENSE | 21 +++++++++ README.md | 3 ++ app/service/cargo_api.go | 17 ++++++++ domain/model/base/aggregate_root.go | 9 ++++ domain/model/base/entity.go | 21 +++++++++ domain/model/base/value_object.go | 5 +++ domain/model/cargo.go | 23 ++++++++++ domain/model/cargo_factory.go | 10 +++++ domain/model/cargo_provider.go | 15 +++++++ domain/model/cargo_repo.go | 18 ++++++++ domain/model/delivery.go | 11 +++++ domain/service/cargo_service.go | 44 +++++++++++++++++++ ft/cargo_test.go | 68 +++++++++++++++++++++++++++++ infra/cargo_provider_impl.go | 11 +++++ infra/cargo_repo_impl.go | 23 ++++++++++ 16 files changed, 318 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 app/service/cargo_api.go create mode 100644 domain/model/base/aggregate_root.go create mode 100644 domain/model/base/entity.go create mode 100644 domain/model/base/value_object.go create mode 100644 domain/model/cargo.go create mode 100644 domain/model/cargo_factory.go create mode 100644 domain/model/cargo_provider.go create mode 100644 domain/model/cargo_repo.go create mode 100644 domain/model/delivery.go create mode 100644 domain/service/cargo_service.go create mode 100644 ft/cargo_test.go create mode 100644 infra/cargo_provider_impl.go create mode 100644 infra/cargo_repo_impl.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..df6791e --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# temp +tmp/ +output/ +build/ + +# mac +.DS_Store + +# python +*.pyc + +# clion +.idea/ +*.xml + +# eclipse +.settings/ +.project +.cproject diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ab60297 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1afed09 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# ddd-sample-in-golang + +ddd sample diff --git a/app/service/cargo_api.go b/app/service/cargo_api.go new file mode 100644 index 0000000..acb8fff --- /dev/null +++ b/app/service/cargo_api.go @@ -0,0 +1,17 @@ +package service + +import ( + "github.com/agiledragon/ddd-sample-in-golang/domain/service" +) + +func CreateCargo(cargoId string, afterDays uint) { + service.GetCargoServiceInstance().Create(cargoId, afterDays) +} + +func DelayCargo(cargoId string, days uint) { + service.GetCargoServiceInstance().Delay(cargoId, days) +} + +func GetCargoAfterDays(cargoId string) uint { + return service.GetCargoServiceInstance().GetAfterDays(cargoId) +} \ No newline at end of file diff --git a/domain/model/base/aggregate_root.go b/domain/model/base/aggregate_root.go new file mode 100644 index 0000000..b9fa026 --- /dev/null +++ b/domain/model/base/aggregate_root.go @@ -0,0 +1,9 @@ +package base + +type AggregateRoot struct { + Entity +} + +func NewAggregateRoot(id string) AggregateRoot { + return AggregateRoot{NewEntity(id)} +} \ No newline at end of file diff --git a/domain/model/base/entity.go b/domain/model/base/entity.go new file mode 100644 index 0000000..183a0de --- /dev/null +++ b/domain/model/base/entity.go @@ -0,0 +1,21 @@ +package base + +type Entity struct { + Id string +} + +func NewEntity(id string) Entity { + return Entity{Id: id} +} + +func (t *Entity) GetId() string { + return t.Id +} + +func (t *Entity) Equal(other *Entity) bool { + return t.Id == other.Id +} + +func (t *Entity) NotEqual(other *Entity) bool { + return !t.Equal(other) +} \ No newline at end of file diff --git a/domain/model/base/value_object.go b/domain/model/base/value_object.go new file mode 100644 index 0000000..b192aa6 --- /dev/null +++ b/domain/model/base/value_object.go @@ -0,0 +1,5 @@ +package base + +type ValueObject struct { + +} \ No newline at end of file diff --git a/domain/model/cargo.go b/domain/model/cargo.go new file mode 100644 index 0000000..8771a53 --- /dev/null +++ b/domain/model/cargo.go @@ -0,0 +1,23 @@ +package model + +import ( + "github.com/agiledragon/ddd-sample-in-golang/domain/model/base" +) + +type Cargo struct { + base.AggregateRoot + Delivery Delivery +} + +func newCargo(cargoId string, delivery Delivery) *Cargo { + return &Cargo{AggregateRoot: base.NewAggregateRoot(cargoId), Delivery: delivery} +} + +func (t *Cargo) Delay(days uint) { + afterDays := t.GetAfterDays() + days + t.Delivery = Delivery{AfterDays: afterDays} +} + +func (t *Cargo) GetAfterDays() uint { + return t.Delivery.AfterDays +} \ No newline at end of file diff --git a/domain/model/cargo_factory.go b/domain/model/cargo_factory.go new file mode 100644 index 0000000..8cc5375 --- /dev/null +++ b/domain/model/cargo_factory.go @@ -0,0 +1,10 @@ +package model + +type CargoFactory struct { + +} + +func (t CargoFactory) Create(cargoId string, afterDays uint) *Cargo { + delivery := Delivery{AfterDays: afterDays} + return newCargo(cargoId, delivery) +} \ No newline at end of file diff --git a/domain/model/cargo_provider.go b/domain/model/cargo_provider.go new file mode 100644 index 0000000..fed242f --- /dev/null +++ b/domain/model/cargo_provider.go @@ -0,0 +1,15 @@ +package model + +type CargoProvider interface { + Confirm(cargo *Cargo) +} + +var p CargoProvider = nil + +func SetCargoProvider(provider CargoProvider) { + p = provider +} + +func GetCargoProvider() CargoProvider { + return p +} diff --git a/domain/model/cargo_repo.go b/domain/model/cargo_repo.go new file mode 100644 index 0000000..f9e6085 --- /dev/null +++ b/domain/model/cargo_repo.go @@ -0,0 +1,18 @@ +package model + +type CargoRepo interface { + Add(cargo *Cargo) + Get(cargoId string) *Cargo + Update(cargo *Cargo) + Remove(cargoId string) +} + +var r CargoRepo = nil + +func SetCargoRepo(repo CargoRepo) { + r = repo +} + +func GetCargoRepo() CargoRepo { + return r +} diff --git a/domain/model/delivery.go b/domain/model/delivery.go new file mode 100644 index 0000000..5f11c04 --- /dev/null +++ b/domain/model/delivery.go @@ -0,0 +1,11 @@ +package model + +import ( + "github.com/agiledragon/ddd-sample-in-golang/domain/model/base" +) + +type Delivery struct { + base.ValueObject + AfterDays uint +} + diff --git a/domain/service/cargo_service.go b/domain/service/cargo_service.go new file mode 100644 index 0000000..6e5f1c7 --- /dev/null +++ b/domain/service/cargo_service.go @@ -0,0 +1,44 @@ +package service + +import ( + "github.com/agiledragon/ddd-sample-in-golang/domain/model" + "sync" +) + +type CargoService struct { + repo model.CargoRepo + provider model.CargoProvider +} + +var cs = &CargoService{} +var once sync.Once +func GetCargoServiceInstance() *CargoService { + once.Do(func() { + cs.repo = model.GetCargoRepo() + cs.provider = model.GetCargoProvider() + }) + return cs +} + +func (t *CargoService) Create(cargoId string, afterDays uint) { + cargo := model.CargoFactory{}.Create(cargoId, afterDays) + t.repo.Add(cargo) + t.provider.Confirm(cargo) +} + +func (t *CargoService) Delay(cargoId string, days uint) { + cargo := t.repo.Get(cargoId) + if cargo != nil { + cargo.Delay(days) + t.repo.Update(cargo) + t.provider.Confirm(cargo) + } +} + +func (t *CargoService) GetAfterDays(cargoId string) uint { + cargo := t.repo.Get(cargoId) + if cargo != nil { + return cargo.GetAfterDays() + } + panic("invalid cargoId") +} \ No newline at end of file diff --git a/ft/cargo_test.go b/ft/cargo_test.go new file mode 100644 index 0000000..39bfa53 --- /dev/null +++ b/ft/cargo_test.go @@ -0,0 +1,68 @@ +package ft + +import ( + "testing" + . "github.com/smartystreets/goconvey/convey" + "github.com/agiledragon/ddd-sample-in-golang/domain/model" + "github.com/agiledragon/ddd-sample-in-golang/app/service" +) + +type SpyCargoProvider struct { + cargoId string + afterDays uint +} + +func (t *SpyCargoProvider) Confirm(cargo *model.Cargo) { + t.cargoId = cargo.GetId() + t.afterDays = cargo.GetAfterDays() +} + +type FakeCargoRepo struct { + cargoes map[string]*model.Cargo +} + +func (t *FakeCargoRepo) Add(cargo *model.Cargo) { + t.cargoes[cargo.GetId()] = cargo +} + +func (t *FakeCargoRepo) Get(cargoId string) *model.Cargo { + return t.cargoes[cargoId] +} + +func (t *FakeCargoRepo) Update(cargo *model.Cargo) { + t.cargoes[cargo.GetId()] = cargo +} + +func (t *FakeCargoRepo) Remove(cargoId string) { + delete(t.cargoes, cargoId) +} + +func TestCargo(t *testing.T) { + provider := &SpyCargoProvider{} + model.SetCargoProvider(provider) + repo := &FakeCargoRepo{make(map[string]*model.Cargo)} + model.SetCargoRepo(repo) + const cargoId = "1" + + Convey("TestCargo", t, func() { + Convey("create cargo", func() { + const afterDays = 10 + service.CreateCargo(cargoId, afterDays) + So(provider.cargoId, ShouldEqual, cargoId) + So(provider.afterDays, ShouldEqual, afterDays) + So(service.GetCargoAfterDays(cargoId), ShouldEqual, afterDays) + }) + + Convey("delay cargo", func() { + const afterDays = 20 + const days = 5 + service.CreateCargo(cargoId, afterDays) + service.DelayCargo(cargoId, days) + So(provider.cargoId, ShouldEqual, cargoId) + So(provider.afterDays, ShouldEqual, afterDays + days) + So(service.GetCargoAfterDays(cargoId), ShouldEqual, afterDays + days) + + }) + }) +} + diff --git a/infra/cargo_provider_impl.go b/infra/cargo_provider_impl.go new file mode 100644 index 0000000..67ae8bb --- /dev/null +++ b/infra/cargo_provider_impl.go @@ -0,0 +1,11 @@ +package infra + +import "github.com/agiledragon/ddd-sample-in-golang/domain/model" + +type CargoProviderImpl struct { + +} + +func (t *CargoProviderImpl) Confirm(cargo *model.Cargo) { + +} \ No newline at end of file diff --git a/infra/cargo_repo_impl.go b/infra/cargo_repo_impl.go new file mode 100644 index 0000000..9e7e859 --- /dev/null +++ b/infra/cargo_repo_impl.go @@ -0,0 +1,23 @@ +package infra + +import "github.com/agiledragon/ddd-sample-in-golang/domain/model" + +type CargoRepoImpl struct { + +} + +func (t *CargoRepoImpl) Add(cargo *model.Cargo) { + +} + +func (t *CargoRepoImpl) Get(cargoId string) *model.Cargo { + return nil +} + +func (t *CargoRepoImpl) Update(cargo *model.Cargo) { + +} + +func (t *CargoRepoImpl) Remove(CargoId string) { + +} \ No newline at end of file