<div class="gmail_quote">On Sun, Aug 9, 2009 at 7:30 PM, Laurens Van Houtven <span dir="ltr">&lt;<a href="mailto:lvh@laurensvh.be">lvh@laurensvh.be</a>&gt;</span> wrote:<br><div> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
As you probably know, the interfaces for t.p live in t.p.ipositioning.<br>
I still haven&#39;t quite understood why they are going to be awesome, but<br>
anyway -- I&#39;m running into a problem where keeping them would (I<br>
think) imply a bunch of duplicated code.<br>
</blockquote><div><br>Have you read this?<br><br><a href="http://glyph.twistedmatrix.com/2009/02/explaining-why-interfaces-are-great.html">http://glyph.twistedmatrix.com/2009/02/explaining-why-interfaces-are-great.html</a><br>
 </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">The thing is, t.p.nmea.NMEAAdapter needs to (at least, I think so)<br>
implement all of the methods of t.p.ipositioning.IPositioningProvider,<br>
because people will subclass t.p.nmea.NMEAAdapter and override the<br>
corresponding (stub) methods.</blockquote><div><br>I don&#39;t think this is the case.  NMEAAdapter implements INMEAReceiver.  It should take an IPositioningProvider as an <i>argument</i> somewhere, not implement that interface itself.<br>
<br>A user implementing a position-aware application should be encouraged as strongly as possible to avoid any NMEA-specific junk in their application until it comes time to connect the app logic (IPositioningProvider) to the actual device spitting out NMEA data.  After all, they&#39;re not going to be able to easily make use of cell-tower positioning information if their application class is hard-coded to subclass NMEAAdapter.<br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">In order to get all of the stub methods
implemented (otherwise people using the class need to implement *every* method, which is dumb, since a lot of people won&#39;t care about
things like GPS climb),</blockquote><div><br>The general sentiment here is right, despite the terminology problem I pointed out: somewhere, a user is going to implement an IPositioningProvider and it&#39;s quite likely that they won&#39;t want to implement every method.  So let&#39;s assume there&#39;s going to be a BasePositioningProvider which stubs out many of these methods or unifies / simplifies them.<br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">I would basically be copying every line of the body of the interface into the t.p.nmea.NMEAAdapter.<br>
</blockquote><div><br>Not quite.  For one thing, your method declaration lines will have a &#39;self&#39; in BasePositioningProvider, and in IPositioningProvider they won&#39;t.  (I notice that this is not currently the case.  You should probably fix that: interface method definitions should never include &#39;self&#39;.)<br>
<br>Also, your methods&#39; docstrings won&#39;t need to be as complete as those on the interface, since they can just say &quot;implement L{IPositioningProvider.foo} to...&quot;.<br><br>Finally, I hope <i>most</i> of the methods will actually have a body that has some implementation; some default behavior that will be useful  For example, remembering the last position / heading / speed / error so that &#39;positionReceived&#39; can conveniently expect the last error received without implementing that method itself.  One or two might be completely stubbed out, but the interface can&#39;t contain any implementation.<br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">This sounds like a dumb idea.<br></blockquote><div> <br>Let&#39;s assume the worst case: BasePositioningProvider has absolutely no default behavior besides a no-op.  The level of duplication we&#39;re talking about here is this:<br>
<br>    def positionReceived(self, latitude, longitude):<br>    def positioningErrorReceived(self, positioningError):<br>    def headingReceived(self, heading):<br>    def headingErrorReceived(self, headingError):<br>    def magneticHeadingReceived(self, magneticHeading):<br>
    def altitudeReceived(self, altitude):<br>    def altitudeErrorReceived(self, altitudeError):<br>    def speedReceived(self, speed):<br>    def speedErrorReceived(self, speedError):<br>    def climbReceived(self, climb):<br>
    def climbErrorReceived(self, climbError):<br><br>In other words, the duplicated code in question will be considerably shorter than the body of the message you composed to fret about code duplication, and <i>way</i> shorter than my response :-). This doesn&#39;t really seem excessive, considering that there&#39;s no duplication of <i>functionality</i> (the interface only specifies behavior, the base class implements it), only duplication of text.<br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Subclassing the interface sounds like *entirely* the wrong thing to
do, since the class is-not-an Interface.<br>
</blockquote><div><br>You&#39;re definitely right here.  It isn&#39;t just conceptually wrong, it&#39;s also completely broken.  Subclassing an Interface creates another Interface (i.e. instance of InterfaceClass) not a class or type.  In other words, you can&#39;t instantiate it, and you can&#39;t call methods on it if you define any.  IIRC, more recent versions of zope.interface will actually emit warnings if you try to put methods which have definitions on an interface.<br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Another alternative is using getattr-with-default-value in order to<br>
call the methods, since then missing (non-implemented) methods will be<br>
handled gracefully. I kinda like this one, mainly because it&#39;s very<br>
little work ;-)</blockquote><div><br>It&#39;s more work than you think.  If you misspell a method name, then the code which invokes it will fail in a totally straightforward way: it won&#39;t invoke your method, and as a result it will probably blow up.  If you use getattr-with-default, then it silently does nothing.<br>
 </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">A third alternative would be to scrap the interface all together and<br>
use a base class with method stubs (I&#39;m deliberately not using the<br>
word abstract there). This sounds like a bad idea because we&#39;d be<br>
losing the interface, but I&#39;m not entirely sure why we want it in the<br>
first place...<br></blockquote></div><br>I believe the real problem here is that you don&#39;t quite get the value of interfaces.  Read that blog post that I linked to if you haven&#39;t already, and if you have, let&#39;s talk about that instead.<br>
<br>