Skip to content

Commit c005aec

Browse files
committed
document handler interface pattern
1 parent 05c1d40 commit c005aec

1 file changed

Lines changed: 49 additions & 1 deletion

File tree

docs/ROUTES-LISTING.md

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,55 @@ fi
388388
go run cmd/routes/main.go --json | jq '.routes[].Name' | grep -q "api.users.index"
389389
```
390390

391-
### 4. Documentation Generation
391+
### 4. Listing Routes Without Real Handler Dependencies
392+
393+
In larger applications, handlers are often constructed with live dependencies (database
394+
connections, service clients, config, etc.) that are unavailable or expensive to build in a
395+
standalone CLI tool. The recommended pattern is to extract route registration into a shared
396+
function that accepts a handler interface, then provide a stub implementation backed by
397+
`teapot.NoopHandler` when listing:
398+
399+
```go
400+
// Handlers defines the contract your route registration depends on.
401+
type Handlers interface {
402+
ListUsers() http.Handler
403+
ShowUser() http.Handler
404+
CreateUser() http.Handler
405+
}
406+
407+
// RegisterRoutes is the single source of truth for all routes.
408+
// It is used by both the real server and the listing tool.
409+
func RegisterRoutes(r *teapot.Router, h Handlers) {
410+
r.GET("/users", h.ListUsers()).Name("users.index")
411+
r.GET("/users/{id}", h.ShowUser()).Name("users.show")
412+
r.POST("/users", h.CreateUser()).Name("users.store")
413+
}
414+
415+
// Real implementation — constructed with live dependencies in main.go.
416+
type appHandlers struct{ db *sql.DB }
417+
func (h *appHandlers) ListUsers() http.Handler { return NewListUsersHandler(h.db) }
418+
func (h *appHandlers) ShowUser() http.Handler { return NewShowUserHandler(h.db) }
419+
func (h *appHandlers) CreateUser() http.Handler { return NewCreateUserHandler(h.db) }
420+
421+
// Stub implementation — no dependencies required.
422+
type stubHandlers struct{}
423+
func (stubHandlers) ListUsers() http.Handler { return teapot.NoopHandler }
424+
func (stubHandlers) ShowUser() http.Handler { return teapot.NoopHandler }
425+
func (stubHandlers) CreateUser() http.Handler { return teapot.NoopHandler }
426+
427+
// cmd/routes/main.go — prints routes with zero real dependencies.
428+
func main() {
429+
r := teapot.New()
430+
RegisterRoutes(r, stubHandlers{})
431+
teapot.FormatRoutesTable(os.Stdout, r.Routes())
432+
}
433+
```
434+
435+
Because the stub satisfies the same interface as the real implementation, adding a new route
436+
to `RegisterRoutes` will cause a compile error until `stubHandlers` is updated — keeping
437+
the listing tool automatically in sync.
438+
439+
### 5. Documentation Generation
392440

393441
Generate route documentation from routes:
394442

0 commit comments

Comments
 (0)