├── .gitignore
├── LICENSE
├── README.md
├── cargo
├── app
│ └── service
│ │ └── cargo_api.go
├── domain
│ ├── model
│ │ ├── base
│ │ │ ├── aggregate_root.go
│ │ │ ├── entity.go
│ │ │ └── value_object.go
│ │ ├── cargo.go
│ │ ├── cargo_factory.go
│ │ ├── cargo_provider.go
│ │ ├── cargo_repo.go
│ │ └── delivery.go
│ └── service
│ │ └── cargo_service.go
├── infra
│ ├── cargo_provider_impl.go
│ └── cargo_repo_impl.go
└── test
│ └── cargo_test.go
├── counting-shapes
├── app
│ └── service
│ │ └── counting_shapes.go
├── domain
│ ├── model
│ │ ├── set.go
│ │ ├── set_test.go
│ │ └── spec.go
│ └── service
│ │ └── counting_shapes.go
└── test
│ └── counting_shapes_test.go
└── shapes.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # temp
2 | tmp/
3 | output/
4 | build/
5 |
6 | # mac
7 | .DS_Store
8 |
9 | # python
10 | *.pyc
11 |
12 | # clion
13 | .idea/
14 | *.xml
15 |
16 | # eclipse
17 | .settings/
18 | .project
19 | .cproject
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Zhang Xiaolong
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DDD sample
2 |
3 |
4 | ### cargo
5 |
6 | DDD sample with OO
7 |
8 | ## counting shapes
9 |
10 | DDD sample with FP
11 |
12 |
13 |
14 | The first game:
15 | >How many triangles can you see?
24, details as follows:
[abc abd abe acd ace ade aef aeg aeh afg afh agh ahi ahj ahk aij aik ajk beh ceg def ehk fhj ghi]
16 |
17 | The second game:
18 | >How many quadrangles can you see?
18, details as follows:
[aceh adeg adeh afhk aghj aghk bcgh bcih bdfh bdjh bekh cdfg cdji ceki dekj efjk egik fgij]
19 |
--------------------------------------------------------------------------------
/cargo/app/service/cargo_api.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "github.com/agiledragon/ddd-sample-in-golang/cargo/domain/service"
5 | )
6 |
7 | func CreateCargo(cargoId string, afterDays uint) {
8 | service.GetCargoService().Create(cargoId, afterDays)
9 | }
10 |
11 | func DelayCargo(cargoId string, days uint) {
12 | service.GetCargoService().Delay(cargoId, days)
13 | }
14 |
15 | func GetCargoAfterDays(cargoId string) uint {
16 | return service.GetCargoService().GetAfterDays(cargoId)
17 | }
18 |
19 | func DestroyCargo(cargoId string) {
20 | service.GetCargoService().DestroyCargo(cargoId)
21 | }
22 |
--------------------------------------------------------------------------------
/cargo/domain/model/base/aggregate_root.go:
--------------------------------------------------------------------------------
1 | package base
2 |
3 | type AggregateRoot struct {
4 | Entity
5 | }
6 |
7 | func NewAggregateRoot(id string) AggregateRoot {
8 | return AggregateRoot{NewEntity(id)}
9 | }
10 |
--------------------------------------------------------------------------------
/cargo/domain/model/base/entity.go:
--------------------------------------------------------------------------------
1 | package base
2 |
3 | type Entity struct {
4 | id string
5 | }
6 |
7 | func NewEntity(id string) Entity {
8 | return Entity{id: id}
9 | }
10 |
11 | func (this *Entity) Id() string {
12 | return this.id
13 | }
14 |
15 | func (this *Entity) Equal(other *Entity) bool {
16 | return this.id == other.id
17 | }
18 |
19 | func (this *Entity) NotEqual(other *Entity) bool {
20 | return !this.Equal(other)
21 | }
22 |
--------------------------------------------------------------------------------
/cargo/domain/model/base/value_object.go:
--------------------------------------------------------------------------------
1 | package base
2 |
3 | type ValueObject struct {
4 | }
5 |
--------------------------------------------------------------------------------
/cargo/domain/model/cargo.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "github.com/agiledragon/ddd-sample-in-golang/cargo/domain/model/base"
5 | )
6 |
7 | type Cargo struct {
8 | base.AggregateRoot
9 | Delivery Delivery
10 | }
11 |
12 | func newCargo(cargoId string, delivery Delivery) *Cargo {
13 | return &Cargo{AggregateRoot: base.NewAggregateRoot(cargoId), Delivery: delivery}
14 | }
15 |
16 | func (this *Cargo) Delay(days uint) {
17 | afterDays := this.GetAfterDays() + days
18 | this.Delivery = Delivery{AfterDays: afterDays}
19 | }
20 |
21 | func (this *Cargo) GetAfterDays() uint {
22 | return this.Delivery.AfterDays
23 | }
24 |
--------------------------------------------------------------------------------
/cargo/domain/model/cargo_factory.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type CargoFactory struct {
4 | }
5 |
6 | func (this CargoFactory) Create(cargoId string, afterDays uint) *Cargo {
7 | delivery := Delivery{AfterDays: afterDays}
8 | return newCargo(cargoId, delivery)
9 | }
10 |
--------------------------------------------------------------------------------
/cargo/domain/model/cargo_provider.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type CargoProvider interface {
4 | Confirm(cargo *Cargo)
5 | }
6 |
7 | var p CargoProvider = nil
8 |
9 | func SetCargoProvider(provider CargoProvider) {
10 | p = provider
11 | }
12 |
13 | func GetCargoProvider() CargoProvider {
14 | return p
15 | }
16 |
--------------------------------------------------------------------------------
/cargo/domain/model/cargo_repo.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type CargoRepo interface {
4 | Add(cargo *Cargo)
5 | Get(cargoId string) *Cargo
6 | Update(cargo *Cargo)
7 | Remove(cargoId string)
8 | }
9 |
10 | var r CargoRepo = nil
11 |
12 | func SetCargoRepo(repo CargoRepo) {
13 | r = repo
14 | }
15 |
16 | func GetCargoRepo() CargoRepo {
17 | return r
18 | }
19 |
--------------------------------------------------------------------------------
/cargo/domain/model/delivery.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "github.com/agiledragon/ddd-sample-in-golang/cargo/domain/model/base"
5 | )
6 |
7 | type Delivery struct {
8 | base.ValueObject
9 | AfterDays uint
10 | }
11 |
--------------------------------------------------------------------------------
/cargo/domain/service/cargo_service.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "github.com/agiledragon/ddd-sample-in-golang/cargo/domain/model"
5 | "sync"
6 | )
7 |
8 | type CargoService struct {
9 | repo model.CargoRepo
10 | provider model.CargoProvider
11 | }
12 |
13 | var cs = &CargoService{}
14 | var once sync.Once
15 |
16 | func GetCargoService() *CargoService {
17 | once.Do(func() {
18 | cs.repo = model.GetCargoRepo()
19 | cs.provider = model.GetCargoProvider()
20 | })
21 | return cs
22 | }
23 |
24 | func (this *CargoService) Create(cargoId string, afterDays uint) {
25 | cargo := model.CargoFactory{}.Create(cargoId, afterDays)
26 | this.repo.Add(cargo)
27 | this.provider.Confirm(cargo)
28 | }
29 |
30 | func (this *CargoService) Delay(cargoId string, days uint) {
31 | cargo := this.repo.Get(cargoId)
32 | if cargo == nil {
33 | panic("not found cargo by cargoId")
34 | }
35 | cargo.Delay(days)
36 | this.repo.Update(cargo)
37 | this.provider.Confirm(cargo)
38 | }
39 |
40 | func (this *CargoService) GetAfterDays(cargoId string) uint {
41 | cargo := this.repo.Get(cargoId)
42 | if cargo == nil {
43 | panic("not found cargo by cargoId")
44 | }
45 | return cargo.GetAfterDays()
46 | }
47 |
48 | func (this *CargoService) DestroyCargo(cargoId string) {
49 | this.repo.Remove(cargoId)
50 | }
51 |
--------------------------------------------------------------------------------
/cargo/infra/cargo_provider_impl.go:
--------------------------------------------------------------------------------
1 | package infra
2 |
3 | import "github.com/agiledragon/ddd-sample-in-golang/cargo/domain/model"
4 |
5 | type CargoProviderImpl struct {
6 | }
7 |
8 | func (this *CargoProviderImpl) Confirm(cargo *model.Cargo) {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/cargo/infra/cargo_repo_impl.go:
--------------------------------------------------------------------------------
1 | package infra
2 |
3 | import "github.com/agiledragon/ddd-sample-in-golang/cargo/domain/model"
4 |
5 | type CargoRepoImpl struct {
6 | }
7 |
8 | func (this *CargoRepoImpl) Add(cargo *model.Cargo) {
9 |
10 | }
11 |
12 | func (this *CargoRepoImpl) Get(cargoId string) *model.Cargo {
13 | return nil
14 | }
15 |
16 | func (this *CargoRepoImpl) Update(cargo *model.Cargo) {
17 |
18 | }
19 |
20 | func (this *CargoRepoImpl) Remove(CargoId string) {
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/cargo/test/cargo_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | "github.com/agiledragon/ddd-sample-in-golang/cargo/app/service"
5 | "github.com/agiledragon/ddd-sample-in-golang/cargo/domain/model"
6 | . "github.com/smartystreets/goconvey/convey"
7 | "testing"
8 | )
9 |
10 | type SpyCargoProvider struct {
11 | cargoId string
12 | afterDays uint
13 | }
14 |
15 | func (this *SpyCargoProvider) Confirm(cargo *model.Cargo) {
16 | this.cargoId = cargo.Id()
17 | this.afterDays = cargo.GetAfterDays()
18 | }
19 |
20 | type FakeCargoRepo struct {
21 | cargoes map[string]*model.Cargo
22 | }
23 |
24 | func (this *FakeCargoRepo) Add(cargo *model.Cargo) {
25 | this.cargoes[cargo.Id()] = cargo
26 | }
27 |
28 | func (this *FakeCargoRepo) Get(cargoId string) *model.Cargo {
29 | return this.cargoes[cargoId]
30 | }
31 |
32 | func (this *FakeCargoRepo) Update(cargo *model.Cargo) {
33 | this.cargoes[cargo.Id()] = cargo
34 | }
35 |
36 | func (this *FakeCargoRepo) Remove(cargoId string) {
37 | delete(this.cargoes, cargoId)
38 | }
39 |
40 | func TestCargo(t *testing.T) {
41 | provider := &SpyCargoProvider{}
42 | model.SetCargoProvider(provider)
43 | repo := &FakeCargoRepo{make(map[string]*model.Cargo)}
44 | model.SetCargoRepo(repo)
45 | const cargoId = "1"
46 |
47 | Convey("TestCargo", t, func() {
48 |
49 | Convey("create cargo", func() {
50 | const afterDays = 10
51 | service.CreateCargo(cargoId, afterDays)
52 | So(provider.cargoId, ShouldEqual, cargoId)
53 | So(provider.afterDays, ShouldEqual, afterDays)
54 | So(service.GetCargoAfterDays(cargoId), ShouldEqual, afterDays)
55 | service.DestroyCargo(cargoId)
56 | })
57 |
58 | Convey("delay cargo", func() {
59 | const afterDays = 20
60 | const days = 5
61 | service.CreateCargo(cargoId, afterDays)
62 | service.DelayCargo(cargoId, days)
63 | So(provider.cargoId, ShouldEqual, cargoId)
64 | So(provider.afterDays, ShouldEqual, afterDays+days)
65 | So(service.GetCargoAfterDays(cargoId), ShouldEqual, afterDays+days)
66 | service.DestroyCargo(cargoId)
67 | })
68 | })
69 | }
70 |
--------------------------------------------------------------------------------
/counting-shapes/app/service/counting_shapes.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "github.com/agiledragon/ddd-sample-in-golang/counting-shapes/domain/service"
5 | )
6 |
7 | func CountingTriangles(points string, lines []string) int {
8 | return len(service.CountingTriangles(points, lines))
9 | }
10 |
11 | func CountingQuadrangles(points string, lines []string) int {
12 | return len(service.CountingQuadrangles(points, lines))
13 | }
--------------------------------------------------------------------------------
/counting-shapes/domain/model/set.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "strings"
5 | //"fmt"
6 | )
7 |
8 | type Point = byte
9 | type Line = string
10 | type Points = string
11 |
12 |
13 | func belong(points Points, lines []Line) bool {
14 | flag := false
15 | for _, line := range lines {
16 | flag = true
17 | for _, point := range points {
18 | if !strings.ContainsRune(line, point) {
19 | flag = false
20 | break
21 | }
22 | }
23 | if flag {
24 | return true
25 | }
26 | }
27 | return false
28 | }
29 |
30 | func Subset(points Points, n int) []Points {
31 | l := len(points)
32 | if l < n {
33 | return nil
34 | }
35 | if l == n {
36 | return []string{points}
37 | }
38 |
39 | results := make([]Points, 0)
40 | if n == 1 {
41 | for i := range points {
42 | results = append(results, Points([]byte{points[i]}))
43 | }
44 | return results
45 | }
46 |
47 | firsts := Subset(points[1:], n - 1)
48 | for _, first := range firsts {
49 | results = append(results, Points([]byte{points[0]}) + first)
50 | }
51 |
52 | lasts := Subset(points[1:], n)
53 | results = append(results, lasts...)
54 |
55 | return results
56 | }
57 |
58 | func hasConnected(lines []Line) func(x, y Point) bool {
59 | return func(x, y Point) bool {
60 | points := make([]Point, 2)
61 | points[0] = x
62 | points[1] = y
63 | return belong(Points(points), lines)
64 | }
65 | }
66 |
67 | func inSameLine(lines []Line) func(x, y, z Point) bool {
68 | return func(x, y, z Point) bool {
69 | points := make([]Point, 3)
70 | points[0] = x
71 | points[1] = y
72 | points[2] = z
73 | return belong(Points(points), lines)
74 | }
75 | }
76 |
77 | func not(flag bool) bool {
78 | return !flag
79 | }
80 |
81 | func ringOrderConnected(lines []Line) func(points ...Point) bool {
82 | connected := hasConnected(lines)
83 |
84 | return func(points ...Point) bool {
85 | // fmt.Println("ring:", points)
86 | prev := points[0]
87 | for i := 1; i < len(points); i++ {
88 | next := points[i]
89 | if !connected(prev, next) {
90 | return false
91 | }
92 | prev = next
93 | }
94 | first := points[0]
95 | last := points[len(points) - 1]
96 | if connected(last, first) {
97 | return true
98 | }
99 | return false
100 | }
101 | }
102 |
103 | func hasCrossConnected(lines []Line) func(ls, rs Points) bool {
104 | return func(ls, rs Points) bool {
105 | flag := false
106 | lfound := false
107 | rfound := false
108 | ll := ""
109 | rl := ""
110 | for _, line := range lines {
111 | if !lfound {
112 | flag = true
113 | for _, l := range ls {
114 | if !strings.ContainsRune(line, l) {
115 | flag = false
116 | break
117 | }
118 | }
119 | if flag {
120 | ll = line
121 | lfound = true
122 | }
123 | }
124 |
125 | if !rfound {
126 | flag = true
127 | for _, r := range rs {
128 | if !strings.ContainsRune(line, r) {
129 | flag = false
130 | break
131 | }
132 | }
133 | if flag {
134 | rl = line
135 | rfound = true
136 | }
137 | }
138 |
139 | if lfound && rfound {
140 | break
141 | }
142 |
143 | }
144 |
145 | //fmt.Println("ll:", ll)
146 | //fmt.Println("rl:", rl)
147 |
148 | lstart := 0
149 | lend := 0
150 | for i := range ll {
151 | if ll[i] == ls[0] {
152 | lstart = i
153 | } else if ll[i] == ls[1] {
154 | lend = i
155 | }
156 | }
157 | if lstart > lend {
158 | lstart, lend = lend, lstart
159 | }
160 | //fmt.Println("lstart, lend:", lstart, lend)
161 |
162 |
163 | rstart := 0
164 | rend := 0
165 | for i := range rl {
166 | if rl[i] == rs[0] {
167 | rstart = i
168 | } else if rl[i] == rs[1] {
169 | rend = i
170 | }
171 | }
172 | if rstart > rend {
173 | rstart, rend = rend, rstart
174 | }
175 | //fmt.Println("rstart, rend:", rstart, rend)
176 | for i := 1; i < lend - lstart; i++ {
177 | for j := 1; j < rend - rstart; j++ {
178 | //fmt.Println("ll[i]:", ll[lstart + i])
179 | //fmt.Println("rl[j]:", rl[rstart + j])
180 | if ll[lstart + i] == rl[rstart + j] {
181 | return true
182 | }
183 | }
184 | }
185 | return false
186 | }
187 | }
--------------------------------------------------------------------------------
/counting-shapes/domain/model/set_test.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | . "github.com/smartystreets/goconvey/convey"
5 | "testing"
6 | )
7 |
8 | func TestRingConnected(t *testing.T) {
9 | lines := []string{"abh", "acgi", "adfj", "aek", "bcde", "hgfe", "hijk"}
10 | ring_connected := ringOrderConnected(lines)
11 | Convey("TestRingConnected", t, func() {
12 |
13 | Convey("succ", func() {
14 | So(ring_connected([]Point("abc")...), ShouldBeTrue)
15 | So(ring_connected([]Point("bcgh")...), ShouldBeTrue)
16 | So(ring_connected([]Point("cdfg")...), ShouldBeTrue)
17 | So(ring_connected([]Point("abeg")...), ShouldBeTrue)
18 | So(ring_connected([]Point("abhg")...), ShouldBeTrue)
19 | So(ring_connected([]Point("defj")...), ShouldBeTrue)
20 | })
21 |
22 | Convey("failed", func() {
23 | So(ring_connected([]Point("acf")...), ShouldBeFalse)
24 | So(ring_connected([]Point("bcg")...), ShouldBeFalse)
25 | So(ring_connected([]Point("defk")...), ShouldBeFalse)
26 | })
27 |
28 | })
29 | }
30 |
31 | func TestHasCrossConnected(t *testing.T) {
32 | lines := []string{"abh", "acgi", "adfj", "aek", "bcde", "hgfe", "hijk"}
33 | cross_connected := hasCrossConnected(lines)
34 | Convey("TestHasCrossConnected", t, func() {
35 |
36 | Convey("succ", func() {
37 | So(cross_connected("ag", "bd"), ShouldBeTrue)
38 | So(cross_connected("af", "ce"), ShouldBeTrue)
39 | So(cross_connected("af", "be"), ShouldBeTrue)
40 | So(cross_connected("ai", "eh"), ShouldBeTrue)
41 | })
42 |
43 | Convey("failed", func() {
44 | So(cross_connected("bc", "hg"), ShouldBeFalse)
45 | So(cross_connected("fj", "ek"), ShouldBeFalse)
46 | })
47 |
48 | })
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/counting-shapes/domain/model/spec.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | func IsTriangle(points Points, lines []Line) bool {
4 | ring_order_connected := ringOrderConnected(lines)
5 | in_same_line := inSameLine(lines)
6 |
7 | a := points[0]
8 | b := points[1]
9 | c := points[2]
10 |
11 | return ring_order_connected(a, b, c) &&
12 | not(in_same_line(a, b, c))
13 | }
14 |
15 | func IsQuadrangle(points Points, lines []Line) bool {
16 | ring_order_connected := ringOrderConnected(lines)
17 | cross_connected := hasCrossConnected(lines)
18 | in_same_line := inSameLine(lines)
19 |
20 | a := points[0]
21 | b := points[1]
22 | c := points[2]
23 | d := points[3]
24 | ab := Points([]Point{a, b})
25 | cd := Points([]Point{c, d})
26 | ad := Points([]Point{a, d})
27 | bc := Points([]Point{b, c})
28 |
29 | return ring_order_connected(a, b, c, d) &&
30 | not(cross_connected(ab, cd)) &&
31 | not(cross_connected(ad, bc)) &&
32 | not(in_same_line(a, b, c)) &&
33 | not(in_same_line(a, b, d)) &&
34 | not(in_same_line(a, c, d)) &&
35 | not(in_same_line(b, c, d))
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/counting-shapes/domain/service/counting_shapes.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "github.com/agiledragon/ddd-sample-in-golang/counting-shapes/domain/model"
5 | // "fmt"
6 | "fmt"
7 | )
8 |
9 | func CountingTriangles(points model.Points, lines []model.Line) []model.Points {
10 | sets := model.Subset(points, 3)
11 | matches := make([]model.Points, 0)
12 | for _, set := range sets {
13 | if model.IsTriangle(set, lines) {
14 | matches = append(matches, set)
15 | }
16 | }
17 | fmt.Println("matches:", matches)
18 | return matches
19 | }
20 |
21 | func CountingQuadrangles(points model.Points, lines []model.Line) []model.Points {
22 | sets := model.Subset(points, 4)
23 | matches := make([]model.Points, 0)
24 | for _, set := range sets {
25 | a := set[0]
26 | b := set[1]
27 | c := set[2]
28 | d := set[3]
29 | orderSets := []model.Points{
30 | model.Points([]model.Point{a, b, c, d}),
31 | model.Points([]model.Point{a, b, d, c}),
32 | model.Points([]model.Point{a, c, b, d}),
33 | model.Points([]model.Point{a, c, d, b}),
34 | model.Points([]model.Point{a, d, b, c}),
35 | model.Points([]model.Point{a, d, c, b}),
36 | }
37 |
38 | for _, orderSet := range orderSets {
39 | if model.IsQuadrangle(orderSet, lines) {
40 | matches = append(matches, orderSet)
41 | break
42 | }
43 | }
44 |
45 | }
46 | //fmt.Println("matches:", matches)
47 | return matches
48 | }
--------------------------------------------------------------------------------
/counting-shapes/test/counting_shapes_test.go:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import (
4 | . "github.com/smartystreets/goconvey/convey"
5 | "testing"
6 | "github.com/agiledragon/ddd-sample-in-golang/counting-shapes/app/service"
7 | )
8 |
9 | func TestCountingShapes(t *testing.T) {
10 | points := "abcdefghijk"
11 | lines := []string{"abh", "acgi", "adfj", "aek", "bcde", "hgfe", "hijk"}
12 |
13 | Convey("TestCountingShapes", t, func() {
14 |
15 | Convey("counting triangles", func() {
16 | num := service.CountingTriangles(points, lines)
17 | So(num, ShouldEqual, 24)
18 | })
19 |
20 | Convey("counting quadrangles", func() {
21 | num := service.CountingQuadrangles(points, lines)
22 | So(num, ShouldEqual, 18)
23 | })
24 | })
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/shapes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agiledragon/ddd-sample-in-golang/c1f10a224a2a45ac9dbfa77eee05e8e0dab4596b/shapes.png
--------------------------------------------------------------------------------