I believe that we all have good intentions.
And even the flawed approach is better than inactivity.
I was working on a feature. There was this architectural issue. One thing led to the other, and...
func main() {
s := setup.New()
notification, err := notification_setup.NewSetup()
if err != nil {
log.Fatalf("Could not set up no module: %v", err)
}
booking, err := booking_setup.New(s.Enqueueer, notification.API)
if err != nil {
log.Fatalf("Could not set up booking module: %v", err)
}
go booking.ListenForEvents(s.Dequeueer)
go notification.PeriodicRetry()
metrics.RegisterRoutes(s.Router)
booking.RegisterRoutes(s.Router.Group("/booking"))
s.StartServer()
}
type api struct {
TemplateRepo TemplateRepo
UserRepo UserRepo
SmsSender SmsSender
}
func New(templateRepo TemplateRepo, userRepo UserRepo, sender SmsSender) API {
return withLogs{
API: api{
TemplateRepo: templateRepo,
UserRepo: userRepo,
SmsSender: sender,
},
}
}
type APIImplementation struct {
TemplateRepo TemplateRepo
UserRepo UserRepo
SmsSender SmsSender
}
notifications := api.APIImplementation{
TemplateRepo: infra.TemplateRepo{},
UserRepo: infra.UserRepo{},
SmsSender: infra.SmsSender{},
}
type API interface {
SendNotification(templateID string, userID string) error
}
We control creation,
user knows only about the interface
"internal" folder restricts who can use it
Domain Driven Design?
bids.go seems more important
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
Let's have some questions!
☝️My blog
danielantos.com
☝️Slides