diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..92714be --- /dev/null +++ b/.editorconfig @@ -0,0 +1,79 @@ +root = true + +[*] +charset = utf-8 + +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +indent_style = space +indent_size = 4 + +[*.mod] +indent_style = tab + +[{Makefile,**.mk}] +indent_style = tab + +[*.go] +indent_style = tab + +[*.css] +indent_size = 2 + +[*.proto] +indent_size = 2 + +[*.ftl] +indent_size = 2 + +[*.toml] +indent_size = 2 + +[*.swift] +indent_size = 4 + +[*.tmpl] +indent_size = 2 + +[*.js] +indent_size = 2 +block_comment_start = /* +block_comment_end = */ + +[*.{html,htm}] +indent_size = 2 + +[*.bat] +end_of_line = crlf + +[*.{yml,yaml}] +indent_size = 2 + +[*.json] +indent_size = 2 + +[.{babelrc,eslintrc,prettierrc}] +indent_size = 2 + +[{Fastfile,.buckconfig,BUCK}] +indent_size = 2 + +[*.diff] +indent_size = 1 + +[*.m] +indent_size = 1 +indent_style = space +block_comment_start = /** +block_comment = * +block_comment_end = */ + +[*.java] +indent_size = 4 +indent_style = space +block_comment_start = /** +block_comment = * +block_comment_end = */ + diff --git a/ddd-domain-gen/go.sum b/ddd-domain-gen/go.sum index 493f020..35a0714 100644 --- a/ddd-domain-gen/go.sum +++ b/ddd-domain-gen/go.sum @@ -11,6 +11,7 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -34,6 +35,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/dave/jennifer v1.4.1 h1:XyqG6cn5RQsTj3qlWQTKlRGAyrTcsk1kUmWdZBzRjDw= github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpTVGlwA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -66,6 +68,7 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -92,18 +95,22 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -130,6 +137,7 @@ github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -148,7 +156,9 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -169,6 +179,7 @@ github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -287,6 +298,7 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= diff --git a/ddd-domain-gen/pkg/generate/main.go b/ddd-domain-gen/pkg/generate/main.go index 6bcabc5..05525a4 100644 --- a/ddd-domain-gen/pkg/generate/main.go +++ b/ddd-domain-gen/pkg/generate/main.go @@ -8,6 +8,7 @@ import ( "go/types" "os" "path/filepath" + "reflect" "regexp" "strings" @@ -19,9 +20,26 @@ func Main(sourceTypeName string) error { // Get the package of the file with go:generate comment goPackage := os.Getenv("GOPACKAGE") + path, err := os.Getwd() + if err != nil { + return err + } + + // Build the target file name + goFile := os.Getenv("GOFILE") + ext := filepath.Ext(goFile) + baseFilename := goFile[0 : len(goFile)-len(ext)] + targetFilename := baseFilename + "_gen.go" + + // Remove existing target file (before loading the package) + if _, err := os.Stat(targetFilename); err == nil { + if err := os.Remove(targetFilename); err != nil { + return err + } + } // Inspect package and use type checker to infer imported types - pkg, err := loadPackage(goPackage) + pkg, err := loadPackage(path) if err != nil { return err } @@ -44,30 +62,37 @@ func Main(sourceTypeName string) error { } // Generate code using jennifer - err = generate(goPackage, sourceTypeName, structType) + err = generate(goPackage, targetFilename, sourceTypeName, structType) if err != nil { return err } return nil } -// Use a simple regexp pattern to match tag values +// StructTag Key var ( - structRequiredTagPattern = regexp.MustCompile(`required:"([^"]+)"`) + structTagGenKey = "gen" + structTagDDDKey = "ddd" +) + +// A simple regexp pattern to match tag values +var ( + structRequiredTagPattern = regexp.MustCompile(`required'([^']+)'`) structPrivateTagPattern = regexp.MustCompile(`private`) - structGenGetterTagPattern = regexp.MustCompile(`gen-getter`) + structGenGetterTagPattern = regexp.MustCompile(`getter`) ) -func generate(goPackage, sourceTypeName string, structType *types.Struct) error { +func generate(goPackage, targetFilename, sourceTypeName string, structType *types.Struct) error { // Start a new file in this package + // return fmt.Errorf(goPackage) f := NewFile(goPackage) // Add a package comment, so IDEs detect files as generated f.PackageComment("Code generated by ddd-domain-gen, DO NOT EDIT.") - f.Line() f.Comment("Generators ...") + f.Line() // 1. define code region variables var ( @@ -83,19 +108,25 @@ func generate(goPackage, sourceTypeName string, structType *types.Struct) error // 2. iterate over struct fields and populate those variables for i := 0; i < structType.NumFields(); i++ { field := structType.Field(i) - tagValue := structType.Tag(i) + tag := reflect.StructTag(structType.Tag(i)) // 2.1 match default getter creation to fields - genGetterMatchs := structGenGetterTagPattern.FindStringSubmatch(tagValue) - if genGetterMatchs != nil { - genGetterFields = append(genGetterFields, field) + if structTagGenKeyValue, ok := tag.Lookup(structTagGenKey); ok { + if matches := structGenGetterTagPattern.FindStringSubmatch(structTagGenKeyValue); matches != nil { + genGetterFields = append(genGetterFields, field) + } } // 2.2 separate private and public fields var private bool - privateMatchs := structPrivateTagPattern.FindStringSubmatch(tagValue) - if privateMatchs != nil { - private = true + var requiredMatches []string + if structTagDDDKeyValue, ok := tag.Lookup(structTagDDDKey); ok { + if matches := structPrivateTagPattern.FindStringSubmatch(structTagDDDKeyValue); matches != nil { + private = true + } + requiredMatches = structRequiredTagPattern.FindStringSubmatch(structTagDDDKeyValue) + } + if private { privateParams = append(privateParams, Id(field.Name()).Id(field.Type().String())) privateFields = append(privateFields, field) } else { @@ -104,7 +135,6 @@ func generate(goPackage, sourceTypeName string, structType *types.Struct) error } // 2.2 generate required validation code (error if also private) - requiredMatches := structRequiredTagPattern.FindStringSubmatch(tagValue) if requiredMatches != nil { if private { return fmt.Errorf("private field %s cannot be required", field.Name()) @@ -129,7 +159,10 @@ func generate(goPackage, sourceTypeName string, structType *types.Struct) error f.Commentf("New returns a guaranteed-to-be-valid %s or an error", sourceTypeName) f.Func().Id("New").Params( publicParams..., - ).Op("*").Id(sourceTypeName).Err().BlockFunc(func(g *Group) { + ).Call( + Op("*").Id(sourceTypeName), + Error(), + ).BlockFunc(func(g *Group) { for _, code := range publicValidations { g.Add(code) } @@ -139,17 +172,17 @@ func generate(goPackage, sourceTypeName string, structType *types.Struct) error d[Id(fld.Name())] = Id(fld.Name()) } }), - )) + ), Nil()) }) // -- Add MustNew() constructor f.Commentf("MustNew returns a guaranteed-to-be-valid %s or panics", sourceTypeName) f.Func().Id("MustNew").Params( publicParams..., - ).Parens( + ).Call( Op("*").Id(sourceTypeName), ).Block( - Id(sF).Err().Op(":=").Id("New").CallFunc(func(g *Group) { + Id(sF).Op(",").Err().Op(":=").Id("New").CallFunc(func(g *Group) { for _, fld := range publicFields { g.Id(fld.Name()) } @@ -160,8 +193,8 @@ func generate(goPackage, sourceTypeName string, structType *types.Struct) error Return(Id(sF)), ) - f.Line() f.Comment("Marshalers ...") + f.Line() // -- Add UnmarshalFromRepository() unmarshaler f.Commentf("UnmarshalFromRepository unmarshals %s from the repository so that non-constructable", sourceTypeName) @@ -171,7 +204,7 @@ func generate(goPackage, sourceTypeName string, structType *types.Struct) error f.Comment("Reason: This method initializes private state, so you could corrupt the domain.") f.Func().Id("UnmarshalFromRepository").Params( allParams..., - ).Op("*").Id(sourceTypeName).Err().BlockFunc(func(g *Group) { + ).Op("*").Id(sourceTypeName).BlockFunc(func(g *Group) { g.Id(sF).Op(":=").Id("MustNew").CallFunc(func(g *Group) { for _, fld := range publicFields { g.Id(fld.Name()) @@ -183,24 +216,18 @@ func generate(goPackage, sourceTypeName string, structType *types.Struct) error g.Return(Id(sF)) }) - f.Line() f.Comment("Getters ...") + f.Line() for _, fld := range genGetterFields { fN := strings.Title(fld.Name()) f.Commentf("%s returns %s value", fN, fld.Name()) f.Func().Params( - Id(sF), Id(sourceTypeName), - ).Id(fN).Op("*").Id(fld.Type().String()).Block( - Return(Id(sF).Dot(fld.Name()).Id(fld.Name())), + Id(sF).Op("*").Id(sourceTypeName), + ).Id(fN).Params().Id(fld.Type().String()).Block( + Return(Id(sF).Dot(fld.Name())), ) } - // Build the target file name - goFile := os.Getenv("GOFILE") - ext := filepath.Ext(goFile) - baseFilename := goFile[0 : len(goFile)-len(ext)] - targetFilename := baseFilename + "_gen.go" - // Write generated file return f.Save(targetFilename) } diff --git a/ddd-domain-gen/tests/account.go b/ddd-domain-gen/tests/account.go new file mode 100644 index 0000000..cc8e125 --- /dev/null +++ b/ddd-domain-gen/tests/account.go @@ -0,0 +1,10 @@ +package tests + +//go:generate go run ../main.go -t Account +type Account struct { + uuid *string `gen:"getter" ddd:"required'field uuid is missing'"` + holder *string `gen:"getter" ddd:"required'field holder is missing'"` + address *string `gen:"getter"` + balance *int64 `ddd:"private"` // read via domain logic: don't generate default getter + values *[]int64 `ddd:"private" gen:"getter"` +} diff --git a/ddd-domain-gen/tests/account_gen.go b/ddd-domain-gen/tests/account_gen.go new file mode 100644 index 0000000..02796df --- /dev/null +++ b/ddd-domain-gen/tests/account_gen.go @@ -0,0 +1,66 @@ +// Code generated by ddd-domain-gen, DO NOT EDIT. +package tests + +import "errors" + +// Generators ... + +// New returns a guaranteed-to-be-valid Account or an error +func New(uuid *string, holder *string, address *string) (*Account, error) { + if uuid == nil { + return nil, errors.New("field uuid is missing") + } + if holder == nil { + return nil, errors.New("field holder is missing") + } + return &Account{ + address: address, + holder: holder, + uuid: uuid, + }, nil +} + +// MustNew returns a guaranteed-to-be-valid Account or panics +func MustNew(uuid *string, holder *string, address *string) *Account { + a, err := New(uuid, holder, address) + if err != nil { + panic(err) + } + return a +} + +// Marshalers ... + +// UnmarshalFromRepository unmarshals Account from the repository so that non-constructable +// private fields can still be initialized from (private) repository state +// +// Important: DO NEVER USE THIS METHOD EXCEPT FROM THE REPOSITORY +// Reason: This method initializes private state, so you could corrupt the domain. +func UnmarshalFromRepository(uuid *string, holder *string, address *string, balance *int64, values *[]int64) *Account { + a := MustNew(uuid, holder, address) + a.balance = balance + a.values = values + return a +} + +// Getters ... + +// Uuid returns uuid value +func (a *Account) Uuid() *string { + return a.uuid +} + +// Holder returns holder value +func (a *Account) Holder() *string { + return a.holder +} + +// Address returns address value +func (a *Account) Address() *string { + return a.address +} + +// Values returns values value +func (a *Account) Values() *[]int64 { + return a.values +}