"Maybe I am modularly handicapped, but most apps I write to do utility type work are one time shots and are short, sweet, and to the point." This is not to be viewed as a bad solution just because it's not OO, but a targeted one to serve an immediate purpose. Sometimes, --a lot of times, this is what a sysadmin wants. Other times, it isn't. When it is what is wanted, spending all the time to develop very intuitive and graceful OO solutions as an end-all to end-all solution just doesn't't make sense. "I have read many places that OO is MUCH slower. Am I to assume from the test that this is incorrect?" Well no, don't assume that such a statement is right or wrong at all. Just remember that OO code sucks when the object oriented code is written poorly. When written correctly and with care, the graceful product isn't at all an unfriendly, ugly maze of unnecessarily complicated, confusing, slow-moving code that works even less often than it was ever useful. The honest truth is that I have been wanting for some time to show just how mistaken all of the assumptions are about the myth that OO programming styles are much slower than a procedural script which does the same thing. It's quite an erroneous prejudice for anyone to assume that this is the case. Try looking at some benchmarked tests I ran recently which demonstrate how efficient OO can be. In these tests, some of my OO code libraries were pitted against a procedural implementation of the same in separate scripts. Looking at the results, you can clearly see that the Object Oriented approach verses the procedural approach is not as slow and stupid as many people seem to think. In some cases, it can even be faster. 7 files were merged together into one, 10,000 times by the Object Oriented code, and by the Procedural code. This test was run twice. CPU times and system resources used in milliseconds were collected. The results and the code used to get them are viewable below: We'll put the pros up against the cons and we'll decide for ourselves which solution works better for us in the given circumstances.... +====================+===========================+===========================+ | Factor in | proposed solution | proposed solution | | Consideration | (procedural) | (object-oriented) | +====================+===========================+===========================+ | Speed of | 25 wallclock secs | 21 wallclock secs | | Execution | 20.56 usr + 2.30 sys | 5.15 usr + 2.68 sys | | | = 22.86 CPU | = 7.83 CPU | | 10,000 iterations | | | | of complete code | | | | compilation and | 25 wallclock secs | 22 wallclock secs | | execution within | 20.98 usr + 2.36 sys | 5.01 usr + 2.54 sys | | one Perl system | = 23.34 CPU | = 7.55 CPU | | process. | | | | | | | +--------------------+---------------------------+---------------------------+ | Maintainability | You have to re-write the | Written once. Never has | | | code each time you need | to be re-visited to do | | | to merge new files. This | the task it was made for. | | | means there's a higher | This means that it is | | | chance for errors to | debugged one time only. | | | creep in, and | | | | necessitates frequent | | | | debugging. | | | | | | +--------------------+---------------------------+---------------------------+ | Scalability | Can not be re-used by | Can be re-used in other | | | other applications, can | applications and can also | | | not be automated for | be automated in large | | | quick batch jobs. | batch jobs. | | | | | +--------------------+---------------------------+---------------------------+ | Ease of Use | Not a utility which can | Can be re-used in other | | | be run from the command | applications and can also | | | line to take arguments | be automated in large | | | where you specify any | batch jobs. | | | number of files to merge | | | | and in what order. | Takes command line args. | | | | | | | Has no built-in help, | Built in help. Runs just | | | or usage information of | like any binary on Linux | | | any kind. | where an -h switch passed | | | | to the app returns a | | | Not many diagnostic error | usage guide and examples | | | messages. Not any error | of correct usage syntax. | | | messages which help find | | | | and eliminate bugs and | Accepts an unlimited num- | | | fix user mistakes such as | ber of files to merge | | | improper usage syntax | | | | with suggestions of how | lets you specify where to | | | to remedy any errors. | write the new file, and | | | | what to name it. | | | Works from one directory | | | | only, or must have fully | Provides an abundance of | | | qualified paths to root | case-specific help in all | | | for each file it opens | its error messages and | | | | provides correct suggest- | | | | tions for the user to | | | | correct any mistakes he | | | | she had made. | | | | | | | | Includes a stack trace. | | | | | | | | Works from any directory | | | | and takes relative paths. | | | | | +--------------------+---------------------------+---------------------------+ | Compatibility | Will work on systems that | Works for Win32, Linux | | | implement a specific type | BSD, Solaris, freeBSD, | | | of file system and could | and probably more. | | | run into problems with | | | | platforms of a different | mod_perl compatible | | | directory structure. | | | | | | | | not designed for mod_perl | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +--------------------+---------------------------+---------------------------+ | Stability | If ever forked or | Implements FLOCK on all | | | run in iterations from | systems that implement | | | inside a virtual environ- | the mechanism. Even | | | ment -(this is how it was | Win32 implements a form | | | tested for speed of exe- | of FLOCK. You can even | | | cution)- it will certian- | get a complete simulation | | | ly start encountering | of FLOCK-ed behavior out | | | what is called a race | of your script when run | | | condition during its | on Win32 by using Cygwin. | | | IO operations on all the | | | | files involved in the | Integrity of all files | | | script. | merged by the app can be | | | | guaranteed. | | | The integrity of all | | | | files merged by the app | | | | cannot be guaranteed | | | | | | +--------------------+---------------------------+---------------------------+ | Reusability | Use one time and throw | Use as many times as you | | | away. If you ever want | want, and never re-write | | | to use it again, you have | a single line of code-- | | | to re-write it or pay | or pay somebody else to. | | | someone else to do it. | | | | | | | | The code may be small, | | | | but it sure seems silly | | | | to spend all the time it | | | | would take to go back and | | | | re-write it 10,000 times | | | | before you could accomp- | | | | lish the same task as | | | | the Object Oriented | | | | solution can in one run | | | | with a list of 10,000 | | | | files. | | | | | | +--------------------+---------------------------+---------------------------+ | Security | If hacked, the syntax | If exploitation is ever | | | used to open and write to | attempted, the manner | | | files would allow a | in which IO is handled | | | hacker the pleasure of | thwarts all efforts to | | | direct access to your | gain access to the system | | | system. | and never escapes to a | | | | shell under any circum- | | | Files are opened without | stance whatsoever. In | | | any kind of check for | case you were wondering, | | | what kind of file is | the procedural solution | | | about to be opened, or if | used in this example | | | it even exists. | could easily be used to | | | | let a given user escape | | | If it doesn't exist, it | commands to the shell, | | | could be that someone is | although it is not a | | | trying to get tricky on | matter of procedural vs. | | | you and open up a pipe | OO programming which | | | or a tty. | determines this vulnera- | | | | bility. It is rather a | | | We probably don't need | matter of using a safer | | | to be merging binaries | type of syntax when open- | | | either. | ing and writing to files. | | | | | +--------------------+---------------------------+---------------------------+ You decide which solution you want. This is something which I find quite gratifying when I've put all the time and effort into creating a really useful, widely compatible, re-usable library of code that took a lot of work but will save a lot down the road. If it weren't the case, I wouldn't bother and neither would anyone else, unless they were stupid :o) Object Oriented language features *can* indeed quickly generate a very cumbersome and unwieldy beast if code starts getting thrown together without a bit of prerequisite understanding. This knowledge is not hard to get a hold of, but you'd probably be surprised at how many programmers never take the time to actually learn the virtues of true Object Oriented practices as opposed to only learning the syntax for a programming language's OO programming features. Instead of reaping any benefit from the tools which better programming languages offer in order to implement object orientation of code, these hyped-out developers just shoot themselves in the foot by using those tools to make modules or libraries of code which are completely procedural in design! They just don't get it, because they haven't taken the time to learn what OO is all about: reuse of code -- where every needed routine or object method is built on one which is more generic and has already been created. Each function you create builds on pre-existent code of your own make, or of someone else's. So think with me a moment... If we just make a whole lot of modules and libraries to import into our scripts which essentially do the same thing, only a little different than its predecessor, we gain nothing. That's just plain stupid. It is defeating the entire point of Object Orientation. Why? Because code isn't re-used. Code gets created all over again every time you make a code library like that. The same thing goes on in the actual program which runs such worthless code libraries. Instead of making execution time faster by using code already compiled, built over code which was also previously created, compiled, and referenced, the program has to make all that code over again each and every time its author cut-and-pasted the same stuff into his routines-- or even in other modules in use by the program in question. That is what makes a so-called Object Oriented program SO slow. Execution times are actually faster in such cases when you just move all that code back into your script. This is why I used the word 'hype', because that is the only reason why anyone would make such an awful creation. They heard that OO is 'da bomb' way to do stuff now, and all the rage, so of course hey've got to get that on their resume. A few hours later, an 'OO for Dummies' book is laid on the desk to never be picked up again, and a monster is born. "I am king!" exclaims the neophyte, because he just learned how to make a module. Well that's it now, he's an OO programmer for life, and will swear by it as long as it is cool. All his code will be 'modular', and his rograms will run as fast as an express lane at Wal-Mart, while sucking even more power and hogging more system resources than the platform it runs on (which is quite a feat on Win32!) If you've ever heard the sorry excuse that, 'OO is slower, but it's ok because I can buy a chip that's twice as fast next year anyway...', than you were probably as turned off to OO as I was before I realized that this was a yellow snow cone of naturally non-citrus flavoring. (For those who may read this and have a harder time understanding sarcasm as dry as mine can be, it means that when you believe such a lie, you might as well have eaten a cup full of frozen pi$$) So what is the real difference between that suck-code, and purely OO code? As stated earlier, it is the re-use of code in every aspect of your libraries/modules/packages/whatever. Well, how is such a thing accomplished when every program you make has different requirements? The answer is perfect OO Zen; the way to enlightenment is called "polymorphism", my friend. This is a really cool word that doesn't really have much to do with viruses like the dreaded 'Polymorphic buffer overflow worm' besides that when this programming technique is used, the bad viruses get worse, and the good programs get better, if you know what I mean. The reason? Polymorphism is the first step to code that knows on its own what to do in different circumstances. It could even be considered 'artificially intelligent' because it learns, and can be taught to learn if it doesn't already know how. WHOA, COOL! Yeah, it is totally cool. It is the thing that makes Object Orientation actually work, and is a technique which must truly be learned in order to get your code from 'moving even slower than it sucks' to code that 'screams through the CPU like diet soda through a 10 year old at bed-time'. There are different ways to implement Polymorphism, and each has another cool name, such as 'Interface Polymorphism', 'Inheritance Polymorphism', and 'Self-diagnostic or Situational Polymorphism'. Essentially, if your code knows how to work under different circumstances, with different arguments, with different types of arguments, in different environments, on different platforms, with different file systems, in threaded tasking, in multi-process tasking, broken or faulty environments, with tainted input, or all of the above + 10, from January to December-- You never have to re-create it, and neither does your compiler and/or your CPU when it is executed. Perhaps you are beginning to realize just why OO demands a little more effort, but perhaps you can also begin to see how OO can truly deliver on the investment of your time spent learning it as much as you keep hearing how cool it is. "On the speed of execution test: Is this run as a standard script, or is it run loaded into memory (mod_perl or the like)?" The benchmarks were run on RedHat 6.2 and Win98. Neither test ran under mod_perl or any other caching environment. The question of whether or not the scripts were 'loaded into memory' is kind of tricky, you see. This is because the larger OO program with its more extensive libraries benefits by allowing the compiler to create and compile the code one time only and use references to point to what is already in memory so that it all gets re-used by your CPU, whether you are using mod_perl or not. The procedural code was a lot smaller! But unlike the big OO code, it had to be re-created each time it was called upon to run the file merging I/O commands. It is essentially a difference to your CPU that this is to you and me: In OO it works like this... #-------------------------------------------- # OK, create the code which will get re-used. #-------------------------------------------- do this, and that, and this, and that, and this, and that ONE TIME save it for later. #-------------------------------------------- # now run it 7 times for all of my files... #-------------------------------------------- Now go get that code and run it again, 1 and again, 2 and again, 3 and again, 4 and again, 5 and again, 6 and again. 7 While in procedural programming it works like this... #-------------------------------------------- # OK, for every file I've got in seven, # create the code which I need to use # and then run it, then copy the previously # created code and start over with that. # Keep doing that... #-------------------------------------------- 1 2 3 4 5 6 do this, do this, do this, do this, do this, do this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this, and this. and this. and this. and this. and this. and this. 7 do this, and this, and this, and this, and this, and this, and this. -Tommy Butler, consultant Atrixnet, for Internet Business Software http://atrixnet.com 2200 North Lamar Suite 307 Dallas, TX 75202 -- Use my services as a contractor http://www.atrixnet.com/contracting/ Visit the open source Perl archives at Atrixnet http://www.atrixnet.com/pub/