<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">...<br>
I have thought for a while that, rather than writing more error-prone code<br>
(at > 17k LOC, surely the API code is big enough as it is?), it would<br>
be good to create a tool that helps us with the underlying problem -<br>
incompatible changes made to marshaled types.<br>
<br>
This would not be too hard - the Go language already has such a tool<br>
(see <a href="http://golang.org/cmd/api/" target="_blank">http://golang.org/cmd/api/</a> ), although it is not currently generally<br>
applicable.<br>
<br>
This could make it possible to provide a much stronger assurance about<br>
compatibility, including compatibility between types not defined inside<br>
juju-core itself, while keeping the code natural and simple.<br>
<br>
cheers,<br>
rog.<br>
<div class="HOEnZb"><div class="h5"><br></div></div></blockquote><div><br></div><div>So that is interesting, and it might be fruitful to explore. I'll just note that it is actually a pretty small (and reasonably obvious) part of API compatibility. It *doesn't* tell you</div><div><br></div><div>1) If passing an empty string suddenly has a different meaning (see Client.ServiceSet where we used to treat "" as meaning reset-to-default vs Client.NewServiceSetForAPI where we wanted to actually treat "" as meaning set this value to the empty string.)</div><div><br></div><div>2) Returning a new value (Machine.Jobs(), we want to add new Jobs for new behaviors and don't want to confuse old agents until they have finished upgrading).</div><div><br></div><div>So while something like the above could tell you "has the shape of the API changed", and what I really like about it is that if it had a collapsed view (like a simple text representation), it is easy to keep that around in the source tree and use it for reference.</div><div><br></div><div>However, you really do need tests for (1) and (2). (1) we actually broke accidentally because we changed the code inside of state/*, and then had to go back and retrofit the API to use a new code path to preserve compatibility.</div><div><br></div><div>And if you need tests, you really still need 2 types to represent the different versions, and if you already need those types, then I would recommend having a regular structure for them.</div><div><br>John</div><div>=:-></div><div><br></div></div></div></div>