Program to an interface, not an implementation 
Author Message
 Program to an interface, not an implementation

Hello,
Can someone shed some light on the GoF adagium:
'program to an interface, not an implementation'
and especially what it means for programming in python ?
GoF is not easy.
egbert
--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS  Amsterdam - 020 6257991
========================================================================


Mon, 22 Nov 2004 18:12:00 GMT  
 Program to an interface, not an implementation

Quote:

> Hello,
> Can someone shed some light on the GoF adagium:
> 'program to an interface, not an implementation'
> and especially what it means for programming in Python ?

The difference is quite simple: for a given class, its interface is the set
of its public methods, with their syntax (parameters, return value(s)) and
semantics (what they should perform). In other terms, the interface of a
class defines _what_ the class should do. The implementation for a class is
_how_ things are done, i.e. the actual code of the methods, performing the
"what" defined in their semantics, including algorithms, call to
protected/private methods, and so on...

For example, for a "sort" method on a list, you may define like in Python
that it has no parameters, no return value and that it sorts the list "in
place". This is the interface, i.e. the "what". The "how" will be the
actual algorithm, which may be any of the well-known algorithms for sorting
lists.

"Program to an interface, not an implementation" means that the caller of a
method on a class should only rely on "what" the method should do, not on
"how" it's done. In the example, it just means that you'll use the "sort"
method for what it's done (sorting a list), and nothing more. When told
like that, it may seem quite obvious, but imagine for example that you
coded the "sort" algorithm and that during this algorithm, you had to set
an attribute of the list to the list length. If after doing the "sort", you
use this attribute to get the list length, you're using a side effect of
your algorithm that should have remained hidden from the outside. That's
what is called "programming to an implementation": it's *because* your
"sort" method is coded like you did that you can use the attribute.

In fact, saying "program to an interface, not an implementation" is just a
way to describe the traditionnal OO concept of "encapsulation": the exposed
part of a class is its interface; how methods are implemented inside the
class should remain hidden. The aim of this is to allow future changes in
the implementation of your class without affecting its interface. In the
example, imagine that you coded a simple but quite inefficient sort
algorithm, and that someday, somebody comes and wishes to use a more
efficient quick-sort: given the interface of the "sort" method, he has no
way to know that you used the attribute giving the list length. So his
modifications may break your code if he doesn't set the list length
attribute anymore.

In fact, I often say that a good OO programmer should be schizoid: the
person who codes the actual algorithms should not be the same than the one
who uses them, even if it's the same physical person. You should always
define the interface of your classes, implement them, then forget
everything you did during the implementation phase, and finally write the
code that uses the classes, just looking at the interface you defined in
the first place.

Hope it's a bit clearer now...
--

PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com



Mon, 22 Nov 2004 22:15:41 GMT  
 Program to an interface, not an implementation
I found it a little bit helpful to think of
'program to an interface, not an implementation' as 'treat all objects the
same'

   The Composite pattern of DP is a good example.  The example they give is
of a
grouping/collection/tree of various GUI widgets.  This might be a common
method
of keeping track of and displaying various windows on a panel.  
   When a widget needs to be updated, various things have to happen for
different
widgets, a Button needs a button update, an edit field needs an edit update
etc...
One way of doing this is to step though the tree, find out what type of
widget we
are dealing with and call the appropriate draw function

        for widget in tree:
                if widget.type == button.type:
                        widget.drawButton()
                elif widget.type == edit.type:
                        widget.drawEdit()
                etc..

Of course this is a poor way to do things, and makes adding new types of
widgets to
the tree extremely difficult.  By programming to an interface, you treat all
objects
the same way by calling the same function regardless of the object.  This is
shown in
the Composite example by having all widgets implement the Graphic interface
which defines
a single Draw() function that specific classes override.  For C++ or Java
this is done by
having the widgets either subclass the parent Graphic class, or (java only)
implementing a
Graphic interface.  Then the tree does not know whether or not it has
Buttons or Edit fields
all, it is dealing with Graphic objects, so all the tree needs to know is
the Graphic.Draw()
function.  This way you can add or modify specific widgets to the tree
pretty easily.
In python the updated code for drawing all the objects in the Composite
might be

        for graphic in tree:
                graphic.Draw()

MUCH simpler than the above.

   Now comes the beautiful part, Python's dynamic typing.  When the GoF
refers to an 'interface'
it is an abstract term that means 'a set of functions an object implements',
which isn't necessarily
a concrete thing like a Java Interface is.  
   So for two Python objects to share the same interface, (assume the
Graphic interface) above, they
simply have to have the functions that a Graphic object has, they do not
need to be subclassed from
a common parent or related in any way!!!!  When you say object.Draw() python
simply looks to see if
that object has a Draw() function, if it does great.  This way you can keep
radically different objects
in your Composite tree and treat them the same way regardless of what they
are, no casting or subclassing
required!  Because of it's dynamic typing Polymorphism is a snap in Python.

  You can see this quite frequently in many Python programs that operate
with 'file-like' objects,
ie objects that have read() and write() operations, and these can be
sockets, files, or StringIO's which are not part of any common class
hierarchy yet the programs work normally with any of those.

Hope that helps...

Quote:
-----Original Message-----

Sent: Thursday, June 06, 2002 3:12 AM

Subject: Program to an interface, not an implementation

Hello,
Can someone shed some light on the GoF adagium:
'program to an interface, not an implementation'
and especially what it means for programming in Python ?
GoF is not easy.
egbert
--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS  Amsterdam - 020 6257991
========================================================================

--
http://mail.python.org/mailman/listinfo/python-list



Mon, 22 Nov 2004 23:30:06 GMT  
 Program to an interface, not an implementation


Quote:
> Hello,
> Can someone shed some light on the GoF adagium:
> 'program to an interface, not an implementation'
> and especially what it means for programming in Python ?
> GoF is not easy.

Sure we can even use python as the example (-:

Any object can act like a list or a dict if they implement the right methods.
This is an interface.

l = [1,2,3] # use a python list

uses the implementation.

To further this, if your class included code which made decisions based on how
you knew say dict was implemented rather than just using ['string'] or
.has_key() that would be violating the interface.



Tue, 23 Nov 2004 00:01:33 GMT  
 Program to an interface, not an implementation
All your comments are crystal clear. Thanks.

My next problem is on nearly the same page (17) of the GoF book:
class versus interface (== type) inheritance, but in the python context.

"In C++ and Eiffel inheritance means both interface and implementation
inheritance" and
"in Smalltalk inheritance means just implementation inheritance".
I don't know any of these languages.

Now in my simplistic worldview, if you inherit from a class,
you inherit everything, implementation and interface,
because the implementation defines the interface as well.
Even if all methods of the superclass only contain 'pass'.
But I may be wrong.
egbert
--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS  Amsterdam - 020 6257991
========================================================================



Tue, 23 Nov 2004 16:48:22 GMT  
 Program to an interface, not an implementation
[Egbert Bouwman]

Quote:
> My next problem is on nearly the same page (17) of the GoF book:
> class versus interface (== type) inheritance, but in the python context.

As the following shows, inheritance in Python is implementation inheritance.
In this particular case, the subclass inherits a method they MUST override,
but you could easily provide an implementation that actually does something
too.  I'm not sure whether this answers your question, though--I haven't
been following this thread.

class PersistentBase:

    def save(self):
        raise NotImplementedError

class Invoice(PersistentBase):

    pass

i = Invoice()

try:
    i.save()
except NotImplementedError:
    pass
else:
    raise

Cheers,

// mark

-



Tue, 23 Nov 2004 18:43:02 GMT  
 Program to an interface, not an implementation

Quote:

> All your comments are crystal clear. Thanks.

> My next problem is on nearly the same page (17) of the GoF book:
> class versus interface (== type) inheritance, but in the python context.

> "In C++ and Eiffel inheritance means both interface and implementation
> inheritance" and
> "in Smalltalk inheritance means just implementation inheritance".
> I don't know any of these languages.

> Now in my simplistic worldview, if you inherit from a class,
> you inherit everything, implementation and interface,
> because the implementation defines the interface as well.
> Even if all methods of the superclass only contain 'pass'.
> But I may be wrong.

I know C++ and I looked at SmallTalk a bit, and it seems the line between
"implementation + interface" and "implementation only" inheritance is very
thin... Apparently, it's quite directly related to strong typing and
declarations. "Interface", in this context, seems to describe what's
declared. So, as you noted in the beginning of your post, an "interface" is
considered as a declared type. Since SmallTalk claims to have no types at
all (which is also the case with Python...), they claim not to have such
thing as an "interface", so obviously they cannot inherit it...

In fact, I don't see the point in this: as you noted, when a class inherits
from another, it inherits everything, implementation and interface. So in
practice, it's not really significant. As I understand it, the only
practical consequence of this distinction *may* be in the following case:

class A:
  def m(self, i):
    pass
class B(A):
  def m(self, i, j):
    pass

In Python or SmallTalk, the preceding code is completely valid, so one
could say that the "interface" of class A was not inherited by class B,
since its method m has a different signature than A's method m.

Trying to do the same thing in interface-inheriting languages would not
have the same effect at all: it would either be forbidden, or even have
stranger consequences. In C++ or Java, it would declare a *second* method,
also called m, that would be distinguished from the inherited one by its
number of parameters or their type:

public class A {
  public int m(int i) {
    ...
  }

Quote:
}

public class B inherits A {
  public int m(int i, int j) {
    ...
  }
Quote:
}

...
o = new B();
o.m(1)      // Calls A.m
o.m(1, 2)   // Calls B.m

So, as you see, you probably can live without knowing anything about all
this and still be able to do great stuff with whatever language you like
:-).

However, if anybody knows a bit more than me about implementation/interface
inheritance, I'd be glad to learn (I happen to teach OO sometimes and I'd
like to be able to answer this question precisely if it ever gets answered
to me ;-).
--

PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com



Wed, 24 Nov 2004 00:30:56 GMT  
 Program to an interface, not an implementation
"My next problem is on nearly the same page (17) of the GoF book:
 class versus interface (== type) inheritance, but in the python context.

 In C++ and Eiffel inheritance means both interface and implementation
 inheritance and in Smalltalk inheritance means just implementation
inheritance.
 I don't know any of these languages."

   To understand this comment that they make you have to make sure you've
got the
previous distinction they make between an objects class and an objects type.
An objects CLASS is an objects IMPLEMENTATION, while an objects TYPE is the
INTERFACE or functions it has.  Note that an object has ONE implementation
but can
have MANY types.
   Unfortunately the best example I have is the C++/Java vs Smalltalk/Python
example.
Perhaps if you said what languages you were familiar with we might be able
to provide
more relevant examples.  But I hope you'll get enough to make sense of
this...

   In C++ (and perhaps to some extent) Java, a class is simply a template
for instantiating
objects.  Because of the static typing of C++/Java an objects class and type
are directly
tied together.  The class directly defines an objects type  You can't have
one w/o the other.
Meaning you can't try and call an operation on an object unless it was
explicitly defined when
the code was compiled.
  Example, if you want to have a piece of client code that performs the same
operation on two
different objects, those two different objects must both be subclasses of a
common parent.
This is class inheritance. C++ is going to force you to cast these objects
to a specific type
(the parent) before you can call the common method.  So now you have two
different objects of
the same type, but they are forced to share implementation since you had to
use class inheritance
to do it.  I'll avoid the technicalities of pure virtual/abstract classes
here, the point is the
same.
   Example again of the common widgets..in c++ the classes would be forced
to inherit from a
common parent.  Class Widget would define Draw() operation.  Class Button
and Class Text would
be subclasses of Widget and would override Draw().  If you want to place
both of these objects into
a collection you'd have to specifically cast them to a Wdiget.

   With Smalltalk and Python things are much different.  Not only do you
have dynamic typing, but
classes are themselves objects that you can manipulate and call operations
on.  The dynamic typing
brings us back to the answers from your previous question.  Due to the
dynamic typing, two objects
only have to have the same operations defined to share types, REGARDLESS of
their implementations or
class relationships.  You can TRY and call any operation on ANY object, if
its there great all is well,
if not you'll get a runtime exception.
   Example again in Python of file-like object.  Assume your client code has
a collection of objects
that it performs reads and writes to.  In python those objects can be
sockets, files, or stringIO's since
those object share the same type, ie all have read and write methods.
However none of those objects share any sort of implementation, meaning they
are not subclasses of a common ancestor.

  So class inheritance is standard classing and subclassing, whereas
interface inheritance is multiple
objects having the same type.  With interface inheritance you can swap in
and out different objects into
your client code regardless of the implementation/class that they are, and
all will work well.

For C++ interface inheritance REQUIRES class inheritance.  For
Python/Smalltalk, it does not.

Quote:
-----Original Message-----

Sent: Friday, June 07, 2002 9:31 AM

Subject: Re: Program to an interface, not an implementation


> All your comments are crystal clear. Thanks.

> My next problem is on nearly the same page (17) of the GoF book:
> class versus interface (== type) inheritance, but in the python context.

> "In C++ and Eiffel inheritance means both interface and implementation
> inheritance" and
> "in Smalltalk inheritance means just implementation inheritance".
> I don't know any of these languages.

> Now in my simplistic worldview, if you inherit from a class,
> you inherit everything, implementation and interface,
> because the implementation defines the interface as well.
> Even if all methods of the superclass only contain 'pass'.
> But I may be wrong.

I know C++ and I looked at SmallTalk a bit, and it seems the line between
"implementation + interface" and "implementation only" inheritance is very
thin... Apparently, it's quite directly related to strong typing and
declarations. "Interface", in this context, seems to describe what's
declared. So, as you noted in the beginning of your post, an "interface" is
considered as a declared type. Since SmallTalk claims to have no types at
all (which is also the case with Python...), they claim not to have such
thing as an "interface", so obviously they cannot inherit it...

In fact, I don't see the point in this: as you noted, when a class inherits
from another, it inherits everything, implementation and interface. So in
practice, it's not really significant. As I understand it, the only
practical consequence of this distinction *may* be in the following case:

class A:
  def m(self, i):
    pass
class B(A):
  def m(self, i, j):
    pass

In Python or SmallTalk, the preceding code is completely valid, so one
could say that the "interface" of class A was not inherited by class B,
since its method m has a different signature than A's method m.

Trying to do the same thing in interface-inheriting languages would not
have the same effect at all: it would either be forbidden, or even have
stranger consequences. In C++ or Java, it would declare a *second* method,
also called m, that would be distinguished from the inherited one by its
number of parameters or their type:

public class A {
  public int m(int i) {
    ...
  }

Quote:
}

public class B inherits A {
  public int m(int i, int j) {
    ...
  }
Quote:
}

...
o = new B();
o.m(1)      // Calls A.m
o.m(1, 2)   // Calls B.m

So, as you see, you probably can live without knowing anything about all
this and still be able to do great stuff with whatever language you like
:-).

However, if anybody knows a bit more than me about implementation/interface
inheritance, I'd be glad to learn (I happen to teach OO sometimes and I'd
like to be able to answer this question precisely if it ever gets answered
to me ;-).
--

PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com
--
http://mail.python.org/mailman/listinfo/python-list



Tue, 23 Nov 2004 23:43:23 GMT  
 Program to an interface, not an implementation
Again I learned a lot from both of you, and reading a couple of hours
in a C++ book helped as well. But it is not all crystal clear any more.

Eric says:

Quote:
> So, as you see, you probably can live without knowing anything about all
> this and still be able to do great stuff with whatever language you like

You should see my programs already. However I have the impression that
assimilating the GoF book will improve things enormously. And for that
I have to understand their and other terminology.
Compared to the terminologies the basic mechanisms look simple.

In Gordon's reply the venom is in the end:

Quote:
> For C++ interface inheritance REQUIRES class inheritance.  For
> Python/Smalltalk, it does not.

This I read as:
For Python interface_inheritance does not require class_inheritance.

So you can inherit an interface without inheriting the class,
but interface_inheritance by way of class_inheritance is possible as well.
That means at least two things:
- python has interface inheritance (which some people deny),
- interface_inheritance without class_inheritance is a kind of cultural
  (not genetical) inheritance: give it the same name and all is well.
  But for me that is only polymorphism !

I do all this hair splitting because the GoF say (still page 17)
that many patterns depend on the distinction between interface- and
implementation inheritance. How do you define in python the
interface inheritance the GoF talk about ?
egbert
--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS  Amsterdam - 020 6257991
========================================================================



Fri, 26 Nov 2004 18:19:52 GMT  
 Program to an interface, not an implementation

Quote:

> This I read as:
> For Python interface_inheritance does not require class_inheritance.

> So you can inherit an interface without inheriting the class,
> but interface_inheritance by way of class_inheritance is possible as
> well. That means at least two things:
> - python has interface inheritance (which some people deny),
> - interface_inheritance without class_inheritance is a kind of
> cultural   (not genetical) inheritance: give it the same name and all
> is well.   But for me that is only polymorphism !

Perhaps it would be better to skip the term interface_inheritance
altogether. In Javaspeak, you IMPLEMENT an interface, you promise that you
conform to a specification. In Java, this can be checked at compile time. In
Python, you could probably create interface objects which can check if a
given object or class implements all the methods that are required.

It is only polymorphism in the way the language runtime handles this. But it
is a difference in the way you document your software.

Quote:
> I do all this hair splitting because the GoF say (still page 17)
> that many patterns depend on the distinction between interface- and
> implementation inheritance. How do you define in python the
> interface inheritance the GoF talk about ?

An example from the module pickle:
  dump(object, file[, bin])
  ...
  file must have a write() method that accepts a single string argument. It
can thus be a file object opened for writing, a StringIO object, or any
other custom object that meets this interface.

You specify the methods that will be called. Having a well known object with
the required behaviour is always helpful.

The important part about 'programming to an interface' is this: If you're
implementing the 'dump' method, don't call arbitrary methods of a file
object just because you happen to test it with a file object.

Daniel



Fri, 26 Nov 2004 20:45:35 GMT  
 Program to an interface, not an implementation
[snip]

Quote:
> In Gordon's reply the venom is in the end:
>> For C++ interface inheritance REQUIRES class inheritance.  For
>> Python/Smalltalk, it does not.

> This I read as:
> For Python interface_inheritance does not require class_inheritance.

Nope: it simply means that there's no such thing as an interface in Python,
or more exactly that the interface of an object is figured out dynamically.
For example, this code works:

class A:
  def m(self):
    print "I'm A"
class B:
  def m(self):
    print "I'm B"
def f(o): o.m()
f(A())
f(B())

The function "f" uses the method "m" in both classes. However, classes "A"
and "B" are not related at all: neither do any inherits from the other, nor
do they have a common ancestor. In C++ (or Java), the Python code above
would be unwritable if the method "m" wasn't declared in a common ancestor
of A and B. If you write:

public class A {
  public void m() {
    System.out.writeln("I'm A");
  }

Quote:
}

public class B {
  public void m() {
    System.out.writeln("I'm B");
  }

Quote:
}

you would not be able to write the equivalent of the method/function "f"
than can act on either an instance of A or an instance of B. In C++ or
Java, the interfaces *must* be declared, so you'll have to write:

public class I {
  public abstract void m();

Quote:
}

public class A inherits I {
  public void m () {
    System.out.writeln("I'm A");
  }
Quote:
}

public class B inherits I {
  public void m () {
    System.out.writeln("I'm B");
  }
Quote:
}

...
public void f(I o) {
  o.m();

Quote:
}

Now you can call f on an instance of A or an instance of B, because you
have been able to *type* the object with the type (= interface) I.

Quote:
> So you can inherit an interface without inheriting the class,
> but interface_inheritance by way of class_inheritance is possible as well.

Again, nope: you cannot *inherit* an interface without inheriting from the
class. In fact, I find Gordon's sentence a bit unclear (sorry
Gordon...). Maybe it would be a little clearer if you spoke about
"interface *sharing*" instead of "interface inheritance":

"For C++ interface sharing REQUIRES class inheritance.  For
Python/Smalltalk, it does not."

In Python or SmallTalk, you may have the same (dynamically figured out)
interface without having to make classes inherit from a common ancestor. In
C++ or Java, it would be impossible, as we saw above...

In fact, things are a bit unclear because the word "interface" may be used
to represent two things:
- the actual set of methods with their signature (in the example, the
single method "m" with no parameters and no return value);
- the type used to define this set (in the Java flavour of the example, the
type "I")

The first exists in every OO language, but the second may not exist, like
in Python or SmallTalk. But both are always inherited by class inheritance
(at least in every OO language I know). In the GoF book, they only speak
about the second. But you may of course choose to force yourself to always
do interface sharing via inheritance. You may write the example above as
follows:

class I:
  def m(self):
    raise NotImplementedError
class A(I):
  def m():
    print "I'm A"
class B(I):
  def m(self):
    print "I'm B"
def f(o):
  # Here, we may say the o has the "type" I
  o.m()
f(A())
f(B())

In fact, making things as if Python had interfaces is just a matter of
discipline: in the function f, you choose to see the object o as an
instance of class I, and not to call any method not defined in class I,
even if you know the method will exist. For example, you may consider the
following code incorrect:

class I:
  def m1(self):
    raise NotImplementedError
class A(I):
  def m1():
    print "I'm A"
  def m2(self):
    pass
class B(I):
  def m1(self):
    print "I'm B"
  def m2(self):
    pass
def f(o):
  # o is considered as an instance of I
  o.m1()  # is correct...
  o.m2()  # is incorrect...

Of course, the "incorrectness" of the second line only happens in your
head, because the method "m2" exists on both classes A and B, so the Python
interpreter would not complain at all. But you may want to consider it
incorrect, because the method m2 does not exist in I... But to be able to
achieve that, you'll need to carefully document your code to know what
method calls are "legal" on the objects you handle. And this can only be
achieved by comments in your code and/or code documentation via UML
diagrams, for example. But it may be worth the effort, since, maybe,
someday you'll want to write a class C whose instances can be passed to f.
And at that time, it will be really easier to know which methods should be
implemented on C just looking at I...

Hope it's a bit clearer now...
--

PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com



Fri, 26 Nov 2004 23:48:55 GMT  
 Program to an interface, not an implementation
Quote:

> Hope it's a bit clearer now...

Yes, much clearer, thanks to you all, your patience and didactic
qualities. I suppose this thread is essential reading for any
intermediate python programmer interested in Design Patterns.
egbert
--
Egbert Bouwman - Keizersgracht 197 II - 1016 DS  Amsterdam - 020 6257991
========================================================================


Sat, 27 Nov 2004 16:57:53 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. CFP: PLILP93 Programming Language Implementation and Logic Programming

2. CFP: PLILP'93 (Programming Language Implementation and Logic Programming)

3. CFP: PLILP93 Programming Language Implementation and Logic Programming

4. CFP: PLILP'93 (Programming Language Implementation and Logic Programming)

5. COM: Interface Implementation question

6. Looking for Interface Inheritance Implementation

7. newbie question: implementation inheritance and interface specifications in Haskell 98

8. technical implementation details in language interface

9. Separating Interface and Implementation

10. interface-implementation separation

11. Implementations of C function interface?

12. Inheritance: Interface vs Implementation (was: Questions on inheritance)

 

 
Powered by phpBB® Forum Software