How to talk about architecture?
Author:
Daniel Antos
What are we talking about today?
- Why?
- When good intentions go south
- Approaches that have helped me
- How to continue conversation in the code (Go)
Why?
- The best ideas come from clashing opinions
- Some techniques promote deep thinking
- If everyone is rowing in the same direction,
we will get there faster
When good intentions go south
I believe that we all have good intentions.
And even the flawed approach is better than inactivity.
Large pull requests
I was working on a feature. There was this architectural issue. One thing led to the other, and...
Being too excited for specific solution
Dictating from the ivory tower
Approaches that have helped me
Decision records
Diagrams
Proof of Concept (PoC)
- Show the journey.
- What are the worst ways to solve the problem?
- At which point the other opinion is better?
How to continue the conversation in Go
Folder structure is a good guide
3 stages
Folder structure is a good guide
Domain Driven Design?
bids.go seems more important
Let types tell the story
func init() {
var bids auction.Bids
var tricks int
contract := bids[len(bids)-1]
CountPoints(contract, tricks)
}
func CountPoints(
contract auction.Bid,
tricks int,
) int {
return 0
}
Nothing stops us from passing the wrong thing
// Domain
type Contract Bid
func (bs Bids) Contract() Contract
// Scoring
func init() {
var bids auction.Bids
var tricks int
CountPoints(bids.Contract(), tricks)
}
func CountPoints(
contract auction.Contract,
tricks int,
) int {
return 0
}
Little work to create a new type, but developer will be warned about a wrong type usage
Restrict access
package scoring
var tricks int
contract := infra.Repo{}.Find().Contract()
CountPoints(contract, tricks)
package scoring
var tricks int
contract := infra.Logs{Repo: infra.Repo{}}.
Find().Contract()
CountPoints(contract, tricks)
package scoring
var tricks int
contract := infra.New().Find().Contract()
CountPoints(contract, tricks)
package infra
func New() Repo {
return logs{Repo: repo{}}
}
type Repo interface {
Find() internal.Bids
}
// ...
We can restrict developers from misusing our creations
Restrict access
package scoring
import (
"bridge/pkg/auction"
"bridge/pkg/auction/api"
)
func init() {
var tricks int
contract := api.API{}.FindContract()
CountPoints(contract, tricks)
}
package scoring
import (
"bridge/pkg/auction"
// compilation error!
"bridge/pkg/auction/internal/infra"
)
func init() {
var tricks int
contract := infra.New().Find().Contract()
CountPoints(contract, tricks)
}
Or even hide entire packages!
Restrict access
package auction
type Contract = internal.Contract
// ...
package scoring
import (
"bridge/pkg/auction"
)
func init() {
var tricks int
contract := auction.API{}.FindContract()
CountPoints(contract, tricks)
}
func CountPoints(
contract auction.Contract,
tricks int,
) int {
return 0
}
Let's architect a game - Contract Bridge!
Summary
- Don't do it alone
- Find a way to collaborate that fits you and your team
- The best architecture doesn't matter, if you don't have buy-in
- Expressing ideas in the code explicitly lengthen their lives
- Don't do it alone
Thanks!
Let's have some questions!
☝️My blog
danielantos.com
☝️Slides
How to talk about architecture?
By antosdaniel
How to talk about architecture?
- 40