In [52]:
from IPython.display import Image
from IPython.core.display import HTML

Image(filename = "./images/interface_meme.jpg")


Out[52]:

Object identity is a frail reed upon which to rely.

Whenever I use the word 'is', except in sheer tautology, I deeply misuse it.

George Santayana, philosopher

Critical analysis of [design patterns] and design needs is not an optional issue: without it, you cannot spot what patterns are anti-patterns, in terms of your actual design needs — including what programming languages you intend to target with your design.

Five Easy Pieces: Simple Python Non-Patterns

Learning programming functional style in JavaScript.

I have been making an effort to learn more JavaScript by going through basic tutorials for React which is a JavaScript library.

As I was reading tutorials and referencing some books about JavaScript, I realized that my mind was mismapped when it came to the word interface.

The admonition of the gang of four of Design Patterns kept coming to mind.

And then I saw the admonition explicitly displayed in Eric Elliott's book:

Program to an interface, not an implementation. — The Gang of Four, Design Patterns

Interfaces are one of the primary tools of modular software design. Interfaces define a contract that an implementing module will fulfill.

For instance, a common problem in JavaScript applications is that the application stops functioning if the Internet connection is lost. In order to solve that problem, you could use local storage and sync changes periodically with the server. Unfortunately, some browsers don’t support local storage, so you may have to fall back to cookies or even Flash (depending on how much data you need to store).

Elliott, Eric (2014-06-26). Programming JavaScript Applications: Robust Web Architecture with Node, HTML5, and Modern JS Libraries (Kindle Locations 2752-2759). O'Reilly Media. Kindle Edition.

So then I had to ask myself…

"Do I really know what this means?" Do I know what an interface is in the context of the gang of four design patterns sense?

Sometimes it is easier and much more interesting to know what something is NOT rather than what it is.

Knowing what interface is NOT.

Caution

Do not confuse the concept of the interface with terms like graphical user interface (GUI). Although a GUI is, as its name implies, an interface, the term interfaces, as used here, is more general in nature and is not restricted to a graphical interface.

Weisfeld, Matt (2008-08-25). The Object-Oriented Thought Process (Developer's Library) (Kindle Locations 1027-1029). Pearson Education. Kindle Edition.

Therefore…

knowing what an interface is NOT makes it easier to grasp what interface is meant to be in the context of object oriented programming. Sandi Metz explains:

The methods that make up the public interface of your class comprise the face it presents to the world.

Metz, Sandi (2012-09-05). Practical Object-Oriented Design in Ruby: An Agile Primer (Addison-Wesley Professional Ruby) (p. 62). Pearson Education. Kindle Edition.

And then I recalled…

from a long time ago when I was learning PHP that PHP actually has a thing called interface and that Java does, too.

Java includes a concept called interfaces. A Java interface is a bit like a class, except a Java interface can only contain method signatures and fields. An Java interface cannot contain an implementation of the methods, only the signature (name, parameters and exceptions) of the method.

Java Interfaces

So when…

the gang-of-four admonition Program to an interface, not an implementation. is quoted, the meaning of interface is likely meant in the sense that it is in a Java interface sense.

While the concept…

of interface still applies in non-staticlly typed languages such as Python and Ruby, its meaning is used in a more abstract sense rather than in a language-enforced sense.

❝…languages that force you to be explicit about this transition do offer a benefit. They make it painfully, inescapably, and explicitly clear that you are defining an abstract interface. It is impossible to create an abstraction unknowingly or by accident; in statically typed languages defining an interface is always intentional.❞ —Sandi Metz

Because statically typed languages have compilers that act like unit tests for types, you would not be able to inject just any random object into Gear. Instead you would have to declare an interface, define diameter as part of that interface, include the interface in the Wheel class, and tell Gear that the class you are injecting is a kind of that interface.

Rubyists are justifiably grateful to avoid these gyrations, but languages that force you to be explicit about this transition do offer a benefit. They make it painfully, inescapably, and explicitly clear that you are defining an abstract interface. It is impossible to create an abstraction unknowingly or by accident; in statically typed languages defining an interface is always intentional.

Metz, Sandi (2012-09-05). Practical Object-Oriented Design in Ruby: An Agile Primer (Addison-Wesley Professional Ruby) (p. 54). Pearson Education. Kindle Edition.

And then to add to my confusion…

Matt Weisfeld points out that there are interfaces to the classes as well as to the methods!

Interfaces Versus Interfaces

It is important to note that there are interfaces to the classes as well as the methods—don't confuse the two. The interfaces to the classes are the public methods while the interfaces to the methods relate to how you call (invoke) them.

Weisfeld, Matt (2008-08-25). The Object-Oriented Thought Process (Developer's Library) (Kindle Locations 705-708). Pearson Education. Kindle Edition.

Note: This book The Object-Oriented Thought Process uses Java for its examples so is using "interface" to mean what it means canonically in object oriented programming.

In general, reusable classes tend to have interfaces that are more abstract than concrete. Concrete interfaces tend to be very specific, whereas abstract interfaces are more general. However, simply stating that a highly abstract interface is more useful than a highly concrete interface, although often true, is not always the case.

It is possible to write a very useful, concrete class that is not at all reusable. This happens all the time, and there is nothing wrong with it in some situations. However, we are now in the design business, and want to take advantage of what OO offers us.

So our goal is to design abstract, highly reusable classes—and to do this we will design highly abstract user interfaces. To illustrate…

Weisfeld, Matt (2008-08-25). The Object-Oriented Thought Process (Developer's Library) (Kindle Locations 1179-1185). Pearson Education. Kindle Edition.

As another example, consider an automobile. The interface between you and the car includes components such as the steering wheel, gas pedal, brake, and ignition switch. For most people, aesthetic issues aside, the main concern when driving a car is that the car starts, accelerates, stops, steers, and so on. The implementation, basically the stuff that you don't see, is of little concern to the average driver. In fact, most people would not even be able to identify certain components, such as the catalytic converter and gasket. However, any driver would recognize and know how to use the steering wheel because this is a common interface.

By installing a standard steering wheel in the car, manufacturers are assured that the people in their target market will be able to use the system. If, however, a manufacturer decided to install a joystick in place of the steering wheel, most drivers would balk at this, and the automobile might not be a big seller (except for some eclectic people who love bucking the trends). On the other hand, as long as the performance and aesthetics didn't change, the average driver would not notice if the manufacturer changed the engine (part of the implementation) of the automobile.

Weisfeld, Matt (2008-08-25). The Object-Oriented Thought Process (Developer's Library) (Kindle Locations 1036-1045). Pearson Education. Kindle Edition.

The module concept.

Module

We can use functions and closure to make modules. A module is a function or object that presents an interface but that hides its state and implementation. By using functions to produce modules, we can almost completely eliminate our use of global variables, thereby mitigating one of JavaScript’s worst features.

Crockford, Douglas (2008-05-08). JavaScript: The Good Parts: The Good Parts (Kindle Locations 846-849). O'Reilly Media. Kindle Edition.

Douglas Crockford points out…

the utility of modules in JavaScript which provides namespacing. This brings to mind the last item of the Zen of Python:

Namespaces are one honking great idea -- let's do more of those!

And in Python module creation is easy. You only have to put Python code into a file and it becomes a module!

A module is a file containing Python definitions and statements.

https://docs.python.org/2/tutorial/modules.html

Because Python doesn't have (and doesn't need) a formal Interface contract, the Java-style distinction between abstraction and interface doesn't exist. If someone goes through the effort to define a formal interface, it will also be an abstract class. The only differences would be in the stated intent in the docstring.

http://stackoverflow.com/questions/372042/difference-between-abstract-class-and-interface-in-python


In [53]:
%%HTML
        
  <div style="background-color:#d9edf7;color:#31708;border-color:#bce8f1;padding: 15px;margin-bottom: 20px;border: 1px; border-radius:4px;">
  <strong>psittacism: </strong> <p>automatic speech without thought of the meaning of the words spoken</p>
  <p>New Latin psittacismus, from Latin psittacus parrot + -ismus -ism</p>
  <citation>Psittacism. (n.d.). Retrieved August 24, 2016, from http://www.merriam-webster.com/dictionary/psittacism</citation>

  </div>


psittacism:

automatic speech without thought of the meaning of the words spoken

New Latin psittacismus, from Latin psittacus parrot + -ismus -ism

Psittacism. (n.d.). Retrieved August 24, 2016, from http://www.merriam-webster.com/dictionary/psittacism

In [54]:
%%HTML

<a title="By John Moose (originally posted to Flickr as Moluccan Cockatoo) [CC BY 2.0 (http://creativecommons. org/licenses/by/2.0)], via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File%3ACacatua_moluccensis_-Cincinnati_Zoo-8a.jpg"><img width="256" alt="Cacatua moluccensis -Cincinnati Zoo-8a" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Cacatua_moluccensis_-Cincinnati_Zoo-8a.jpg/256px-Cacatua_moluccensis_-Cincinnati_Zoo-8a.jpg"/></a>


So in conclusion…

while it is easy to psittacistically repeat

Program to an interface, not an implementation.

I have to stop and ask myself, "Does that word mean what I think it means?"

Here is an example of how one might use the concept of an interface in Python by using classes and inheritance.

Some code…

Using an introspection tool from included library in Python.


In [55]:
import inspect

Python does not have interfaces. If it did, it would look something like this. Interfaces can be imitated with a class.


In [56]:
class AbstractShape:
    """Abstract (base) class for shapes."""
    
    def draw(self, ):
        """Draw shape."""
        
        error_message = "Method {} not defined. Abstract shapes have no idea what to draw!"\
            .format(self.draw)
        raise NotImplementedError(error_message)

If one tries to make an instance of AbstactShape and calls obj.draw() an ImplementationError is raised because the shape is abstract. It has no idea what to draw.


In [57]:
try:
    shape = AbstractShape()
    shape.draw()
except NotImplementedError as e:
    print(Exception(e))


Method <bound method AbstractShape.draw of <__main__.AbstractShape object at 0x7ff9f6773c18>> not defined. Abstract shapes have no idea what to draw!

If one tries to make an instance of Cirlce and calls cirlce.draw() an ImplementationError is not raise because the shape is no longer abstract.


In [58]:
class Circle(AbstractShape):
    """Circle implements AbstactShape."""
    
    def __init__(self, ):
        print("My ancestors are {}".format(inspect.getmro(Circle)))
    
    def draw(self, ):
        print("An instance of {} {} is drawing itself via {}."\
            .format(super(), self, self.draw))
        print("<circle appears>")

In [59]:
circle = Circle()
circle.draw()


My ancestors are (<class '__main__.Circle'>, <class '__main__.AbstractShape'>, <class 'object'>)
An instance of <super: <class 'Circle'>, <Circle object>> <__main__.Circle object at 0x7ff9f6753588> is drawing itself via <bound method Circle.draw of <__main__.Circle object at 0x7ff9f6753588>>.
<circle appears>

In [60]:
class Square(AbstractShape):
    """Square implements AbstactShape."""
    
    def __init__(self, ):
        print("My ancestors are {}".format(inspect.getmro(Square)))
    
    def draw(self, ):
        print("An instance of {} {} is drawing itself via {}."\
            .format(super(), self, self.draw))
        print("<square appears>")

In [61]:
square = Square()
square.draw()


My ancestors are (<class '__main__.Square'>, <class '__main__.AbstractShape'>, <class 'object'>)
An instance of <super: <class 'Square'>, <Square object>> <__main__.Square object at 0x7ff9f6fb9ba8> is drawing itself via <bound method Square.draw of <__main__.Square object at 0x7ff9f6fb9ba8>>.
<square appears>

Create a list of shapes by instantiating Circle and Square.


In [62]:
shapes = [class_() for class_ in (Circle, Square)]
print(shapes)


My ancestors are (<class '__main__.Circle'>, <class '__main__.AbstractShape'>, <class 'object'>)
My ancestors are (<class '__main__.Square'>, <class '__main__.AbstractShape'>, <class 'object'>)
[<__main__.Circle object at 0x7ff9f6fb9dd8>, <__main__.Square object at 0x7ff9f6fb9e10>]

Invoke bound draw method on each shape instance.


In [63]:
for shape in shapes:
    shape.draw()


An instance of <super: <class 'Circle'>, <Circle object>> <__main__.Circle object at 0x7ff9f6fb9dd8> is drawing itself via <bound method Circle.draw of <__main__.Circle object at 0x7ff9f6fb9dd8>>.
<circle appears>
An instance of <super: <class 'Square'>, <Square object>> <__main__.Square object at 0x7ff9f6fb9e10> is drawing itself via <bound method Square.draw of <__main__.Square object at 0x7ff9f6fb9e10>>.
<square appears>

NB: This blog post was created entirely inside of a Jupyter Project notebook and then transpiled into static blog pages by Pelican using the pelican-ipynb plugin. That is why you can see some raw HTML in cells that results in rendered output.