A pokedex REST API kata in go
Go to file
Wouter Groeneveld fb1dff23b9 benchmarks protojson + http.json; added repo integration test 2024-04-15 20:32:15 +02:00
docs add protobuf contract back to front; make pokemon structs internal 2024-04-15 13:56:10 +02:00
pb add protobuf contract back to front; make pokemon structs internal 2024-04-15 13:56:10 +02:00
pokemon benchmarks protojson + http.json; added repo integration test 2024-04-15 20:32:15 +02:00
rest benchmarks protojson + http.json; added repo integration test 2024-04-15 20:32:15 +02:00
.gitignore add protobuf contract back to front; make pokemon structs internal 2024-04-15 13:56:10 +02:00
Makefile try to optimize the binary using UPX 2024-04-15 14:09:29 +02:00
README.md benchmarks protojson + http.json; added repo integration test 2024-04-15 20:32:15 +02:00
go.mod benchmarks protojson + http.json; added repo integration test 2024-04-15 20:32:15 +02:00
go.sum add protobuf contract back to front; make pokemon structs internal 2024-04-15 13:56:10 +02:00
main.go try to optimize the binary using UPX 2024-04-15 14:09:29 +02:00
server.go initial commit 2024-04-15 10:27:31 +02:00

README.md

Pokedex README

A simple Go-powered REST API kata.

HTTP Server

  • KISS: Use built-in http package. https://gin-gonic.com/ looks cooler but also adds dozens of dependencies 😮 No need for a "fully-featured" web framework.

Protobuf

Why? Separation of concerns; do not expose database/domain internals. Structs in pokemon.go should not leave the package. The .proto file serve as the official "contracts".

Is this over-engineered or what? On top of that, protojson's performance is much worse:

goos: darwin
goarch: arm64
pkg: pokedex/rest
BenchmarkJson-8        	 1275931	       928.9 ns/op
BenchmarkJson-8        	 1292184	       926.6 ns/op
BenchmarkJson-8        	 1292647	       926.0 ns/op
BenchmarkJson-8        	 1291228	       926.3 ns/op
BenchmarkJson-8        	 1294453	       927.3 ns/op
BenchmarkProtoJson-8   	  772567	      1510 ns/op
BenchmarkProtoJson-8   	  766005	      1517 ns/op
BenchmarkProtoJson-8   	  779281	      1512 ns/op
BenchmarkProtoJson-8   	  774534	      1513 ns/op
BenchmarkProtoJson-8   	  771370	      1511 ns/op
PASS
ok  	pokedex/rest	16.500s

And that's with indent! Without:

BenchmarkJson-8        	 4067257	       266.6 ns/op
BenchmarkJson-8        	 4503345	       266.5 ns/op
BenchmarkJson-8        	 4512295	       266.9 ns/op
BenchmarkJson-8        	 4505510	       266.7 ns/op
BenchmarkJson-8        	 4482391	       267.4 ns/op

The question then becomes: why use a .proto file to exchange a contract at all, if you're not using gRPC?

Swagger

Big bummer: annotations contain endpoint duplication...

Optimizing the binary

See Makefile; use https://upx.github.io/ to package after stripping some debug info.

Somehow doesn't work on OSX (process killed)?

Interesting philosophical questions

  1. Where should routing be defined? Central or with the domain package (which doesn't seem to be the idiomatic Go way?)
  2. To use or not use DTO or response objects?
  3. How to handle dependencies without dragging in Yet Another Unneeded Framework?
  4. Custom error wrapping or not?
  5. Custom Go web frameworks that ease muxing and exponential back-offs or not?
  6. Where should db migration go? Reusability in tests?