@@ -50,6 +50,23 @@ For detailed instructions, see [examples/README.md](examples/README.md).
5050
5151See [ docs/architecture/STRUCTURE.md] ( docs/architecture/STRUCTURE.md ) for a detailed breakdown of the project structure.
5252
53+ ## Architecture
54+
55+ The project follows clean architecture principles with clear separation of concerns:
56+
57+ - ** Controllers** (` core/controller/ ` ): Pure business logic, independent of transport layer
58+ - Only depend on logger, metrics, and protobuf types
59+ - Example: ` PingController ` handles ping business logic
60+
61+ - ** Server Adapters** (` examples/server/ ` ): gRPC transport layer
62+ - Wrap controllers and implement gRPC service interfaces
63+ - Handle protocol-specific concerns (e.g., ` UnimplementedServiceServer ` )
64+
65+ - ** Observability** : Built-in logging and metrics
66+ - Structured logging with [ Zap] ( https://github.com/uber-go/zap )
67+ - Metrics collection with [ Tally] ( https://github.com/uber-go/tally )
68+ - Development servers use human-readable console logging
69+
5370## Development
5471
5572### Prerequisites
@@ -226,7 +243,8 @@ message PingResponse {
226243 string message = 1;
227244 string service_name = 2;
228245 int64 timestamp = 3;
229- string hostname = 4; // New field added
246+ string hostname = 4;
247+ string new_field = 5; // New field added
230248}
231249```
232250
@@ -240,8 +258,8 @@ make proto
240258# - gateway/protopb/gateway_grpc.pb.go
241259# - gateway/protopb/gateway.pb.yarpc.go
242260
243- # Now update the service implementation
244- # Edit gateway/core/controller/ping.go to populate the hostname field
261+ # Now update the controller implementation
262+ # Edit gateway/core/controller/ping.go to populate the new field in the PingResponse
245263```
246264
247265### Testing
@@ -313,17 +331,44 @@ make test
313331 make proto
314332 ```
315333
316- 3 . ** Implement the method in the service:**
334+ 3 . ** Implement the method in the controller:**
335+ ``` go
336+ // In gateway/core/controller/ (create a new controller file)
337+ type NewController struct {
338+ logger *zap.Logger
339+ metricsScope tally.Scope
340+ }
341+
342+ func NewNewController (logger *zap .Logger , scope tally .Scope ) *NewController {
343+ if logger == nil {
344+ logger = zap.NewNop ()
345+ }
346+ if scope == nil {
347+ scope = tally.NoopScope
348+ }
349+ return &NewController{logger: logger, metricsScope: scope}
350+ }
351+
352+ func (c *NewController ) NewMethod (ctx context.Context, req *pb.NewRequest) (*pb.NewResponse, error) {
353+ // Business logic here
354+ c.logger .Info (" new method called" )
355+ c.metricsScope .Counter (" new_method_total" ).Inc (1 )
356+ // ...
357+ }
358+ ```
359+
360+ 4 . ** Create server wrapper in example:**
317361 ``` go
318- // In gateway/core/controller/ping.go (or create a new file)
319- func (s *PingServiceImpl ) NewMethod (ctx context.Context, req *pb.NewRequest) (*pb.NewResponse, error) {
320- // Implementation here
362+ // In examples/server/gateway/main.go
363+ // Add method delegation to GatewayServer struct:
364+ func (s *GatewayServer ) NewMethod (ctx context.Context, req *pb.NewRequest) (*pb.NewResponse, error) {
365+ return s.newController .NewMethod (ctx, req)
321366 }
322367 ```
323368
324- 4 . ** Update clients to call the new method**
369+ 5 . ** Update clients to call the new method**
325370
326- 5 . ** Rebuild and test:**
371+ 6 . ** Rebuild and test:**
327372 ``` bash
328373 make build
329374 ```
0 commit comments