Orders Orders Backward Forward
Comments Comments
© 1997 The McGraw-Hill Companies, Inc. All rights reserved.
Any use of this Beta Book is subject to the rules stated in the Terms of Use.

Chapter 13: Introduction to Object Oriented Programming for the Uninitiated and the Unaware

This chapter serves as an introduction to learning and using Object Oriented programming in Perl. A lot of ground is covered in a short amount of space, on our 30,000 foot flyover of object oriented programming. The other chapters in this section flesh out the skeleton that we begin here.

Chapter Overview - Modularity is the Programmer's friend.

There has been a lot of attention, bordering on hype about 'Objects' and 'Object Oriented' programming (OO for short). Programming languages are either praised or condemned for their "Object Oriented-ness" or lack thereof.

Applications that work just fine are being converted, often with much anguish, to object oriented languages, methodology and databases. The quickest resume stuffer is to say that you have done the 'OO thing' and then list out the OO projects you have done, and OO languages that you know.

Why all the excitement? Just what does it mean to be "object oriented"? How is it possible to use an OO-capable language and still not be doing object oriented programming? This chapter is designed as a quick primer on why object oriented programming is so hyped as it is, and why you might consider learning OO if you don't already.

Let's take a look at the advantages and disadvantages of using object oriented methodologies in application development.

The Advantages and Disadvantages of OO

The answer to why there is so much hype is because the hype is based on reality. There are many good reasons for businesses to want to use OO, but if they want to use OO, they have to do it right. Appropriately applied, object oriented programming is:

1) less expensive. Projects developed using OO tend to end up costing companies less money than if another technique were used, over the long term. This is because well written OO application are:

2) easier to change. Projects developed using OO tend to last longer than projects without OO. This means OO applications are more likely to grow with an organization and change with changing needs. After all, time-to-market is everything these days.

3) more manageable. Projects developed using OO tend to lend themselves to being divided up into well-defined chunks which can be given to developers.

4) more scalable. OO projects can be made larger, and more complex then projects in non-OO. This is inherent in the technology of OO programming methodology and in combination with OO-capable databases.

In the rush to make projects OO, the dark side of object oriented programming is often overlooked.

The plain fact is that not every application should be made object oriented. Object oriented languages are not inherently superior, more foolproof or more efficient in every case.

The disadvantages of Object Oriented programming are that it:

1) is more difficult to learn than its rival, procedural programming languages. Make no mistake about it, if you are used to procedural programming, you need to do some mental gymnastics in order to make the switch to the 'OO' way.

2) needs more patience to implement. You need to think before you do.

3) requires more of an up-front time commitment. It is very easy to negate the flexibility of the modularity of OO programming with poor design. OO languages can be used procedurally. Some projects out there have a million lines of code, using OO languages, and don't have a single object!

4) is harder to implement correctly. It is necessary to have the proper infrastructure in place for development, testing and the rollout to production. Once again, this is often overlooked in the rush to program.

5) can be difficult to find experienced, successful OO programmers, designers and project leaders. On the flip side, because object oriented programming is so effective and yet has such a steep learning curve, people who know OO can do extremely well in the business world.

So where does Perl fit in all of this? The great thing about Perl is that it lessens the learning curve for OO and lets you be productive at the same time.

Once you understand the concepts and a little syntax, you can start experimenting with object oriented programming, and by extension, other OO languages. With Perl you can do some very effective object oriented things such as database administration, system administration, and web programming, amongst others, without worrying about getting caught in a dead end technically.

In other words, Perl lets you do OO while you learn.

Understanding Object Oriented Programming

Let's first concentrate not on Perl's version of OO, but instead upon what OO is itself. Object Oriented programming is a method of programming that concentrates on making effective, reusable building blocks of code.

Just as it is easier to make a building out of bricks, girders, and wires (and a good building plan) than it is to make a building out of lime, rock, and iron ore, so - OO claims - that it is easier to build computer projects out of reusable components called classes (which implement objects) and to hook these classes together via a design notation. (Grady Booch is famous for his Booch notation, for instance).

OO has its associated terms, just as in any other discipline. The significant object oriented terms are:

Object: a self-contained unit of data that has subroutines to access and manipulate that data.

Class: a piece of code that implements objects. In Perl, classes are implemented via the keyword package.

Modules - object oriented programming is often called "modular" because it has parts that can be moved around and reused. In Perl, unfortunately, the term modules is used in two different ways, which causes much confusion. One definition, which is the OO one, is the file which contains a class. The second definition is a type of programming which concentrates on separating functions out into reusable code, without worrying about the corresponding data.

The second type of 'modular' programming is what we will cover in the next chapter.

Here are more important terms that deal with how OO programming is done are:

Abstraction is the process of taking units of code and separating them by themselves.

Encapsulation is the process of making a object 'self sufficient' so users of that class do not need to directly access the inner pieces of an object directly.

Inheritance is the process of reusing code by declaring a class as a particular type (or child) of another class. If a user calls a function inside the child class and the child class can't find it, it will look for it in the parent class instead, hence inheriting it.

Polymorphism is the process of making a single piece of code (whether a function, object, or class) behave in more than one way.

This whole next section goes into great detail on these concepts. Right now, lets concentrate on the programming concept of abstraction. The OO philosophy (if it can be called as such) is centered around abstraction.

Abstraction

Abstraction is a slippery term to define and understand. Abstraction is a point of focus. When looking at things at a 'high abstraction level', you are looking at them without caring for the details. If you talk about the Internet for example, saying:

the Internet is growing rapidly

then that is a high level of abstraction, since you are not looking at the details like routers, computers, IP addresses, and so forth (you could also make a strong case that this is a 'glittering generality' since it really doesn't say much about anything!). Once again, this is a high level of abstraction.

The concept of abstraction has a very important role in the manufacturing and design of complex systems. Consider an everyday object, the CPU of your computer:

1) Transistors are at the lowest level.

2) Combinations of transistors form logic gates (AND and OR gates are examples).

3) These logic gates are, in turn, combined into circuits called adders, which actually do the computations.

4) Adders are combined into circuit groups called units, as in the Floating Point unit, Arithmetic Logic Unit etc.

5) These units are finally combined into the CPU of your computer.

This is an abstraction scale. At each point in the abstraction scale the point of focus gets higher, as if we were pulling a camera away from the CPU so we could only see things at a certain level of detail. Furthermore, each element can be COMPOSED OF elements in the lower levels of abstraction.

This abstraction scale is essential in order to make and use the CPU. It would be ridiculous if an engineering VP had to focus on making custom-designed transistors, or focus on making custom-designed logic gates for every CPU to be shipped. Nothing would ever be done! If each transistor was hand-designed, then each chip would have hundreds of flaws. Likewise, we, as consumers of this chip would have to custom design our programs for each and every individual CPU.

We, as programmers, are totally dependent on a large number of components working correctly: CPU, operating system, compiler, etc.

How does OO programming fit in to all of this? Well, you can make an abstraction chain out of a programming language as well. With Perl, one starts with statements, then goes to functions, and then on to programs. As stated above, the next two steps in this abstraction chain are the elements that let Perl be OO-capable: modules and objects.

A module is a bundled set of subroutines, all of which have a common purpose. An object is a set of data which has subroutines associated with it, which perform operations on that data. A subsystem is a coherent set of modules/objects which are related to each other.

These structures are explained in detail later. Modules, objects, and subsystems are introduced here to demonstrate the abstraction chain for Perl.

Here is an abstraction chain for Perl:

1) At the lowest level are data structures which the computer understands directly such as ints, floats, characters, and so on, as well as low level operations on those data structures. Perl handles all of this internally.

2) Combinations of these simple data structures compose the data structures we are familiar with (hashes, arrays and scalars).

3) Combinations of these simple data structures with functions and operators make expressions. For example:

push(@array, 5);

4) Combinations of expressions make subroutines. For example:

sub swap

{

my ($pos1, $pos2, $arrayref) = @_;

@{$arrayref}[$pos1,$pos2] = @{$arrayref}[$pos2,$pos1];

}

5a) Combinations of subroutines make modules. For example:

package Array;

sub swap {} # code as above.

sub reverse { my($arrayref) =@_; @a = reverse(@a); }

is a module, with usage:

Array::swap(1,2,\@array);

Array::reverse(\@array);

Array just so happens to be a module that Perl provides by default.

5b) Combinations of data structures with subroutines to manipulate those data structures make objects.

package Array;

sub new

{

my ($type, $args) = @_;

my $self = {};

$self->{data} = [@$args];

bless $self, $type;

}

sub swap

{

my ($self, $pos1, $pos2) = @_;

my $arrayref = $self->{data};

@{$arrayref}[$pos1, $pos2] = @{$arrayref}[$pos2, $pos1];

}

6) Combinations of modules/objects make a subsystem. For example, if you had a Perl script that needed to run on both Sybase and Access databases, you might create a database subsystem, as in:

object DatabaseAccess

which is composed of

Database::Sybase

and

Database::Access

7) Combinations of subsystems make a system. This too, is a simplification, but a useful one.

The process of truly learning a computer language is effectively learning each level in this abstraction chain. You learn the data elements (abstraction level 2). You then learn how to manipulate them via expressions (abstraction level 3). You then learn how to put them into subroutines. (abstraction level 4). Unfortunately this is where many programmers stop in the learning curve.*

****** Begin FootNote**************

Now, It isn't always bad to stop at the subroutine level. Sometimes you simply need to get something working and get it working fast, and don't want to think about reuse of code. Furthermore, if you are learning the language for the first time, you probably want to concentrate on the building blocks of the language: hashes, arrays and subroutines. It is also one of the virtues of Perl that you can do extremely rapid prototypes by ignoring such issues as code reuse.

Remember, however, if you stick to the lower levels of the abstraction scale, you are condemning yourself to small projects and maintenance nightmares for a long time to come. We shall see this shortly.

****** End FootNote**************

 

You don't buy nuts and bolts at the hardware store and put them directly together into an automobile engine, do you? Unfortunately, that is what many of programmers do when they concentrate on using the power of Perl's syntax to make subroutines. (abstraction levels 3 and 4). A formal definition of procedural programming is a programming technique which concentrates on the series of steps that the computer does in order to get something done. If the programmer stops here, she is not using the object oriented capabilities of Perl.

Object oriented programming, on the other hand, is the process of programming by concentrating on the object (abstraction levels 5b, 6, 7). Instead of concentrating on the procedure (the subroutines, and data structures), the programmer concentrates on building common 'bundles' of data and subroutines called objects which then can be used and reused in programs. In other words, object oriented programming (OO for short) is a programming technique which concentrates on the object and how objects fit together. These objects then perform the tasks that make the application run.

This requires the programmer and project designer to shift focus and concentrate on the big picture. Instead of thinking about each task in isolation and then writing a bunch of statements to perform the task, as in:

open(FD, ">>log");

print FD "first log message\n";

close(FD);

Instead, think about the possibility of making a Log object first, and then using the log as in:

my $log = new Log("log");

$log->write("first log message");

See the difference? Both are a series of statements, both get something done. However, in the second piece of code, we forget about the details of a 'Log', and concentrate instead on higher-level operations on that log. These higher level operations are creating it (rather than operating on a low level filehandle), and writing to it, rather than printing to a low level filehandle.

This may not look like much, but consider when we want to change our 'log policy' (the example we will give in section 'Object examples' will be adding a timestamp to all our logs). What if there were a hundred scripts which write to a hundred logs? In the procedural example we would have to change all of these examples to look like:

open(FD, ">> log");

print FD localtime() . "\n";

print FD "first log message\n";

close(FD);

whereas in the second example, we would need only change the method write*

<footnote>

This is a bit of a simplification, because you could make a 'logwrite' subrountine which is not an object, and still be better than this stuff.

<end footnote>

It is a much abused phrase, but what we are talking about here is code reuse. Paying attention to code reuse will help you be a lot more productive.

A Short Discourse On The Difficulty of Learning Object Oriented Programming (especially for procedual programmers)

Although object oriented programming looks deceptively simple, it is quite a paradigm shift from procedural programming. There are a lot of reasons why this is so, but one of the main technical reasons is that it adds a level of indirection in what you are doing compared with procedural programming. Indirection goes side by side with abstraction. Once something is abstracted out, then it can't be directly seen, so you need to trust that the abstraction was correct.

It is easy to concentrate on the task at hand with a procedural program written without subroutines. You take a series of steps, without needing to worry about the consequences of those steps. Programs are assembled the same way that you would bake a cake, by following a recipe.

The use of subroutines adds the first level of indirection in procedural programming. This adds power, but it also adds complexity, since you do not see directly what you are doing. If something goes wrong, you need to trace what went wrong down, often through several layers.

Object oriented programming is, of course, another level of indirection. This adds yet more power (considerably more) but it also adds more complexity. Not only do you not see what you are doing, but you also need to think about how to put the objects together, and how different subroutines work together. Thinking in both the macro and the micro levels is not particularly easy.

But more than that, learning OO is a matter of psychology. It is often hard to learn because people are comfortable with the procedural paradigm. Procedural programming works for them, it is relatively simple, it has its warts, but it generally is pretty powerful (especially Perl procedural programming). Remember the saying, if all you know how to use is a hammer everything looks like a nail! Object oriented programming puts a few extra tools in your programmers tool belt.

The first step

So what is the best road to take to overcome the barriers that prevent learning object oriented programming? The first step is to recognize the limitations of procedural programming. What follows is a short exercise in looking at the gymnastics required by procedural programming to get certain tasks done.

Say that you wanted to make a program that takes input interactively and then puts this input into a file, based on a switch on the command line. One possible bit of code would look something like:

Listing 14.1 - Sync.pm

1 #!/usr/local/bin/perl

2

3 open (FD, "> input_log"); # opens up the input log for

4 # the input to follow.

5 if (grep (/-input/, @ARGV)) # looks for the input switch in the

6 { # arguments on the command line.

7

8 do

9 {

10 my ($answer, $amount) = ('',0.00);

11

12 print "What do you want for christmas?\n";

13 chop($answer = <STDIN>);

14 push(@output, $answer);

15

16 print "How much will it cost?\n";

17 chop($amount = <STDIN>);

18 if ($amount > 100.00)

19 {

20 print "That's way too expensive\n";

21 }

22 } while ($amount > 100.00);

23 }

24

25 print FD "@output\n";

26 close(FD);

This is extremely easy to program, which is great if you want to get a program out the door quickly. This program hovers around abstraction levels two and three in that there is:

1) direct, raw access to filehandles

open(FD, "> input_log");

2) direct access to standard input

chop($line = <STDIN>);

Finally, we are repeating what looks like similar loops of logic inside the code, as in asking how much the gift will cost, what we want, etc. Moreover, the results of this program are not put into a data structure.

The upshot of all this is that this sort of programming has a long term cost:

1) If we want to add onto this program (in any way) we are going to have to type quite a bit. For example, to add on an extra question, with an extra condition then we have to type 5 lines: the print statement, the prompt, the if condition, and the action if the condition is faulty.

2) To add an extra flag, say a '-gift' flag which fills in the answer to 'What do you want for Christmas?' at the command line. There is no way to do this without rearranging the entire program.

3) Say that we want to make a series of programs, all which do basically the same thing (i.e.: a 'gift' series of programs) various values from the command line. How do we insure that the 'look and feel' of the program stays the same?

All of these are important questions since programs seldom stay constant. They fluctuate and respond to the demands that people have on them. People demand features of programs, and if your programs are not designed for malleability, you will ultimately get overwhelmed in the end. The way I look at it, if you are programming like this consistently, it is like custom-designing each brick in making a house; it is labor intensive, and ultimately costly to maintain.

Realizing the long term cost of not abstracting code is the first step.

The Second Step In Learning OO

The second step to learning object oriented programming is to recognize the terror of cut and paste.

On the face of it, one solution to the problem of adding new code is 'cut and paste'; reusing existing code by copying it by some 'high power editor' tricks. Now everybody knows that this is a bad idea (whether from gut feeling or from analysis), yet everybody does it (including myself). But I have managed to limit myself from doing it by just reiterating through my mind why this is so bad.

With cut and paste you can save a little time in the short run, and in the long run, render your programs completely unmanagable. Say you cut and paste 1000 lines of code into another one of your programs. And then, lo and behold, a user of your program asks you for a certain change.

Now you are either going to do one of a number of things:

1) you will remember to change it in both places and get the change correct.

2) you will remember to change it in both places, and get the changes correct, but make it 'right' in two different ways.

3) you will remember to change it in both places and get one correct, and make a mistake and create a bug in the second place.

4) you will remember to change it in both places and get two different bugs, one in each place.

5) you will only remember to change it in one place, and totally forget the other one.

Only two of these changes are acceptable from the point of view of your users, the ones in which you changed both places and got both changes right. And only one should be acceptable to YOU, namely the one where you changed both places and changed them the SAME. Code tends to take a life of its own. Once the two sets of copied code diverge, you will find it very difficult to merge them back again.

In other words, if you cut and paste (in any language), you are multiplying the amount of code you need to maintain unnecessarily. As I'm sure you are aware, this is NOT a good thing! Your day will be split into fixing the same types of bugs over and over.

Once you feel that you have gotten a handle on things, someone will ask for additions or changes, and you will go through the same cycle of needles bug fixes. With Perl this is an extra danger, since the free form of the language tempts and/or almost invites the cutting and pasting mentality, which as I said works well in the small, but not so well in the large.

As a summary, if you notice, that in your own code:

1) you seem to be solving the same problem over and over again

2) you keep on hitting that 'cut and paste' function to manage change.

3) you change code in one place, and then users report the same bug, this time in a different script.

4) your code has hundreds of control blocks spread throughout the code.

Then you are probably not abstracting your code correctly, and you need to read on.

A guide for the Uninitiated and Unaware, on learning Object Oriented Programming

Step #1: learn the syntax for and use modular programming.

One of the simplest ways to get used to object oriented programming is by walking before you start to run. Remember, modular programming is the process of taking related subroutines, and putting them into modules for reuse.

Perl provides a very convenient syntax for modular programming, which if you are trying to learn OO, provides a good bridge to getting to OO. By using modular programming, you get into the habit of categorizing your thoughts, and splitting your design into reusable chunks. We have devoted an entire chapter to the technique, and use of modular programming.

Step #2: learn the syntax for making and using objects.

Actually making Perl objects takes some time getting used to as the syntax is a bit difficult to grasp. Therefore, you should learn the syntax relatively well.

Perl also has some major differences from the way it does object oriented programming than C++. Hence, you should realize exactly what the policy is for Perl on certain OO issues, issues such as memory management, privacy, and the way Perl stores its objects.

Step #3: Actually see examples of objects in action!

One of the biggest barriers that people have to object oriented programming is that they can't get a good, real-life example of objects to work. On the CD (and available by net) we have put all the source code that we use in this book onto disk, plus more. Please avail yourself of this opportunity, and actually take the time to copy this source code (along with your installation of Perl) onto your home computer!

The chapter 'Examples of objects in action' goes through the mindset, the steps, and some common problems that Perl OO programmers face, such as consciously thinking about reuse, steps in construction of objects, maintainability, looking towards new designs, and towards the future, i.e.: the creation of objects from A to Z.

If you understand the process well enough to create a Perl object, then you will naturally gravitate towards Perl's OO and procedural programming will not seem very clean.

Step #4: Actually use the examples that we give for objects in your own code!

I designed these examples specifically so that people could use them. They deal with very generic, low-level problems that everybody faces (log output, document code, and options processing) so you should be able to transfer them into your codebase fairly easily. Furthermore, they are not very so you should be able to follow the flow pretty well.

Step #5: Create a couple of your own objects.

Now that you see the examples in action and have traced how they work, go ahead and design, and implement a couple of your own objects. They could either be enhancements on the ones we have done in detail, or new objects. We give some ideas on some good, starting objects at the end of 'Examples of objects in action'.

Step #6: Learn the more advanced Perl OO concepts

Advanced Perl object oriented concepts such as typing, inheritance, polymorphism, containers, and iterators are very useful to know.. Notice that I put this step after you have actually used OO and grouped a lot of stuff into it. This is because that you really DON'T need to know this for a long while. You can be productive in object oriented Perl without knowing these. We have dedicated a lot of material to these concepts, because they are useful. But they are not essential to the beginning Perl programmer. Here are some capsule definitions, and where they will be covered in the text, below.

Inheritance

Inheritance is the ability of a class to 'borrow' methods from another class if they have not defined them themselves.

See the section 'Inheritance and Perl' for the use of inheritance, how to learn it, and how to apply it to your code. You will want to understand this fully before you apply it to your code.

Polymorphism

Polymorphism is a technique for making different functions or classes be 'transparent' from the point of view of people who would use that function. For example, if you define a function add which is used like add(1,2), you might want to have this function take any number of arguments instead of defining a function like add3(1,2,3). The section 'Polymorphism and Perl' goes into this in more detail.

Make no mistake, we will mention these different techniques as they arise in the chapters that lie ahead. But we will not dwell on them. Far too many programmers concentrate on learning everything at once, instead of trying to build their knowledge on top of simple foundations.

Step #7: Look at Some Actual, Object Oriented Perl projects.

Finally, the last few chapters of the book will cover some useful Perl projects. Look over these examples, and feel free to incorporate some of the code into your own projects.

Objects are the building blocks in Perl. Projects are the ways that those blocks are put together. By seeing the culmination of thinking and programming in an OO way you will be more likely to think this way yourself.

Summary of A guide for the Uninitiated and Unaware, on learning Object Oriented Programming

Object Oriented programming is a method for building up large structures out of simpler objects, building on foundations. Learning OO is exactly the same way: if you worry about understanding objects and understanding object design concepts at the same time, then chances are you are going to get frustrated and possibly quit. Hence, learn at a steady pace. Don't rush through the next few chapters. Take your time to learn, understand, and apply the principles that are given.

The next few chapters should give you a solid footing in learning Perl's OO, even if you do not currently know object oriented programming.

If they don't, we are not doing our job. Perl is one of the easiest programming languages to teach object oriented programming, and in part, the next few chapters are designed for that very purpose. But be forewarned that for many people, OO programming does not come easy. Hence, you are best off reading the next few chapters in tandem with the programs that we provide on disk. Everything will go smoother if you can document, trace, look, tinker, and feel your way around the objects that we provide.

So lets get going. Object oriented programming is an extremely cool thing to know, Perl especially! Cool, and fun.

OO can be frustrating at first, but once you get into it, you will see all sorts of cool ways to improve your designs. Perl helps a lot, since it is so easy to do OO in Perl. After studying the next few chapters, you should have a pretty good idea on how to actually program this way.

Orders Orders Backward Forward
Comments Comments

COMPUTING MCGRAW-HILL | Beta Books | Contact Us | Order Information | Online Catalog


HTML conversions by Mega Space.

This page updated on October 14, 1997 by Webmaster.

Computing McGraw-Hill is an imprint of the McGraw-Hill Professional Book Group.

Copyright ©1997 The McGraw-Hill Companies, Inc. All Rights Reserved.
Any use is subject to the rules stated in the Terms of Use.