Saturday, July 19, 2008

Object Oriented Programming is not Procedural programming with structures

For beginners.

Object Oriented Programming is not Procedural programming with structures. They are 2 different ways to think about programs. This is a brief explanation of why the two approaches are different.


Procedural model

Procedural programs are a series of steps. It is the most natural and widespread style of programming. The first HL language - Plankalk├╝l - was a procedural language.

I don't know why Procedural programming is natural... but think about the first program you were taught. Nope, not "Hello World!". More like the program to tie your shoes, or the program to use the big boy's potty. The program they taught you was a series of sequential actions - a procedure.

We use Procedural programming all the time. Cooking recipes for example. Procedural programming is easier to grasp.


The OO model

Object Oriented programming shift the focus away from the procedure to the definition and combination of high-level constructs. These constructs are called Objects.

Instead of being too theoretic, I'll jump into an example to illustrate why this is a major paradigm shift.


Example: Procedural approach

I found a good snippet to illustrate how they differ. Many thanks to Martin Carel.


#!/usr/bin/env python
# Thanks to Martin Carel from http://dev-logger.blogspot.com/

import time
import urllib
from elementtree import ElementTree

feed_link = "http://feeds.feedburner.com/37signals/beMH"
title, published_date = "", ""
TITLE_PATH = ".//item/title"
DATE_PATH = ".//item/pubDate"

while True:
feed = urllib.urlopen(feed_link).read()
tree = ElementTree.fromstring(feed)
fetched_title = tree.findtext(TITLE_PATH)
fetched_published_date = tree.findtext(DATE_PATH)

if title != fetched_title:
print fetched_title, fetched_published_date
title, published_date = fetched_title, fetched_published_date

time.sleep(5 * 60)

Writing this procedure was straightforward. I simply listed the steps needed to get the desired result. I didn't spend a lot of time analyzing my problem.


How am I going to write the OO program?

First, I have to think about the task at hand. Analysis is important. You cannot have a good OO program without understand your problem space well.

For example, I have to identify what concepts of the problem domain I will model as objects. Then I will define the relations between objects and what operations will be possible on them.

Finally, I have to express the program as a combination of the building blocks I defined earlier.


Example: Hybrid functional/OO approach

#!/usr/bin/env python
# Thanks to Martin Carel from http://dev-logger.blogspot.com/

import time
import urllib
from elementtree import ElementTree

class Feed:
class Entry:
def __init__(self, elem):
self.title = elem.findtext("./title")
self.last_updated = elem.findtext("./pubDate")

def __eq__(self, other):
return True if self.title == other.title else False

def __init__(self, url):
self.url = url
self.entries = []

def fetch(self):
feed = urllib.urlopen(self.url).read()
tree = ElementTree.fromstring(feed)
self.entries = [Feed.Entry(e) for e in tree.findall(".//item")]

def has_recent_post(self):
old = self.entries[:1]
self.fetch()
return old != self.entries[:1]

# High-level functionality
feed = Feed("http://feeds.feedburner.com/37signals/beMH")
while True:
if feed.has_recent_post():
print feed.entries[0].title, feed.entries[0].last_updated
time.sleep(5 * 60)


Why is this better?

You know instantly what the program does by looking at the high-level functionality. That's because I was able to match my program to the problem definition by defining the right constructs.

The OO approach forces you to create black boxes. A black box is an abstract element that you can use through it's input and output without having to know it's implementation. Engineers use them everyday.

Black boxes reduce complexity dramatically. It's easy to reason about them. First, each has an isolated and simple function. Second, the interactions between black boxes are explicit. They also reduce complexity by restricting the number of possible interactions. And since a black box can be made of other black boxes, they can organize your program into neat and coherent layers.

Black box designs are easier to understand. You can even choose to know only the boxes and layers of boxes that matter to you. You cannot do the same with a procedural program because nothing is isolated into a component that you can understand independently. You always have to understand how everything interacts.

The OO program is easier to extend because it has well defined extension points. New functionality can be added by adding methods to the class. And it can be used by using the method from the main program.

Lastly, having high-level components allows you to perform high-level operations like late binding and reflection. This is the source of OOP's real power and prowess. It is a very wide and interesting topic so I won't cover that here.

4 comments:

photosinensis said...

There's a problem in the second bit of code that renders it unusable, regardless of how much better its structure is.

Line 26: you're using an equality comparison. It should be an inequality comparison. I tested this myself. Currently, it'll be stuck in a loop that does nothing forever.

What's more, you will need a comparison function for the Entry object so that it will check the value of the old latest entry against the new latest entry, instead of comparing the value of the entries' memory addresses (the default behavior in Python). Here's what the entry class should look like:

class Entry:
def __init__(self, elem):
self.title = elem.findtext("./title")
self.last_updated = elem.findtext("./pubDate")

def __eq__(self, other):
if self.title == other.title: return self.last_updated == other.last_updated
else: return False

With these changes, one has a rudimentary command line feed reader in Python. <3 Python.

Yann said...

Thanks photosinensis. I corrected the code.

i80and said...

I believe that you define procedural and functional languages incorrectly. A procedural language (such as C) is based around the concept of defining subroutines or functions, and does allow for opaque, or as you phrased it, "black box" modules. That's a fundamental aspect of software development, after all.

A functional language (such as Haskell), for comparison, has a more mathematical basis, and is centered around evaluating mathematical functions of some variety. I personally don't know Haskell, Erlang, or such languages, so this is purely what I know from my explorations and from reading Wikipedia.

I suggest reading the relevant Wikipedia articles:
Procedural Programming
Functional Programming

My apologies in advance if I misunderstood some portion of your post. My various articles have certainly been misunderstood enough times to realize that such things can indeed happen easily.

Yann said...

@i80and

I define Procedural and Functional programming correctly.

Procedural languages - like C - allow the creation of black boxes through subroutines.
Subroutines can only abstract a small number of things.

Essentially, subroutines allow the creation of new 'actions'. Your program is then still a sequence of those actions.

Both Functional and OO languages give you more abstraction power. OOP allows you to do crazy things thanks to the Meta Object Protocol(MOP) for example. Functional languages have High-Order functions - functions which create and return other functions.

In terms of abstraction power, procedural languages are paper planes and functional/OO languages are Boeings. Same, but very different.

Happy to clarify,
Yann