Skip to content

Instantly share code, notes, and snippets.



Last active Mar 7, 2019
What would you like to do?
Go - cost of change for methods in application code. App code has many types that work together, requiring mocking.
// Let's define a type with a method that needs a fair few arguments
type Thing struct {}
func (c *Thing) Verb(a A,b B,c C,d D) {}
// We have things that depend on Thing and we want to test them, so to mock it we'll need to
// define an interface and generate a mock
type Thinger interface {
Verb(a A,b B,c C,d D)
type MockThing struct{}
func (c *MockThing) Verb(a A,b B,c C,d D) {}
// Okay, now the cost of changing Method's arguments is:
// 1. update interface
// 2. regenerate mock
// in addition to updating callers to those methods: concrete and in test
// We could dodge this by rolling up the arguments into a value object, however, this is now
// really unsafe as we can't make the struct require all args
type VerbArgs struct { A A, B... }
func (c *Thing) VerbV2(args VerbArgs) {}
// Whoops, now C and D are zero-values. Havok may ensure
// If we make a factory for VerbArgs we have safety and a lower cost of change: changing the args doesn't require
// a change to the Verb method, so the Thinger interface and MockThing don't need updating.
func newVerbArgs(a A,B...) VerbArgs {}
// However: if we don't move `VerbArgs` into its own package, and conceal the struct type, people can
// still forget and use `VerbArgs` directly, which gives us the zero-value problem again. Making a interface
// type for it with getters would be safe but it's a heap of code. This could be tooled though, so seems somewhat
// tractable.
// A likely non-answer: "make it take fewer arguments". Okay, then we need to define value-objects which
// needs to conceal its structure with a separate package + getters to avoid the zero-value problem mentioned above.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.