The correlation when building anything; Go

The correlation when building anything

Every server you ever build has exactly three layers:

LAYER 1 DATA
"what do I store and how?"
-> your Log, your Database, your Cache
-> pure Go structs, no HTTP, no network

LAYER 2 BUSINESS LOGIC  
"what can I do with the data?"
-> Append, Read, Delete. Run logic to get/derive result
-> still no HTTP, just functions on your data

LAYER 3 TRANSPORT
"how does the outside world talk to my logic?"
-> HTTP, gRPC, CLI
-> unmarshal -> call layer 2 -> marshal back

The correlation is each layer only knows about the layer below it, never above. Layer 3 calls Layer 2. Layer 2 calls Layer 1. Layer 1 knows nothing about HTTP.

  • HTTP knows nothing about your Log
  • Your Log knows nothing about HTTP
  • Business logic sits in the middle, clean

The code is clean. And tomorrow when we swap HTTP for gRPC. Log doesn't change at all. Only Layer 3 changes. That's the payoff of the design. Interesting isn't it.

In http.go + log.go:

Layer 1  ->  Log struct (log.go)
Layer 2  ->  Append(), Read() methods
Layer 3  ->  http.go the bridge between net/http and your logic

Every decision in chapter 1 is a question answered. once you see the questions, the code writes itself.

1. what am I building?     -> a log, append-only, ordered by time

2. what does it need?      -> store records, give them back by offset
                           -> define Record, define Log

3. what type for offset?   -> never negative -> uint64
                           -> "make illegal states unrepresentable"

4. concurrent access?      -> multiple goroutines -> RWMutex
                           -> reads share, writes exclusive

5. how does outside        -> HTTP server
   world reach it?         -> two routes: produce, consume

6. how do routes reach     -> httpServer struct carries the Log
   the Log?                -> handlers are methods on that struct

7. public or private?      -> NewHTTPServer public (world uses it)
                           -> newHTTPServer private (internal setup)

8. pointer or value?       -> big structs, shared state -> pointers