Hey there!
I'm currently trying to do a bit of web development, and have a bunch of classes (FooPage, BarPage) that are almost exactly the same, save for the interface for their dependencies and methods specific to how they serve their content.
It became onerous to write basically the same constructor for each page, so I am trying to split things out and make my code more DRY. This has resulted in the following code:
type Page[D any] interface {
Register(m *http.ServeMux)
SetDeps(d D)
SetTemplate(t *template.Template)
}
type PageBase[D any] struct {
Deps D
Tmpl *template.Template
}
func (p *PageBase[D]) SetDeps(d D) {
p.Deps = d
}
func (p *PageBase[D]) SetTemplate(t *template.Template) {
p.Tmpl = t
}
func NewPage[P Page[D], D any](p P, m *http.ServeMux, d D, t *template.Template) P {
p.SetDeps(d)
p.SetTemplate(t)
p.Register(m)
return p
}```
which allows us to then define whole pages like so:
```go
type MockPageDeps interface {
// Blank for testing
}
type MockPage struct {
dmn.PageBase[MockPageDeps]
}
func (p *MockPage) Register(m *http.ServeMux) {
// Typically calls m.HandleFunc("/whatever", pageFunction)
}
and construct them like so:
dmn.NewPage[*mckpg.MockPage, mckpg.MockPageDeps](&mckpg.MockPage{}, mux, deps, &tmpl)
This works, but feels very ugly to me. I'm wondering if anyone more experienced has a better (still DRY) way of doing what I'm trying to do?