GoSungrow icon indicating copy to clipboard operation
GoSungrow copied to clipboard

4.0 architecture idea

Open jpillora opened this issue 2 years ago • 1 comments

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

jpillora avatar Feb 17 '23 03:02 jpillora

Disclaimer: I dont fully understand the codebase, so feel free to correct any inaccuracies!

jpillora avatar Feb 17 '23 03:02 jpillora