As many GIS users become GIS developers, one of the harder ideas to fully digest is
object oriented programming (OOP). This section is not going to "teach" you the details
of OOP, but I will go over a few issues I've seen when people more from procedural coding
to writing actual OOP code of their own.
What is OOP?
Here's a good definition from Wikipedia...
Object-oriented programming may be seen as comprising a collection of cooperating objects,
as opposed to a traditional view in which a program may be seen as a collection of functions,
or simply as a list of instructions to the computer. In OOP, each object is capable of receiving
messages, processing data, and sending messages to other objects. Each object can be viewed as an
independent little machine with a distinct role or responsibility.
There is no magic to OOP, it is just a different way of thinking about and writing code. In many cases you may actually write more
lines of code, but the benefits far out weigh this extra effort.
Nomenclature: Classes vs. Objects
This is a question I always ask in interviews, and the answer is simple: an Object is an instance of a Class. What we
write as developers are classes. What exists in memory while the software is running are objects. Know it. Own it. Be it.
Procedural Programming with Objects
This is perhaps the most common first phase that most developers go through. Essentially, you are writing a
program using an API that is object oriented, but the code you write is not. The result is that you still end
up writing procedural code in "Big Ugly Functions". While it's common overall, I think it's especially prevalent
in GIS, and at some level it flows from the fact that many times we are automating a series of
tasks. When translating the series of tasks into code, the tendancy is to write this out in one big
function. While this can work (many examples show this sort of thing), it does have some problems -
primarily when things get complex. Maintaining this complex code soup is very difficult, and
as you may have guessed, using objects can really help out.
Rolling Your Own
Although it's very hard to convert a procedural application to an oject oriented application, it is relatively easy to
start thinking in objects (A good book to help out is Object Thinking
by David West).
When starting a project, make a list of the "things" you are working with. This is sometimes referred to as
creating the "Domain Model". Despite being very ephemeral, software tends
to deal with things in the real world, so locating your classes should be relatively easy. Once you have this list, start
thinking about what you need to know about them. The "need to know" part
is important because there could be hundreds of properties of the object (i.e. a car), but since we are trying to keep
things simple, we only want the properties that our software needs to know about. Next, we need to determine what that object can do.
This is also known as defining the methods.
Once we have all of these mapped out, we're well on our way to an object oriented solution - we just need to code it!
Encapsulation - Hiding the Details
This is where OOP really makes a difference. Back in the old procedural code, where everything was in one big long
function, everything "knew" the details of everything else. If you needed to change how one part of that function worked,
you'd likely need to make a lot of changes all over the code.
When we are working with classes, the details are hidden (or encapsulated) within the class, and the only details
its clients need to know about are it's properties and methods. How the method is implemented inside the class
is of no concern to the class calling the method - so long as the method returns the correct data. If a bug is found, the
developer can go back and make a change inside a method, and it will have no effect on the classes which call it. This
makes maintenance much simpler.
Writing Maintainable Code
If you are writing anything beyond a very simple tool for yourself, chances are you are going to
need to update the code at some time in the future, likely well after you have forgotten all the details which seemed
so obvious when you wrote it. Part of the solution lies in creating and maintaing design documentation, but
there are also things you can do in the code itself to make things easier. Here are a few tips for writing code you can
maintain without losing your mind.
- Keep methods short and focused
- Use understandable method names
- Use readable variable names
- Comment your code
- Comment your code
- Comment your code
Side Effects
Unlike special effects in movies, these are bad things to encounter. A
"Side Effect" occurs when something effects the internal
implementation of a method, in a way which is not expected. The end result is code
which may "look" correct, but acts incorrectly in certain situations.
A very common way to end up with
a mess of side effects is through the mis-use of "global" variables. In
this case, a the variable gets set in one place, and then changed in another, and finally used in some
other location - all of which is not apparent to the developer. These sort of
problems are really tough to track down.
The best way to avoid them is to not use globals if you don't need them.