<div dir="ltr">On Fri, Aug 23, 2013 at 5:47 PM, Nate Finch <span dir="ltr"><<a href="mailto:nate.finch@canonical.com" target="_blank">nate.finch@canonical.com</a>></span> wrote:<div class="gmail_extra"><div class="gmail_quote">

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>It does require a little discipline when creating methods to avoid the mental default of just writing a method to take the concrete type that you expect to receive, and instead look at what methods you use from that type and see if it's more appropriate to use an interface that type implements.</div>

</div></blockquote><div><br></div><div>The trouble comes when one of the methods on the interface returns something non-trivial. Consider the following:</div><div><br></div><div>-------------------------------------</div>

<div>package example</div><div><br></div><div><div>type Fooer struct{</div><div>    // non-trivial</div><div>}</div><div><br></div><div>func (*Fooer) Foo() *Barer {</div><div><span style="white-space:pre-wrap">    </span>return &Barer{</div>

<div>        // private fields</div><div>    }</div><div>}</div><div><br></div><div>type Barer struct{</div><div>    // non-trivial</div><div>}</div><div><br></div><div>func (*Barer) Bar() {}</div>-------------------------------------</div>

<div><br></div><div>...and a client func somewhere else:</div><div><br></div><div>-------------------------------------<br></div><div>package client</div><div><br></div><div>import "example"</div><div><br></div>

<div>func FooBar(f *example.Fooer) {</div><div>    f.Foo().Bar()</div><div>}</div><div>-------------------------------------<br></div><div><br></div><div>Of course, this was written without taking the above advice into consideration, so of course it's not mockable. Let's try:</div>

<div><br></div><div>-------------------------------------</div><div>package client</div><div><br></div><div>import "example"</div><div><br></div><div>type Fooer interface {</div><div>    Foo() *example.Barer</div>

<div>}</div><div><br></div><div>func FooBar(f Fooer) {</div><div>    f.Foo().Bar()</div><div>}</div><div>-------------------------------------</div><div><br></div><div>Great! We accept an interface, and follow good practice, and everyone's happy, until we try to mock it.</div>

<div><br></div><div>-------------------------------------<br></div><div>package client_test</div><div><br></div><div>import "client"</div><div>import "example"</div><div><br></div><div>type MockFooer struct {}</div>

<div><br></div><div>func (MockFooer) Foo() *example.Barer {</div><div>    // ...wait a moment</div><div>}</div>-------------------------------------<div><br></div><div>If example.Barer has private fields, for example, or otherwise cannot be constructed without the aid of a concrete example.Fooer, we're no better off than we were before. We have to go to the example package and change *its* interface in a breaking way (leaving aside naming problems, which are not insignificant, the return type of Fooer.Foo() has to change).</div>

<div><br></div><div>It's enough of a hassle updating the client code that you control when you have to make a change like this; and if anyone *else* depends on that package, game over. Frequently you just sigh, and use the concrete types, and move on. And the client test suite just has to suck it up and become that little bit less wieldy.</div>

<div><br></div><div>And that's why we should generally prefer to return interfaces -- because the cost of doing so and not needing to is negligible, but the cost of doing after the fact approaches the prohibitive with alarming stealth and speed. This is not to say that you *can't* return structs... but you almost certainly shouldn't return structs with private fields, or structs whose public fields could take a lot of work to set up, or structs that might legitimately come to fall under those categories.</div>

<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div></div><div>I don't know the exact problems you were having, Tim, but maybe a more specific example would help us (or at least me) understand the problem you're trying to solve.</div>

</div></blockquote><div><br></div><div>Tim may have found other problems, but that's the general shape of the ones I've found. Interfaces are great, but you have to *use* them, and it's not trivial to bolt them on.</div>

<div>  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div><div class="gmail_extra">
<div class="gmail_quote">On Fri, Aug 23, 2013 at 5:37 AM, roger peppe <span dir="ltr"><<a href="mailto:rogpeppe@gmail.com" target="_blank">rogpeppe@gmail.com</a>></span> wrote:</div></div></div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div><div><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


Perhaps we could do it this other way around?<br>
<br>
// TODO (thumper) Details about the change needed<br>
// 2013-08-23 bug 1654321<br></blockquote></div></div></div></div></blockquote><div><br></div><div>Plenty of todo descriptions are multiline; I'd rather follow tim's model please.</div><div> </div></div></div></div>