![]()
Because I only write large programs in Perl when working with the CGI capabilities of the language, I'll use examples from those situations. I simply haven't seen any large non-CGI programs written in Perl.
But, is your program really nice without the OOP?
Let me give you some examples. These examples just illustrate a problem. later, I'll explain how to solve them with OOP.
Example1: A user account system
Most large CGI programs have an user registration and login system,
with some very nice and interesting functions for members.
Large CGI programs mostly provide a control center for Administrators,
and that requires cookie management, a login dialog and password storage and encryption.
However, what will you do when your site is getting larger and larger, and finally you end of with 4 large CGI programs? Do users have to register themselves 4 times, for every program once? Even worse - they have to login 4 times when they want to use many things at your web site.
But now, let's look at the problem from the site of the programmer. Will you really program such a registration system for every program, or copy-parse some parts, and adjust everything a bit? Eventually, you'll find a huge bug. Just overwriting the files won't do much good. Every file has some minor differences, as we just mentioned. You'll have to make all changes 4 times, and eventually, you get sick of it and stop your activities.
Wouldn't it be a lot easier if you created one system that could be used from different programs?
Your script can load a module that exports some subroutines, and implement some variables
and settings because the module is very flexible in use. In other words,
you're stuck with even more subroutines and variables. In the end, you'll loose
the overview. Other programmers will never be able to understand where some things
happen in your program. There are simply too many lousy subroutines involved, and
nobody wants to document everything, isn't it? I refuse to do that part as well sometimes.
Example2: My current situation
I've just finished version 1.05 of the
X-Forum Discussion script.
It's a nice robust program, it's code is pretty structured. Most of the rules for large
programs are applied. Well, that's wrong with it, you might say...
Or do you really think that program isn't that large? Then,
download it,
and take a look at the code. I hope you can keep overview of all the code.
I know where everything is located and what it does, because I've created it.
Still, nothing really seams to be wrong, but have you seen the initializations? About 50 global variables are declared, used through the entire program. Some modules are loaded, which functionality will be used throughout a lot of components of the program. The settings, language files will be loaded. Finally some basic initializations are made, concerning loading of more files, and test for banned members, missing files, etc...
For my download manager is build the same way; pretty robust, but not flexible.
But what if I want to:
For example, we have a television set (the object).
main program
variable (TV) tv1 = new TV(500,400) variable (TV) tv2 = new TV(400,300) tv1->attachConnection(cable1) tv2->attachConnection(cable2) tv1->turnOn() tv2->turnOn() tv1->changeChannel(2) wait 5 minutes tv1->turnOff() tv2->changeChannel(3) wait 5 minutes tv2->turnOff()
This creates two TV's from scratch. Both TV's work independent from each other. Through the methods we can let the TV do something. We don't know how it works, but we can handle it. You also don't get confused with tons of subroutines. All actions are embedded within the object, and only accessible when you know of the object itself.
Definition of a TV
class TV { # The hidden object variables define the properties of an object variable (number) channel variable (Connection) connection variable (Screen) screen variable (number) hertz # A constructor that initializes the object on creation subroutine constructor(number width, number height) { self->channel = 1 self->screen = new Screen(width, height); } # Turn on public method turnOn() { call showImage every 1/30 of a second } # Display an image at the screen private method showImage() { image = screen->retreiveImage(hertz) screen->display(image) } public method turnOff() { stop calling timer_action } # Switch channel public method changeChannel(number newChannel) { self->channel = newChannel self->hertz = connection->getChannelFrequency(self->channel) } # Handling a connection, The connection variable can also # be changed from outside, through this method public method attachConnection(Connection newCable) { self->connection = newCable } public method disconnect() { self->connection = undefined } # Some methods to return the internal data, read-only # because we don't provide methods to change the data public method getWidth() { return self->screen->width } public method getHeight() { return self->screen->height } public method getChannel() { return self->channel } }
This TV class is very simple, but shows how a class can look like.
Take a look at the comments inserted in the code, and you'll properly
understand what is done here. Very much is delegated to other objects,
to simplify the example. However, we can create and work with a TV
everywhere now, in every program, in any situation. Just like we wanted.
The hidden variables inside the TV aren't shared among other TV's,
which avoids the need to make collection structures.
Written by Diederik van der Boor at 10 March 2001