I use this blog as a soap box to preach (ahem... to talk :-) about subjects that interest me.

Thursday, September 2, 2010

OO does it with Class[es]

This post begins a small series of postings on Object Oriented Technology.

In our everyday's life, we deal with objects all the time. Some are so small that they fit in the palm of our hand, and some are so large that we can walk into them and then even get lost in their interior.
In its basic meaning, an object is a material thing that falls under our senses. Notwithstanding the obviousness of this definition, objects have revolutionised the way in which we write computer programs.

Computers were initially seen as nothing more than glorified adding machines, only capable of performing sequences of mathematical operations. It took decades before they could also manipulate logical and symbolic entities, complex data structures independent of the underlying hardware architecture.

The term OOP (Object Oriented Programming) was introduced by Xerox in the 1970s but only took off with the introduction of C++ and Java. To understand what makes OO computer languages so different from the so called procedural languages like Fortran, Cobol, C, and Pascal, it is worth spending a few words on the evolution of computer languages.

Towards an increasing Level of Abstraction
Ultimately, all computer programs are converted into machine instructions to be executed by the computer's Central Processing Unit (CPU), which consists of one or more microprocessors.

Initially, there were only assembly languages specific to individual machines, which reflected the structure and operations of the CPU. They provided mnemonic codes for machine instructions and symbolic names for CPU registers and memory addresses. Nothing more than thin veneers laid over the native machine languages to make them easier to read.

The next step was to create languages with a syntax expressing often recurring operations, with each statement generally corresponding to a handful of machine instructions. In many cases, this made possible for the programmer to write code without caring about the underlying machine language. Checks performed during compilation managed to catch programming errors that had been impossible to detect with programs written in assembly language.

Although these languages could be extremely powerful (consider Fortran, Cobol and more recently C), they still were very close to the machine. The programmer still had to express himself in terms very close to what was best for the computer.

This was still very far from how we do things in our daily life. For example, if we want to drive a nail into a wall, we know that we need a hammer, because driving nails is one of the operations that the object hammer can perform. We are not [normally] interested in what muscles of the arm we need to flex or in how we should hold our feet while doing it. In other words, our focus is on the objects. The actions follow naturally.

As software systems grew in complexity, it quickly became clear that it was necessary to break them down into more manageable chunks. The trick was to isolate parts which could be developed as independently as possible and then integrated together to form the system. It was also important to keep duplications to a minimum, so as to avoid having to write, test, and update more code than necessary. This led to the introduction of modules, subroutines, functions and, in general, structured programming.

But the winning strategy was to introduce the layered model: a series of functions that operate together to form a consistent interface, while masking their internal complexity. Different layers rest on top of each other like the floors of a building. To understand how a layered system works, imagine a factory in which the ground floor contains raw materials and energy generators, the first floor the processing plant, the second floor the assembly line, and the third floor the packaging and shipping line. Each layer relies on the services and the products of the layers below but doesn't need to know how things are done there. Once a layer has done its job, it delivers its work products one floor upward, until the end product pops off the top.

In a layered system, the complexity of the products increases from the bottom up or, if we imagine it as a series of concentric spheres, from the kernel outward (ever heard of a Linux kernel?). But within each layer, the complexity remains manageable, because each layer is protected from having to deal with the details of the layers on which it relies.

This idea of encapsulating functionality is natural for us humans. We don't need to know how cars or microwave ovens work in order to use them. OO technology makes it natural for computer software as well.

OO basic Components
I have already introduced the concept of object as a material thing of which we are aware. With this definition, an object can be a single atom or the entire universe, depending on what we are focussing on. In other words, there is a containment hierarchy of objects, where the largest and more complex ones consist of simpler and smaller object. For example, the object "aCar" contains four wheel objects, one engine object, three seat objects, etc. And each one of these objects is itself an assembly of other objects, and so on down to atoms, particles, quarks... To be able to communicate, we focus on individual objects and take it from there.

One of the characteristics which set us apart from most animals is the capability of abstracting objects. For example, we can talk about cars in general, without referring to a specific one. Such a generic object is defined by its attributes and by what one can do with it. One of such generic object is called in OO terminology a class. Some classes are very similar to each other and only differ by few qualifying attributes. For example, the differences between a motorcar and a quad bike might just be in the number and shape of the seats and in the steering controls. When an object belongs to a class it is said that it is an instance of that class.

When an object belongs to a class, it has all the attributes of that class. The opposite is obviously not true, as objects can have many more attributes than those of the class to which they belong. For example, if both objects "aCar" and "anAirplane" belong to the class "MeansOfTransportation", this means that "MeansOfTransportation" cannot have "wings" as an attribute; otherwise the object "aCar" couldn't belong to it!

All objects actually belong to several classes. For example, a particular car can belong to the classes " MeansOfTransportation", "SelfPoweredMechanicalDevice", "ObjectHeavierThan100Pounds", "SilverGrayThing", "GasGuzzler", etc.

In fact, the attributes of each object are the sum of all attributes of all classes to which the object belongs (i.e. which it instantiates). Fortunately, for most practical purposes, we can safely ignore most attributes. For example, when designing the "Employee" class to be used in a payroll program, we are not likely to have to define attributes for the colour of her hair or the size of her shoes.

Attributes are part of defining classes but not sufficient to fully define them. To do that, we also have to consider the class behaviours. In other words, what can an object belonging to a particular class do? A car can carry people from A to B, be refuelled, break down, turn left, etc. The behaviours (i.e., the actions) of a class are called methods. Exactly like with attributes, when we are defining methods we obviously have to concentrate on behaviours that are relevant in the context in which we operate. For example, some reasonable methods for the class "Employee" in a payroll program would be "list all", "change salary", "change department". It wouldn't probably make any sense to have methods like "have a smoke" or "get a back rub"!

Articles and books on OO often speak of "sending a message” to an object, instead of "executing a method" for it.

The collection of attributes and methods of a particular class is usually referred to as its interface.

Summary of Key OO Terms:
Term Meaning
class groups objects in terms of attributes and behaviours
object instance of a class, belongs to a class
attribute defining property of a class or an object
method defining behavior of a class or an object
interface attributes and methods of a class considered collectively

An old idiom states: "there are many ways to skin a cat". There are certainly more ways to define a class!

No comments:

Post a Comment