What's so good about OOP?

it isn’t really something you can explain to someone because procedural style programming ‘CAN’ do it. Oop doesn’t do it better but differently

I find that to be the case, indeed. Object composition as I described in my previous post is certainly possible with procedular programming, but it requires a lot of thought, and is almost counterintuitive. But it CAN be done. I also agree that OOP is a way of thinking. Myself, I find it extremely hard to write software in a procedural style, because I think in a somewhat object-oriented manner (and not just when it concerns programming).

Okay, let’s talk about databases ;).

The Database interface I gave in my previous post is actually more or less the interface (give or take a few methods) I use every day. As you can see, there is no way to process some kind of query result. However when I do this:


$database = new MyDatabase('localhost', 'test'); // MySQL implementation
$database->connect('username', 'password');
$result = $database->query('SELECT * FROM table');

That $result-thingie is not a simple variable, but it’s an instance of class QueryResult, which looks like this:


class QueryResult
{
    // Create a new object; this is done by class Database
    function QueryResult(&$database, $resultId) { }
	// Clear the query result
	function clear() { }
	// Was the query executed successfully?
	function isSuccess() { }
	// Get the error message in case of an error
	function getErrorMessage() { }
	// Get the total number of rows in the result (for a SELECT)
	function getRowCount() { }
	// Get a specific row in the result
	function getRow($index) { }
}

Given an object of class QueryResult, I can traverse all rows in a SELECT-query, and find out if the query executed okay. If I wanted to, I could add methods specific for INSERT-, DELETE- and UPDATE-queries (“How many rows were affected?”, “What is the last used insertion ID?”), but I haven’t had the need for that yet.

Now, classes Database and QueryResult are both interfaces, so they don’t do anything by themselves. If I want to use some specific database, I have to implement both classes, as in MyDatabase and MyQueryResult for MySQL, and PgDatabase and PgQueryResult for PostgreSQL.

The philosophy behind both interfaces is that every class should do what it does best. Class Database knows about connecting to databases and executing queries on it, so why bloat it with code to process the results from those queries? That’s a whole different ballgame, so that’s why I wrote the QueryResult interface. If you compare this to PEAR, you’ll see the following:

  • Class DB_common (and thus classes DB_mysql, DB_pgsql, and so on) have many methods. It can be used to connect to databases, execute queries, process the results in these queries, and handle transactions (and that’s not all!).
  • There is a class DB_result, but it’s not meant to be subclassed. When using this class to process query results, it internally calls the query handling methods in the database class.

Now what if I want to do something like this (and I do regularly):


// Select all books
$books = $database->execute('select * from book order by title');
// Select all authors
$authors = $database->execute('select * from author order by lastname');
// Handle both the $books and $authors QueryResults

Executing queries one after another and processing their results at a later time is easy and straightforward. More importantly, it requires no extra coding in the classes to make sure it works. Also, once I’ve got the results from some query in a variable ($authors or $books), I don’t need the Database object anymore! This is unlike PEAR, where class DB_* must be used to access the various rows in the result. Additional administration is required in the DB_*-classes to make sure rows from the right query are selected, and in my code I have to pass my database object around a lot, just to be able to process query results.

Given the query result $books above, I can print booktitles like this:


for ($i = 0; $i < $books->getRowCount(); $i++)
{
    $row = $books->getRow($i);
    echo $row['title'] . "<br>\
";
}

This loop is simple, and there is no reference to the database object whatsoever, which makes sense: what has a database connection to do with a result-set from a query?

In my previous post, I told about class Loop, which implements loops on iterators. Iterators are higher-level, generic objects. All iterators have the same interface, so I can use the same loop for arrays, strings, trees and query results. The iterator for QueryResult-objects looks like this:


class QueryIterator
{
    var $queryResult;
	var $current;
	var $size;
	
	function QueryIterator(&$queryResult)
	{
	    $this->queryResult = &$queryResult;
		$this->size = $queryResult->getRowCount();
		$this->reset();
	}
	
	function reset()
	{
	    $this->current = 0;
    }
	
	function next()
	{
	    $this->current++;
	}

	function isValid()
	{
	    return $this->current < $this->size;
	}
	
	function &getCurrent()
	{
	    return $this->queryResult->getRow($this->current);
	}
}

Again, you see that class QueryIterator doesn’t need the Database class to do its work. Not only does this make more sense, it also makes software more layered: I don’t need to pass my Database object to many objects or functions. Only the highest level code needs acccess to the database. The code at lower levels doesn’t, so they don’t need the Database object, so I don’t need to pass it.

To print book-titles, I can now write this:


for ($it = new QueryIterator($books); $it->isValid(); $it->next())
{
    $row = &$it->getCurrent();
    echo $row['title'] . "<br>\
";
}

In this case, this adds little or no benefit to traversing the query results directly from the QueryResult object. This changes if you take into account that I can now layer my code even more: by creating an iterator and passing this on to code at a lower level, that level needs to know nothing about the kind of data is traversing. More importantly, as all iterators have the same interface, I can reuse that code over and over again. A perfect example is class Loop:


class Loop
{
    // static member!
    function run(&$iterator, &$manipulator)
    {
        $index = 0;
        $iterator->reset();
        if ($iterator->isValid())
        {
            $manipulator->prepare();
        }
        for ( ; $iterator->isValid(); $iterator->next())
        {
            $current = &$iterator->getCurrent();
            if ($index)
            {
                $manipulator->between($index);
            }
            $manipulator->current($current, $index++);
        }
        if ($index)
        {
            $manipulator->finish($index);
        }
        return $index;
    }
}

The one and only method ‘run’ is extremely simple. It gets passed an iterator and implements the iteration loop, so that I don’t have to write it ever again. At certain steps in the iteration, it calls methods on a manipulator, that must be passed as the second argument. The manipulator must implement these four methods:

  1. prepare(): is called right before the first item in the iteration is processed
  2. between(): is passed in between every two items, thus not before the first or after the last
  3. current(): is called for every item
  4. finish(): is called right after the last item in the iteration is processed

If I were to print book-titles, I now have to write a manipulator. To make life easy, I can write this manipulator as a subclass of class LoopManipulator, that implements all four required methods as empty methods. For example:


class BookTitlePrinter extends LoopManipulator
{
	function current(&$row, $index)
	{
	    echo $row['title'], "<br>\
";
	}
}

Now why is this better than the simple loop I had before? I’ll get into that later, after I’ve shown the complete code for printing booktitles:


// Layer 1: create a database connection
$database = new MyDatabase('localhost', 'test');
$database->connect('username', 'password');
// Layer 2: select the books from the database
$result = $database->query('select * from book order by title');
// Layer 3: set up the iterator and the manipulator
$it     = new QueryIterator($result);
$manip  = new BookTitlePrinter;
// Layer 4: print the book titles
Loop::run($it, $manip);

All layers are shown in one block of code, but in large systems they typically aren’t. Note that all code in layer ‘n’ only requires access to code in layer ‘n - 1’.

If you examine the code above more closely, you’ll see that the variables $result, $it and $manip are all temporary: once the loop is completed, they aren’t needed any more. The question then is: why create them at all? Thanks to the design of the various classes I can write the code above like this:


$database = new MyDatabase('localhost', 'test');
$database->connect('username', 'password');
Loop::run(
	new QueryIterator($database->query('select * from book order by title')),
	new BookTitlePrinter
);

No more temporary variables, and simpler code as a result. On the other hand, this only makes sense if all 4 layers are placed at the same part of the code. Anyway, it does show how the same classes can be used to write layered code as well as compact code.

To answer the question “Why is using manipulators a good idea?”:

  • There is now a clear separation between the algorithm (the loop) and the behavior of the algorithm (printing booktitles). In other words: object composition.
  • The algorithm (the loop) is implemented just once in a generic way, instead of many times, specialized for specific problems.
  • As the manipulator is a class, I can reuse it by writing subclassing or wrapping.
  • An intelligently written manipulator can be reused for other loops.
  • Layering is supported ‘out of the box’

To end this post, I’d like to remind you that the example I’ve used here is pretty simple, and therefore may lead you to think that the various classes are bit ‘over the top’. In larger systems they certainly aren’t, I can vouch for that! Also, by using a set of compact and efficient classes instead of large, bloated ones (PEAR), I find no impact in execution speed whatsoever. But that’s just my experience of course :wink:

Vincent

Vincent, I’m learning to love the wooshing sound that your posts make as they go waaaaaaay over my head! LOL! :wink:

Seriously, though - I’m a PP man myself… never quite grasped the OO approach in my time at Uni, and it cost me dearly. (my degree, as it happens!)

I reckon if any of my lecturers had half the talent for breaking stuff down as you do, that wooshing sound would be the sound of my brain grasping the concept.

Nice to see Larry foxed for once - you guys keep at it; I’ll follow along.

scrolls back up the page and gets reading

voost, at last a description of OOP in PHP that makes me strongly consider at least dabbling with it. i can see the logic behind it, and yes, if you look at it that way, it does make a lot of sense indeed. i was under the (mistaken, admittedly) impression that OOP in PHP == PEAR, and what kept me from playing with it was indeed the bloated “one-size-fits-all-or-else” approach of all those classes. if i now start going OO and flood this forum with silly questions, remember: it’s your fault for starting me down that path :wink:

Thanx again voo. I think I have more posts by your printed out than anyone. You have also (indirectly) convinced me to go and grab some cbt’s on advanced oop. I thought I had a good understanding of it but realize I have a ‘good’ understanding, I want to understand more :smiley:

Again, muchly appreciated on the fantastic artical.

I would also refer people to this article/tutorial on the ZEND WebSite.

Nice artical and thank you. :)…The only thing I was having a problem grasping was the reason to use this type of thing

Loop::run(new QueryIterator($result),new ResultDisplay);

I am starting to get most of the features discussed in this ‘article’. I have been able to work through the code provided by Voo and work out most of my dilemas with advanced oop :)…

For a basic design theory. If we were creating a artical manager (one small piece of a CMS) you would subdivide classes up into

db //class to handle connections with db
queryResult ///class to handle the querying and information based on those queries
queryIterator //class to handle the iteration of the rows fetched by the queryResult
Loop::run //class to display (iterate) the query using the template class
ResultDisplay //template class setting various section of the iteration ‘DISPLAY’ settings

Obviously this will handle any query given it and display that query according to the ResultDisplay I define.

Loop::run(
new QueryIterator($db->query(“select * from blah blah”)),
new resultDisplay
)

Do I have this so far :wink: This works great for things like displaying lists of sections AND/OR lists of articles and the article itself.

For a templating system to seperate your content from the template (keeping it in a DB) I have something like this in mind

db //use above class to connect to correct table containing the templates
QueryResult //reuse this class to fetch result #ID for templates and content

fetchTemplate //This class fetches the db stored templates from the result ID
createTemplate //uses information ‘fetched’ to create the template. This is similar to the manipulator in Voos class’s

fetchContent //class to retrieve ‘content’ or articles from the database

Loop::Template //superclass to use template information to ‘place’ the templates in the right spot

Loop::Template(
new createTemplate(new fetchTemplate),
new fetchContent($result2)
)

So what I have tried to do here is seperate each interface in to multiple areas

1 - db control - open close, and query results
2 - template display - using db control fetches and displays template
3 - content display - using db control and fetches content based on page info
4 - Loop::template - uses information from template and content to fully create a page.

Just wanted to run this by you guys and see if this make logical sense or if I am just blowing wind. This is my first attempt at layering my oop in this manner.

Thanx for any critism :slight_smile:

Do I have this so far This works great for things like displaying lists of sections AND/OR lists of articles and the article itself.

Yup, you’ve got it completely!

<shameless self-plug>
If you really want to try out this kind of programming, but don’t want to do all the necessary work to create your basic classes (databases, query results, iterators, and so on), you might want to look here: http://www.sunlight.tmfweb.nl/eclipse/ :wink:
</shameless self-plug>

Now, about those templates. I can see how you made your design. You have a template, and you have contents for this template. So, logically, you start with classes Template and Content. But what’s next? You can either make the template responsible for showing itself in combination with the content (‘$template->show($content)’), or you use an ‘outside’ mechanism, like a controller: ‘$controller->show($template, $content)’. It seems you went for this design. I don’t know which one is better; it depends on the complexity of both the template and the content classes.

When I write code, I always look at how it reads. This may sound silly, but when I examine any particular piece of code, I always want to be able to see immediately what job it has, and not necessarily how it does that. Code like ‘Loop::run($iterator, $manipulator)’ is (for me) very simple to understand. I can see clearly what it is meant to do. If I want to know exactly how it does its job, I’ll have to dig a little deeper, which makes sense to me. This is not something I try to achieve in the highest level of my programs; I aim for that in all levels. Naturally, the higher levels are more abstract than the lower ones, but that doesn’t mean they should be less readable.

Vincent

Well I did borrow the code you posted here and inferred the remainder. Or at least the pieces needed by me :wink: Playing with it and adjusting it I have been able to create other iterators. Interesting set of classes and objects you have. Thank you for the time and effort you put into your posts regarding this issue. I know you have helped me tenfold grasp all of the aspects explained above. :slight_smile:

wow Voostind

really… wow. Maybe I should have gone to college after all.

Currently, I have used basic OOP principles (much like PEAR uses) for my one OO project (Datalib) which just happens to be YADAC (Yet another database abstraction class). I did sperate the connections and results/recordsets into seperate objects, but I definately didn’t go so far as using Object Composition :slight_smile:

Anyhow, I just wanted to say Thank You for taking the time to write those lengthy posts! Definately something to keep in mind whilst devloping future software!

Wow. That is some great explaining.

voostind, you should point the Sitepoint people to this thread, you 2 posts would make a great article for Sitepoint. If nothing else, I’m sure it will get a nice discussion going.:tup:

On DrL’s point about OO performance back there, have a shot in the dark theory, based on my experiences with error reporting from classes.

Basically, could it be the case that instantiate a class comes with a flat overhead cost in time, something along the lines of;


Flat overhead = Time to instantiate class + time to define properties + time to run Constructor method

Then to use one of the methods within the class, you add to that an overhead for “declaring” and using that single method.

Where as for functions you’ve got


Flat Overhead = time to declare each function

Then you’ve got another overhead every time you use one of the functions.

So basically classes pay off when you’re dealing with alot of functions, i.e.

You’ve got an include file with 10,000 functions in it (extreme I know but for the sake of argument) vs. a class with 10,000 methods.

For the functions approach, each one must be declared, which makes a massive overhead.

For the class, the methods only add an overhead when they are used.

Anyway - a ballpark theory.

Ok… regarding performance.

In the real world of programming a script to run on a server… not just theory. How much would coding using OOP hurt efficiency.

I’m quite the OOP guy, but that’s mostly with C++ and other languages like that where OOP is a significant part of it. I don’t know how good it really is with PHP.

If I’m making a script that I am hoping to be able to sale later on, when it is complete with all features, debuged, etc… would having used OOP hurt it’s over all performance on big sites?

Can anybody give speed-up factors of using Procedural as oposed to OOP?

Thanks,
-cARL

Edit:

I swear I’m not reposting a question that was posted before in the tread, what I really want to know is if this slow down is acceptible for a “commercial” product?

I don’t think it’s possible to give raw numbers on speed differences between PP and OOP. There are too many factors that must be taken into account. Sure, you can run a test that calls some code as a function and a class-method 1000 times each, but that makes little sense.

After years of studying on and experimenting with object-oriented programming, I can say the following in favour of it, compared to procedural programming:

  • I need much less (lines of) code
  • The software is easier to understand
  • The software is easier to maintain

In that light, what do I care if generating an HTML page takes 0.06 seconds instead of 0.04 seconds? That problem can easily be solved by buying hardware. And because of the time (and thus the money) I’m saving, there’s plenty of room for that.

I’m not saying that buying hardware is always a valid solution to overcome slow code! When you implement a sorting algorithm in O(n^2) while it can be done in O(n log n), you can throw as much hardware at it as possible to make it faster, but it will remain crap.

On the other hand, if you are using good algorithms and good OOP techniques (design patterns and such) and find little room for improvement while the software still runs (too) slow, than buying hardware is a perfectly good solution. It’s much cheaper.

Vincent

ehh, some quotes from Top 21 PHP Programming Mistakes; Overusing OO:

The OO paradigm is a wonderful concept. It has numerous benefits, the most notable being the ability to reuse code easily. However, as we’ve all come to understand: ‘PHP is not an OO language’.

While PHP does offer adequate object oriented support, it is neither efficient nor wise to use its object oriented features when you can make use of other methods to achieve the same result. The reason for this is that PHP’s OO support is not full blown.

Nor is the code behind PHP’s OO support very efficient or fine tuned. This means that when you use the OO paradigm with PHP, you may in fact be slowing down the execution time of your programs considerably.

  • Note: Generally speaking, an application that uses OO support will be slower just as using eval() will be slower than normal code. To amply show places where OO support gets somewhat ugly, I’d have to use advanced PHP features and concepts, some of which have not even been documented yet.

If you are coming to PHP from a language such as Java or C++ where you can’t really create complex programs without using object oriented features, bypassing PHP’s OO support may be difficult. Let me assure you, however, that powerful applications can be written without the use of any OO concepts and methodologies (PHP was written in C, which has no OO support).

Let me just clarify something. I’m not advocating that you abandon PHP’s object oriented features entirely. Rather, I’m just trying to warn you not to use PHP like it was Java or C++ where one would freely use OO.

Carefully balance the benefits with the drawbacks before you decide to use an object oriented approach with PHP.

Although the author is right of course - OO in PHP is slower than PP - I would also like to say this:

…a language such as Java or C++ where you can’t really create complex programs without using object oriented features…

The fact that the author writes this, says to me he doesn’t really know what he’s talking about, at least when it concerns OOP.

Let me assure you, however, that powerful applications can be written without the use of any OO concepts and methodologies (PHP was written in C, which has no OO support).

As does this. While C doesn’t have OO-support, it’s perfectly possible to write object-oriented programs in it, using those ‘concepts and methodologies’ he claims can’t be used.

Don’t get me wrong, I do think PHP’s OO implementation is slow, but I also get very pissed when someone who doesn’t know anything about it starts saying bad things about it. Of all people who claim they are writing software the OO-way, only about 5% of them really know what they are doing. Of those 5%, maybe 0.0001% is using PHP. I haven’t yet seen ANY application written in PHP that uses OO ‘the right way’, and believe me, I examined a lot of packages, like PEAR, BinaryCloud, Javuh and so on. I’m not talking about WHAT they do - as they work fine in general - I’m talking about HOW they do it.

If you really want to know about OOP, you’ll have to search hard to find someone who can tell you about it, and the chance of that person also knowing PHP is very, very slim. (Of course, I am the noted exception ;)). Before everybody starts screaming: this is the same for Java- and/or C++ programmers. Very few programmers actually know what they are doing in those languages. OO is new and difficult, and it’s easy to write large, inefficient programs with it, and that is what happens a lot.

As I said before: OO-code in PHP is slower than PP-code. But because the codebase gets so much smaller and simpler (if done right, which almost never happens), that almost entirely makes up for the lack of speed. And it certainly will in PHP5.

I am open to let someone convince me that I shouldn’t use OOP in PHP, but the person who achieves that will have to qualify first:

  • Knowledge of real OO-languages like Smalltalk and in a lesser extend Java and C++ is a requirement.
  • Knowlegde of various OO-techniques and concepts (Design Patterns, Refactoring) is a requirement as well.
  • Some knowledge of PHP could come in handy.
  • A degree in Computer Science is a must.
  • A specialization in Software Technology is a must as well.

Now, if they could find a couple of such persons who claim that OOP in PHP is a bad idea, supported by a list of valid reasons, I might just consider abandoning OOP in PHP…

Vincent

Hi Vincent and others,

this is a very interesting thread that I printed it ( 26 pages actually ).

I hope that in the future the PHP core developers will not reinvent the “wheels” so that we will have to modify the scripts we wrote using classes.

An example could be:


class pippo
{
var $pluto;
etc
}
$cartoon = new pippo;
print $cartoon->pluto;

Well the day that php people will introduce the way to render private / public a properties…will they use public as default ?!? ( I do not remember what C++ use )


class pippo
{
// private: if private is the default...
var $pluto;
etc
}
$cartoon = new pippo;
print $cartoon->pluto; //...this will not work

If in that case I had used a method ( a function ) to read that value, the problem will never exist.

This is a poor example from my poor experience of how a bad use of classes could make problem in the future.

I think that the more experienced people like you could help us to design at the present time a good class without be worried or reducing the panic of future php upgrades.

:cool:

ps
I’m sorry but I hope that you will understand my very bad english… :frowning:

I’ve also tried to do OOP but gave up. Why?

1.) the processes that code is trying to do is somehow hidden so when I look at a OOP code I can’t quickly recognize what it is trying to do.

2.) There are a lot of articles that show you how to write code in OOP. But I’ve seen none (which was clear) that shows you how to think OOP. Where are object limits? What can on object be? How to create an object that is similar to the real world objects? !!!

3.) I guess you have to spend more time planning when doing OOP. But if I planned it wrong? Is there any sense then? voostind mentioned: You can code in OOP but not realy making it OO. His post was VERY long.

4.) With OOP object are not realy reusable. Well, they are but when you are trying to use an object that was programmed by someone else you must spend a lot of time learning what he was trying to do. But I guess this is because I don’t realy understand OOP.

Well, no I’m going offline to read voostind posts and try to learn something.

Originally posted by voostind

On the other hand, if you are using good algorithms and good OOP techniques (design patterns and such) and find little room for improvement while the software still runs (too) slow, than buying hardware is a perfectly good solution. It’s much cheaper.

can you offer any guidelines/resources that describe how to create good algorithms and good OOP and maybe even some explanations of various OOP concepts, Design Patterns, Refactoring, etc?

Okay:

Cormen, Leiserson and Rivest, Introduction to Algorithms
Gamma, Helm, Johnson and Vlissides, Design Patterns - Elements of Reusable Object-Oriented Software.
Fowler, Refactoring - Improving the Design of Existing Code.

Try these for starters; they are available at your local bookstore :slight_smile:

Vincent

Also, for a great primer in OOP, try Thinking in Java (http://www.mindview.net/Books) - free online.

1.) the processes that code is trying to do is somehow hidden so when I look at a OOP code I can’t quickly recognize what it is trying to do.

I’ve found OOP to be one of those wierd topics that is extremely hard to convery, at a fundamental level. The best approach is to look at alot of OO code and just keep exposing yourself to it. Eventually it will click and you probably won’t ever want to go back.

These days I find OO code easier to read than a procedural equivalent.

2.) There are a lot of articles that show you how to write code in OOP. But I’ve seen none (which was clear) that shows you how to think OOP. Where are object limits? What can on object be? How to create an object that is similar to the real world objects? !!!

I think the best approach is to make sure you have examples which relate to things you already know in programming. If PHP is your thing, demand examples that relate to the web (as opposed to cars for example). Kevin Yanks paged result set is a great example of how it should be.

The more you code with OOP, the more obvious in becomes what an object should be. A common problem for PHP coders is writing so-called “god classes” - classes which do more than perhaps they should. Say you have an authentication class, which checks user names and passwords, and incorporates starting PHP sessions and fetching data from MySQL. That may be fine for the current problem. But what when the next project uses PostgreSQL and also requires use of sessions for, say, a shopping cart.

You now first need to re-write the class for PostgreSQL and then have to overcome the problems of potential conflicts between what the shopping cart is doing with sessions and what the authentication is doing with sessions.

It would be easier to have three classes, one for sessions, one for authentication and one for database access - these now become independent problems to be tackled independently, and can be nicely re-used by other classes.

3.) I guess you have to spend more time planning when doing OOP. But if I planned it wrong? Is there any sense then? voostind mentioned: You can code in OOP but not realy making it OO. His post was VERY long.

I’m not sure that’s true. I think I’m right in saying that the extreme programming methodology begins with the idea of “do some code first to build a prototype, then think hard once you’ve got there”.

In general, I think what’s most important is learning how to construct good APIs (the method by which you provide access to the code in your class). If the API is sound, behind it you can radically alter the code without effecting any other classes.

4.) With OOP object are not realy reusable. Well, they are but when you are trying to use an object that was programmed by someone else you must spend a lot of time learning what he was trying to do. But I guess this is because I don’t realy understand OOP.

Kind of covered this already. When using someone elses code, for example, they’ve hopefully documented it a userful manner. Once you get used to reading API documentation, you’ll see it’s pretty similar to the PHP manual, for example. Take a look at Vincent’s own API documentation for Eclipse - a very good example of how things should be.