SlideShare a Scribd company logo
1 of 18
Download to read offline
"Clean" Architecture
2016, by Manfred Touron (@moul)
overview
• the "clean" architecture, "Yet Another New Architecture"
• by uncle Bob
• discovered 3 months ago at OpenClassrooms with Romain
Kuzniak
• recent, no real spec, no official implementation
• I don't use "clean" architecture in production
• I'm not a "clean" architecture expert
design slogans 1/2 1
• YAGNI (You Ain't Gonna Need It)
• KISS (Keep It Simple, Stupid)
• DRY (Don't Repeat Yourself)
• S.O.L.I.D (SRP, OCP, LS, IS, DI)
• TDD (Test Driven Development)
1
more info: http://fr.slideshare.net/RomainKuzniak/design-applicatif-avec-symfony2
design slogans 2/2 1
• BDD (Behavior Driven Development)
• DDD (Domain Driven Design)
• ...
1
more info: http://fr.slideshare.net/RomainKuzniak/design-applicatif-avec-symfony2
design types 1
• MVC
• N3 Architectures
• Domain Driven Design
• Clean Architecture
1
more info: http://fr.slideshare.net/RomainKuzniak/design-applicatif-avec-symfony2
the "clean" architecture 2
• Not a revolution, a mix of multiple existing principles
• The other designs are not "dirty" architectures
• Recent examples: Hexagonal Architecture, Onion
Architecture, Screaming Architecture, DCI, BCE
• Dependency injection at the buildtime or at leat at the
runtime init
2
https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html
./cmd/api
func main() {
// Setup gateways
var sprintsGw gateways.Sprints
if len(os.Args) > 1 && os.Args[1] == "--mem" {
// configure a memory-based sprints gateway
sprintsGw = sprintsmem.New()
} else {
// configure a sqlite-based sprints gateway
db, err := gorm.Open("sqlite3", "test.db")
if err != nil {
panic(err)
}
defer db.Close()
sprintsGw = sprintsgorm.New(db)
}
// Setup usecases
getSprint := getsprint.New(sprintsGw, getsprintdto.ResponseAssembler{})
addSprint := addsprint.New(sprintsGw, addsprintdto.ResponseAssembler{})
ping := ping.New(pingdto.ResponseAssembler{})
//closeSprint := closesprint.New(sprintsGw, closesprintdto.ResponseBuilder{})
// Setup API
gin := gin.Default()
gin.GET("/sprints/:sprint-id", apicontrollers.NewGetSprint(&getSprint).Execute)
gin.POST("/sprints", apicontrollers.NewAddSprint(&addSprint).Execute)
gin.GET("/ping", apicontrollers.NewPing(&ping).Execute)
//gin.DELETE("/sprints/:sprint-id", apicontrollers.NewCloseSprint(&closeSprint).Execute)
// Start
gin.Run()
}
./app/controllers/api
type GetSprint struct {
uc *getsprint.UseCase
}
func (ctrl *GetSprint) Execute(ctx *gin.Context) {
sprintID, err := strconv.Atoi(ctx.Param("sprint-id"))
if err != nil {
ctx.JSON(http.StatusNotFound, gin.H{"error": "Invalid 'sprint-id'"})
return
}
req := getsprintdto.RequestBuilder{}.
Create().
WithSprintID(sprintID).
Build()
resp, err := ctrl.uc.Execute(req)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("%v", err)})
return
}
ctx.JSON(http.StatusOK, gin.H{"result": GetSprintResponse{
CreatedAt: resp.GetCreatedAt(),
EffectiveClosedAt: resp.GetEffectiveClosedAt(),
ExpectedClosedAt: resp.GetExpectedClosedAt(),
Status: resp.GetStatus(),
}})
}
type GetSprintResponse struct {
CreatedAt time.Time `json:"created-at"`
EffectiveClosedAt time.Time `json:"effective-closed-at"`
ExpectedClosedAt time.Time `json:"expected-closed-at"`
Status string `json:"status"`
}
./app/repos/sprints/gorm
type Repo struct { // implements gateways.Sprints
db *gorm.DB
}
func (r Repo) Find(id int) (*entities.Sprint, error) {
obj := sprintModel{}
if err := r.db.First(&obj, "id = ?", id).Error; err != nil {
return nil, err
}
ret := entities.NewSprint()
ret.SetCreatedAt(obj.CreatedAt)
ret.SetID(int(obj.ID))
ret.SetStatus(obj.status)
ret.SetEffectiveClosedAt(obj.effectiveClosedAt)
ret.SetExpectedClosedAt(obj.expectedClosedAt)
return ret, nil
}
./bizrules/usecases/get_sprint
type UseCase struct {
gw gateways.Sprints
resp getsprintio.ResponseAssembler
}
func (uc *UseCase) Execute(req Request) (Response, error) {
sprint, err := uc.gw.Find(req.GetID())
if err != nil {
return nil, err
}
return uc.resp.Write(sprint)
}
pros 1/2
• highly reusable
• separate business rules <-> drivers
• ease of switching to new backends
• "LTS" business rules - heritage
• unit-tests friendly
• keep "good" performances (perhaps specific with Go (no
needs for reflect))
pros 2/2
• TDD friendly (Test Driver Development)
• BDD friendly (Behavior Driven Development)
• TDD + BDD drives to good designs
• ease of switching to new interfaces (or have multiple ones)
• standardize exchanges; unit-tests requests and responses
• the boundaries are clearly defined, it forces you to keep
things at the right place
cons
• a loooooot of files, classes, ... (annoying for creating new
entities, usecases...)
• code discovery, classes not directly linked to real objects,
but to interfaces
• make some optimizations harder, i.e: transactions
improvements ideas
• gogenerate: less files, more readable code
• add stats on the GitHub repo (impact on performances,
LOC, complexity)
• ...
conclusion
• it's a Gasoil, the learning curve (start) is long
• interesting for big projects, overkill for smaller, the center
domain needs to be rich enough
• should be done completely, or not at all
• needs to be rigorous with the main and unit tests
questions ?
github.com/moul/cleanarch
@moul

More Related Content

Viewers also liked

Lightning Talk - Clean Architecture and Design
Lightning Talk - Clean Architecture and DesignLightning Talk - Clean Architecture and Design
Lightning Talk - Clean Architecture and Design
Deivison Sporteman
 

Viewers also liked (11)

Choosing the architecture
Choosing the architectureChoosing the architecture
Choosing the architecture
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshop
 
Protobuf & Code Generation + Go-Kit
Protobuf & Code Generation + Go-KitProtobuf & Code Generation + Go-Kit
Protobuf & Code Generation + Go-Kit
 
Introduction to VIPER Architecture
Introduction to VIPER ArchitectureIntroduction to VIPER Architecture
Introduction to VIPER Architecture
 
Lightning Talk - Clean Architecture and Design
Lightning Talk - Clean Architecture and DesignLightning Talk - Clean Architecture and Design
Lightning Talk - Clean Architecture and Design
 
From mvc to viper
From mvc to viperFrom mvc to viper
From mvc to viper
 
iOS viper presentation
iOS viper presentationiOS viper presentation
iOS viper presentation
 
VIPER - Design Pattern
VIPER - Design PatternVIPER - Design Pattern
VIPER - Design Pattern
 
Introducing Clean Architecture
Introducing Clean ArchitectureIntroducing Clean Architecture
Introducing Clean Architecture
 
Rambler.iOS #5: VIPER и Swift
Rambler.iOS #5: VIPER и SwiftRambler.iOS #5: VIPER и Swift
Rambler.iOS #5: VIPER и Swift
 
iOS Coding Best Practices
iOS Coding Best PracticesiOS Coding Best Practices
iOS Coding Best Practices
 

Similar to "Clean" Architecture

AngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page AppsAngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page Apps
jivkopetiov
 
10 ways to make your code rock
10 ways to make your code rock10 ways to make your code rock
10 ways to make your code rock
martincronje
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
Sven Haiges
 
1403 app dev series - session 5 - analytics
1403   app dev series - session 5 - analytics1403   app dev series - session 5 - analytics
1403 app dev series - session 5 - analytics
MongoDB
 

Similar to "Clean" Architecture (20)

AngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page AppsAngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page Apps
 
10 ways to make your code rock
10 ways to make your code rock10 ways to make your code rock
10 ways to make your code rock
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 
Building Your First MongoDB Application
Building Your First MongoDB ApplicationBuilding Your First MongoDB Application
Building Your First MongoDB Application
 
Introduction to REST API with Node.js
Introduction to REST API with Node.jsIntroduction to REST API with Node.js
Introduction to REST API with Node.js
 
Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
 
Software Architecture: Principles, Patterns and Practices
Software Architecture: Principles, Patterns and PracticesSoftware Architecture: Principles, Patterns and Practices
Software Architecture: Principles, Patterns and Practices
 
He stopped using for/while loops, you won't believe what happened next!
He stopped using for/while loops, you won't believe what happened next!He stopped using for/while loops, you won't believe what happened next!
He stopped using for/while loops, you won't believe what happened next!
 
Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2Mobile App Development: Primi passi con NativeScript e Angular 2
Mobile App Development: Primi passi con NativeScript e Angular 2
 
Node.js Patterns for Discerning Developers
Node.js Patterns for Discerning DevelopersNode.js Patterns for Discerning Developers
Node.js Patterns for Discerning Developers
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 
Mobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileMobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve Mobile
 
JS Essence
JS EssenceJS Essence
JS Essence
 
Clean Code for East Bay .NET User Group
Clean Code for East Bay .NET User GroupClean Code for East Bay .NET User Group
Clean Code for East Bay .NET User Group
 
Secrets of Awesome JavaScript API Design
Secrets of Awesome JavaScript API DesignSecrets of Awesome JavaScript API Design
Secrets of Awesome JavaScript API Design
 
Automated malware analysis
Automated malware analysisAutomated malware analysis
Automated malware analysis
 
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023
Comment développer une application mobile en 8 semaines - Meetup PAUG 24-01-2023
 
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
 
1403 app dev series - session 5 - analytics
1403   app dev series - session 5 - analytics1403   app dev series - session 5 - analytics
1403 app dev series - session 5 - analytics
 

Recently uploaded

Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
nirzagarg
 
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
nilamkumrai
 
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
dharasingh5698
 
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
dharasingh5698
 
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
@Chandigarh #call #Girls 9053900678 @Call #Girls in @Punjab 9053900678
 

Recently uploaded (20)

Microsoft Azure Arc Customer Deck Microsoft
Microsoft Azure Arc Customer Deck MicrosoftMicrosoft Azure Arc Customer Deck Microsoft
Microsoft Azure Arc Customer Deck Microsoft
 
20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf
 
Call Now ☎ 8264348440 !! Call Girls in Green Park Escort Service Delhi N.C.R.
Call Now ☎ 8264348440 !! Call Girls in Green Park Escort Service Delhi N.C.R.Call Now ☎ 8264348440 !! Call Girls in Green Park Escort Service Delhi N.C.R.
Call Now ☎ 8264348440 !! Call Girls in Green Park Escort Service Delhi N.C.R.
 
Real Escorts in Al Nahda +971524965298 Dubai Escorts Service
Real Escorts in Al Nahda +971524965298 Dubai Escorts ServiceReal Escorts in Al Nahda +971524965298 Dubai Escorts Service
Real Escorts in Al Nahda +971524965298 Dubai Escorts Service
 
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
 
Russian Call Girls in %(+971524965298 )# Call Girls in Dubai
Russian Call Girls in %(+971524965298  )#  Call Girls in DubaiRussian Call Girls in %(+971524965298  )#  Call Girls in Dubai
Russian Call Girls in %(+971524965298 )# Call Girls in Dubai
 
VIP Model Call Girls NIBM ( Pune ) Call ON 8005736733 Starting From 5K to 25K...
VIP Model Call Girls NIBM ( Pune ) Call ON 8005736733 Starting From 5K to 25K...VIP Model Call Girls NIBM ( Pune ) Call ON 8005736733 Starting From 5K to 25K...
VIP Model Call Girls NIBM ( Pune ) Call ON 8005736733 Starting From 5K to 25K...
 
Al Barsha Night Partner +0567686026 Call Girls Dubai
Al Barsha Night Partner +0567686026 Call Girls  DubaiAl Barsha Night Partner +0567686026 Call Girls  Dubai
Al Barsha Night Partner +0567686026 Call Girls Dubai
 
20240509 QFM015 Engineering Leadership Reading List April 2024.pdf
20240509 QFM015 Engineering Leadership Reading List April 2024.pdf20240509 QFM015 Engineering Leadership Reading List April 2024.pdf
20240509 QFM015 Engineering Leadership Reading List April 2024.pdf
 
Yerawada ] Independent Escorts in Pune - Book 8005736733 Call Girls Available...
Yerawada ] Independent Escorts in Pune - Book 8005736733 Call Girls Available...Yerawada ] Independent Escorts in Pune - Book 8005736733 Call Girls Available...
Yerawada ] Independent Escorts in Pune - Book 8005736733 Call Girls Available...
 
𓀤Call On 7877925207 𓀤 Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
𓀤Call On 7877925207 𓀤 Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...𓀤Call On 7877925207 𓀤 Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
𓀤Call On 7877925207 𓀤 Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
 
Call Girls Ludhiana Just Call 98765-12871 Top Class Call Girl Service Available
Call Girls Ludhiana Just Call 98765-12871 Top Class Call Girl Service AvailableCall Girls Ludhiana Just Call 98765-12871 Top Class Call Girl Service Available
Call Girls Ludhiana Just Call 98765-12871 Top Class Call Girl Service Available
 
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
 
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
 
Shikrapur - Call Girls in Pune Neha 8005736733 | 100% Gennuine High Class Ind...
Shikrapur - Call Girls in Pune Neha 8005736733 | 100% Gennuine High Class Ind...Shikrapur - Call Girls in Pune Neha 8005736733 | 100% Gennuine High Class Ind...
Shikrapur - Call Girls in Pune Neha 8005736733 | 100% Gennuine High Class Ind...
 
Russian Call Girls Pune (Adult Only) 8005736733 Escort Service 24x7 Cash Pay...
Russian Call Girls Pune  (Adult Only) 8005736733 Escort Service 24x7 Cash Pay...Russian Call Girls Pune  (Adult Only) 8005736733 Escort Service 24x7 Cash Pay...
Russian Call Girls Pune (Adult Only) 8005736733 Escort Service 24x7 Cash Pay...
 
WhatsApp 📞 8448380779 ✅Call Girls In Mamura Sector 66 ( Noida)
WhatsApp 📞 8448380779 ✅Call Girls In Mamura Sector 66 ( Noida)WhatsApp 📞 8448380779 ✅Call Girls In Mamura Sector 66 ( Noida)
WhatsApp 📞 8448380779 ✅Call Girls In Mamura Sector 66 ( Noida)
 
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
 
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
 
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
 

"Clean" Architecture

  • 1. "Clean" Architecture 2016, by Manfred Touron (@moul)
  • 2. overview • the "clean" architecture, "Yet Another New Architecture" • by uncle Bob • discovered 3 months ago at OpenClassrooms with Romain Kuzniak • recent, no real spec, no official implementation • I don't use "clean" architecture in production • I'm not a "clean" architecture expert
  • 3. design slogans 1/2 1 • YAGNI (You Ain't Gonna Need It) • KISS (Keep It Simple, Stupid) • DRY (Don't Repeat Yourself) • S.O.L.I.D (SRP, OCP, LS, IS, DI) • TDD (Test Driven Development) 1 more info: http://fr.slideshare.net/RomainKuzniak/design-applicatif-avec-symfony2
  • 4. design slogans 2/2 1 • BDD (Behavior Driven Development) • DDD (Domain Driven Design) • ... 1 more info: http://fr.slideshare.net/RomainKuzniak/design-applicatif-avec-symfony2
  • 5. design types 1 • MVC • N3 Architectures • Domain Driven Design • Clean Architecture 1 more info: http://fr.slideshare.net/RomainKuzniak/design-applicatif-avec-symfony2
  • 6. the "clean" architecture 2 • Not a revolution, a mix of multiple existing principles • The other designs are not "dirty" architectures • Recent examples: Hexagonal Architecture, Onion Architecture, Screaming Architecture, DCI, BCE • Dependency injection at the buildtime or at leat at the runtime init 2 https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html
  • 7.
  • 8. ./cmd/api func main() { // Setup gateways var sprintsGw gateways.Sprints if len(os.Args) > 1 && os.Args[1] == "--mem" { // configure a memory-based sprints gateway sprintsGw = sprintsmem.New() } else { // configure a sqlite-based sprints gateway db, err := gorm.Open("sqlite3", "test.db") if err != nil { panic(err) } defer db.Close() sprintsGw = sprintsgorm.New(db) } // Setup usecases getSprint := getsprint.New(sprintsGw, getsprintdto.ResponseAssembler{}) addSprint := addsprint.New(sprintsGw, addsprintdto.ResponseAssembler{}) ping := ping.New(pingdto.ResponseAssembler{}) //closeSprint := closesprint.New(sprintsGw, closesprintdto.ResponseBuilder{}) // Setup API gin := gin.Default() gin.GET("/sprints/:sprint-id", apicontrollers.NewGetSprint(&getSprint).Execute) gin.POST("/sprints", apicontrollers.NewAddSprint(&addSprint).Execute) gin.GET("/ping", apicontrollers.NewPing(&ping).Execute) //gin.DELETE("/sprints/:sprint-id", apicontrollers.NewCloseSprint(&closeSprint).Execute) // Start gin.Run() }
  • 9. ./app/controllers/api type GetSprint struct { uc *getsprint.UseCase } func (ctrl *GetSprint) Execute(ctx *gin.Context) { sprintID, err := strconv.Atoi(ctx.Param("sprint-id")) if err != nil { ctx.JSON(http.StatusNotFound, gin.H{"error": "Invalid 'sprint-id'"}) return } req := getsprintdto.RequestBuilder{}. Create(). WithSprintID(sprintID). Build() resp, err := ctrl.uc.Execute(req) if err != nil { ctx.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("%v", err)}) return } ctx.JSON(http.StatusOK, gin.H{"result": GetSprintResponse{ CreatedAt: resp.GetCreatedAt(), EffectiveClosedAt: resp.GetEffectiveClosedAt(), ExpectedClosedAt: resp.GetExpectedClosedAt(), Status: resp.GetStatus(), }}) } type GetSprintResponse struct { CreatedAt time.Time `json:"created-at"` EffectiveClosedAt time.Time `json:"effective-closed-at"` ExpectedClosedAt time.Time `json:"expected-closed-at"` Status string `json:"status"` }
  • 10. ./app/repos/sprints/gorm type Repo struct { // implements gateways.Sprints db *gorm.DB } func (r Repo) Find(id int) (*entities.Sprint, error) { obj := sprintModel{} if err := r.db.First(&obj, "id = ?", id).Error; err != nil { return nil, err } ret := entities.NewSprint() ret.SetCreatedAt(obj.CreatedAt) ret.SetID(int(obj.ID)) ret.SetStatus(obj.status) ret.SetEffectiveClosedAt(obj.effectiveClosedAt) ret.SetExpectedClosedAt(obj.expectedClosedAt) return ret, nil }
  • 11. ./bizrules/usecases/get_sprint type UseCase struct { gw gateways.Sprints resp getsprintio.ResponseAssembler } func (uc *UseCase) Execute(req Request) (Response, error) { sprint, err := uc.gw.Find(req.GetID()) if err != nil { return nil, err } return uc.resp.Write(sprint) }
  • 12. pros 1/2 • highly reusable • separate business rules <-> drivers • ease of switching to new backends • "LTS" business rules - heritage • unit-tests friendly • keep "good" performances (perhaps specific with Go (no needs for reflect))
  • 13. pros 2/2 • TDD friendly (Test Driver Development) • BDD friendly (Behavior Driven Development) • TDD + BDD drives to good designs • ease of switching to new interfaces (or have multiple ones) • standardize exchanges; unit-tests requests and responses • the boundaries are clearly defined, it forces you to keep things at the right place
  • 14. cons • a loooooot of files, classes, ... (annoying for creating new entities, usecases...) • code discovery, classes not directly linked to real objects, but to interfaces • make some optimizations harder, i.e: transactions
  • 15.
  • 16. improvements ideas • gogenerate: less files, more readable code • add stats on the GitHub repo (impact on performances, LOC, complexity) • ...
  • 17. conclusion • it's a Gasoil, the learning curve (start) is long • interesting for big projects, overkill for smaller, the center domain needs to be rich enough • should be done completely, or not at all • needs to be rigorous with the main and unit tests