Policies for coding

Frank Mueller frank.mueller at canonical.com
Fri Aug 23 16:22:39 UTC 2013


I like the idea of more focussing on interfaces instead of concrete types
for export. And Roger and Nate, you're right that concentrating on
interfaces as arguments while returning types leads to a relative low
coupling. I experimented exactly with this during my holidays and it worked
very well. The mix of flexibility by directly using returned types while
passing interfaces (beside simple types) as arguments enables to easily not
only test the software but also depend more on behaviors than
implementations. So later changes in direction of more different
implementations of the same interface are possible. Our environ package
shows it (even if the implementations have other problems).

One little additional note on using interfaces: small ones which are
combined to larger ones, like the StorageReader and SorageWriter increases
this benefit even more.

mue



On Fri, Aug 23, 2013 at 5:47 PM, Nate Finch <nate.finch at canonical.com>wrote:

> On the interface point, I agree with Roger. To me, this is a classic
> example of good programming practice: Have your methods accept the most
> general types coming in, and return the most specific types going out. This
> leads to the least coupling between bits of code, while allowing the most
> functionality.
>
> If you return a concrete bufio.Reader, anyone who needs specific methods
> from bufio.Reader can use those methods. However, they can still pass it in
> to any method that accepts an io.Reader interface and it'll work just fine.
> But until such a time as they need to pass it into something that just
> wants an io.Reader, they haven't lost any of the functionality of the bufio
> implementation.
>
> The nice thing about Go is that you don't have to make sure that you pass
> around interfaces everywhere, since the compiler can convert types to
> interfaces "on the fly" as needed.
>
> 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.
>
> 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.
>
>
>
> On Fri, Aug 23, 2013 at 5:37 AM, roger peppe <rogpeppe at gmail.com> wrote:
>
>> On 23 August 2013 04:11, Tim Penhey <tim.penhey at canonical.com> wrote:
>> > Hi folks,
>> >
>> > I have two items I'd like to propose for general policies or guidelines
>> > for coding within the juju-core codebase.
>> >
>> > Firstly is to formalise on structure for TODO comments.  We already have
>> > an informal policy around TODO (person), where person is the person that
>> > most often write it, although I don't believe this is
>> > always followed.
>> >
>> > I propose the following structure:
>> >
>> > // TODO (thumper): 2013-08-23 bug 1654321
>> > // Details about the change needed, or things to do.
>>
>> This seems reasonable, but there's one down side - currently
>> for most TODOs, a grep will pull out both the TODO and its
>> description, whereas this will lose that.
>>
>> Perhaps we could do it this other way around?
>>
>> // TODO (thumper) Details about the change needed
>> // 2013-08-23 bug 1654321
>>
>> > Secondly, I propose the following guideline:
>> >
>> >   Prefer exporting functions and interfaces to structures
>> >   - unless there is a very good reason why the structure
>> >     should be exported.
>> >
>> > A common example of a structure that should be exported is a "params"
>> > type structure that groups parameters for another exported function.
>> >
>> > By exporting interfaces, we have more ability to mock the behaviour for
>> > testing, and to change implementation details without impacting all the
>> > users of the code.
>>
>> I don't quite get this. There's nothing about *returning* an interface
>> that makes more easily mockable, AFAICS. The thing that makes things
>> easier to mock is that *parameters* are interfaces, as narrow as
>> possible for the code in question. Doing things this way makes it
>> the responsibility of each piece of code to enable itself to be mocked,
>> while allowing it to present the most natural API possible to its
>> clients.
>>
>> For example, in the Go library, bufio.NewReader returns a concrete type,
>> not an interface, but many methods and functions will accept an
>> io.Reader interface
>> value, which happens to be implemented by bufio.Reader.
>> This is idiomatic Go, and I think it can work well.
>>
>> Moreover some types really don't need to be mocked, as
>> they're easily created on the fly and their methods don't
>> rely on anything other than the data contained within them.
>> Would there be any advantage in, for example,
>> passing constraints.Value around as an interface?
>>
>> > This is considered good programming practice.
>>
>> I'm concerned that this statement is much more true
>> in a Java-centric world than a Go-centric one.
>>
>> > A third thing...
>> >
>> >   Have these guidelines stored in the source code tree.  Perhaps as
>> >   a HACKING document in the root?
>>
>> +1
>>
>>   cheers,
>>     rog.
>>
>> --
>> Juju-dev mailing list
>> Juju-dev at lists.ubuntu.com
>> Modify settings or unsubscribe at:
>> https://lists.ubuntu.com/mailman/listinfo/juju-dev
>>
>
>
> --
> Juju-dev mailing list
> Juju-dev at lists.ubuntu.com
> Modify settings or unsubscribe at:
> https://lists.ubuntu.com/mailman/listinfo/juju-dev
>
>


-- 
** Frank Mueller <frank.mueller at canonical.com>
** Software Engineer - Juju Development
** Canonical
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ubuntu.com/archives/juju-dev/attachments/20130823/c25ebaf6/attachment.html>


More information about the Juju-dev mailing list