Reduce code for building requests and decoding response bodies #147
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I noticed a REST API is not implemented in this official client (can you tell which one?). I was to implement to support the API, but I noticed that there are too many code duplication. Most client methods create a http request, serialize the payload and add content type header, send the request, and decode the response body. Some methods use
c.PostJSON(...)
, but this does not support decoding response bodies.Too much code duplication makes it boring to read and write.
One of the difficulties to deduplicate this kind of client code was how to decode the response body into each type. But Generics was out in Go 1.18 and it changed the world of Go. We can now use Generics in this library, you now support only Go 1.20 and 1.21. One of the unfamous limitation of it is that we cannot use it for struct methods, but I think this is a small thing, just pass the receiver as an argument.
Here's a list of client utilities I implemented in this PR. There are four requestX each method, and two variants for GET.
For example, we can implement some methods using the utilities as follows.
This is more declarative and neat isn't it? We don't need to care about closing the response, to duplicate code decoding the response body. Previously the code was like this...
My only concern is how this patch grows end users' executable file size. I tested only
mkr
, but file size growth is small (linux amd64 executable size: 10572K -> 10640K). I think this is acceptable, but if there's a case suffering from this patch, we can drop the type parameter fromrequestInternal
, create the response value inrequestGet
, etc., and pass it by reference. This reduces the generated code forrequestInternal
.I'm sorry for submitting a large refactoring patch. I don't mind you close this PR due to any reason, because I don't care how much code it is implemented by, as a package user. But hopefully, I would like to see some good news.
This is an off topic. I'm maintaining mackerel-client-rs. After two years of hiatus, I rebooted the implementation recently. Due to the richness of type system and my own macro definition, I can implement the client methods with fancy code. This leads me motivated to reduce the code duplication of the Go client.
Example of mackerel-client-rs code