go-poodr
go-poodr copied to clipboard
A Go translation of the example code from Practical Object-Oriented Design in Ruby by Sandi Metz.
go-poodr
A Go translation of the example code from Practical Object-Oriented Design in Ruby by Sandi Metz.
Use the Go Playground or go run to try these examples, eg:
chapter2> go run gear1.go
1. Object-Oriented Design
(intro)
2. Designing Classes with a Single Responsibility
gear1.godefines a basic Gear with gettersgear2.gointroduces a new feature (and responsibility)gear3.gohide instance variables (behavior in one place)obscure.godepending on complicated data structures is badrevealing.goisolating the incoming arraygear4.goextracting wheel as an internal structuregear5.goa real Wheel with dependency injection
3. Managing Dependencies
1-dependencies.goGear knows too much about Wheel (actually a step back from gear5.go)2-duck-type.goWe don't need a Wheel specifically, just an object that responds to Diameter()3-isolate-new.goIsolate instance creation (if you can't inject the dependency for some reason)4-isolate-messages.goIsolate external messages that could be vulnerable to change5-map-init.goRemove argument order dependencies (probably not the best way to accomplish this)- Skipped a factory method to work with an unwieldy constructor (gear-wrapper).
7-reverse-dependencies.goWhat if Wheel depends on Gear? (which is more stable?)
4. Creating Flexible Interfaces
(It's all UML! :-)
5. Reducing Costs With Duck Typing
(structural typing in Go)
trip1.goA Trip that knows it needs the bicycles prepared.trip2.goTrip preparation becomes more complicated. It knows too much.trip3.goA Preparer interface, more abstract but easier to extend.
6. Acquiring Behavior Through Inheritance
(which Go doesn't have)
bikes1.goStarting with a road bike.bikes2.goWe need mountain bikes too. Switching on the type.- Skipped misapplying inheritance.
bikes4.goImplicit delegation and type embedding instead of subclasses.bikes5.goSpecializing the Spares method.bikes6.goUse a hook to push responsibilities into the embedded type.
The template method pattern would require a reference to the embedded type, after it is created. Seems like a pattern that shouldn't be attempted in Go.
7. Sharing Role Behavior With Modules
schedule1.goScheduling as part of Bicycle, for later extraction.schedule2.goExtract and delegate to Schedulable.
8. Combining Objects With Composition
- Skipping first transition, which still uses template methods and inheritance.
parts2.goBicycle composed of Parts, which is a slice of Part.parts3.goRather than a PartsFactory, I use array-style composite literals.
9. Designing Cost-Effective Tests
Use go test to run these, eg:
chapter9> go test gear1/gear1_check_test.go
Your GOPATH matters for these, as we are importing a separate package for black box testing.
gear1/gear1_test.goA basic example using Go's built in testing facilities.gear1/gear1_check_test.goThe same code tested with gocheck and a custom matcher.