This suggestion is a fairly big change, but i think would drastically reduce: the number of files, lines of code, compile time, and the overall complexity of the code base.
In the code below, the goal is to minimise the amount of generated code while maintaining a nice API for the user:
// ===================================================
// HAND WRITTEN CODE
type Data = map[string]interface{}
type Config struct {
Version string
BaseURL string
}
type Client struct {
Config
Services services.Services
}
func NewClient(config Config) *Client {
client := &Client{Config: config}
client.Services.init(client)
return client
}
func (c *Client) request(service, endpoint string, data Data) (Data, error) {
url := c.Config.BaseURL + "/" + c.Config.Version + "/" + service + "/" + endpoint
// make request
}
// ===================================================
// GENERATED CODE (all generated code in one place: gen/)
// generate [gen/services/services.go]
package services
type Services struct {
AliSms
App
MttvScreen
}
// general init all, pass Client into all services
func (s *Services) init(client *Client) {
s.AliSms = AliSms{Name: "AliSms", client: client}
s.App = App{Name: "App", client: client}
s.MttvScreen = MttvScreen{Name: "MttvScreen", client: client}
}
// generate service [gen/services/service_ali_sms.go]
package services
// AliSmsService msgDownwardStatusReceipt /v1/messageService/msgDownwardStatusReceipt
// becomes:
type AliSms struct {
client *Client
Name string
State int
}
func (s *AliSms) MsgDownwardStatusReceipt(data Data) (Data, error) {
return s.client.request(s.Name, "messageService/msgDownwardStatusReceipt", data)
}
// generate service [gen/services/service_app.go]
package services
// AppService acceptPsSharing /v1/powerStationService/acceptPsSharing
// AppService activateEmail /v1/userService/activateEmail
// becomes
type App struct {
client *Client
Name string
State int
}
func (s *App) AcceptPsSharing(data Data) (Data, error) {
return s.client.request(s.Name, "powerStationService/acceptPsSharing", data)
}
func (s *App) ActivateEmail(data Data) (Data, error) {
return s.client.request(s.Name, "userService/activateEmail", data)
}
// ===================================================
// USER CODE
client, err := NewClient(Config{ ... })
if err != nil {
// handle
}
out, err := client.Services.App.ActivateEmail(data{
"param1": 42
})
if err != nil {
// handle
}
// out holds response
This suggestion is a fairly big change, but i think would drastically reduce: the number of files, lines of code, compile time, and the overall complexity of the code base.
In the code below, the goal is to minimise the amount of generated code while maintaining a nice API for the user: