The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

McGruf, you just broke 3 fundamental rules that every programmer follows when developing an application:

Reduce public exposure

Seen from the outside the complexity of a class depends upon the number of public methods included in the class. A class which makes one or two methods public is usually easier to understand than a class which makes dozens of them available from the outside.

Classes where the ratio of public/protected methods is low are desirable in that a user of the class only needs to understand the functionality of the methods which are public from the class.

Don’t make assumptions

Don’t make assumptions about why a method has been called or about what the caller of a method wishes to do with the results. (in reference to sticking fingers in power sockets).

Top-down

Write your classes using the top-down fashion, not bottom-up (starting with details). Top-down is a nice way of successively approaching details of the implementation, ending up with defining primitive methods. The code will be independent of representation since the representation is not known when the higher levels of code are designed.

thanks to all for the intellectual debate so far, I suppose it is a shame that there is not a set format to learning and coding PHP OOP but I guess we can blame that on the language itself for being so loose; there are so many ways to achieve the same thing, so naturally everyone develops their own interpretation. Must be one of those greatest strength, greatest weakness things.

Knowing what I know, this is my first class. From an overall standpoint please provide any constructive criticism you might have.

Here is my self-imposed criticism:
- of the db classes i've looked at, they tend to have a method to connect rather than having it in the constructor. But my thought is that I use the db on virtually every page, so it makes sense to always connect
- It lacks privacy
- I don't yet have an error handling class to compliment any problems that may arise
- the clean() method has basically been dropped in without any implementation elsewhere in the class
- I can't work out how I should handle and display an array of results
- 'MySQL' might be a better class name than 'db'

The class encapsulates a database connection ie all the mysql~ fns which allow you to communicate with the db server. I'd call it: "MysqliConnection". (I'd recommend using mysqli provided you don't need to work with any db less than MySQL 4.1 - see manual).

Originally Posted by wheeler

of the db classes i've looked at, they tend to have a method to connect rather than having it in the constructor. But my thought is that I use the db on virtually every page, so it makes sense to always connect

Connecting in the constructor is simpler (it's one less method that needs to be called). Always do the simplest thing unless you have a good reason not to. If you're not sure do the simplest thing anyway and change it later when you are sure, if you have to.

Originally Posted by wheeler

I don't yet have an error handling class to compliment any problems that may arise

That's probably a good thing.

Originally Posted by wheeler

the clean() method has basically been dropped in without any implementation elsewhere in the class

A database connection shouldn't be thinking about output. All it has to do is talk to a db server.

Originally Posted by wheeler

I can't work out how I should handle and display an array of results

How would you like it to work? What's the simplest way you can think of for clients to interact with a connection class?

If you like, we could try writing it test-first with Test Driven Design (TDD). This works one step at a time: you think of a requirement, express it as a test, and then write the minimum amount of code needed to make the test pass. Repeat until done. The class will just write itself.

But I have this feeling that something better is just around the corner, and at my stage that must be OOP. I don't exactly want to change direction I just want to do the same stuff better.

So I thought bugger it, I might as well take the plunge now and try OOP.

Oh boy!

It is possible that your story will go something like:

* Learn the syntax and build an object or two.
* You'll try it in a live project.
* You will realise that you are getting no real advantage, and you'll post your code on the forums.
* People will tell you that your objects are just "smart data", and that you should "think in objects".
* You'll start to build some top level objects, but get confused. Very confused.
* One late project and several rewrites later, you'll come to the conclusion that this OO stuff is a waste of time and go back to procedural.
* You'll repeat the whole sequence six months later.
* ...and again six months after that, but this time you won't listen to advice.
* A year after that, you'll "get it".
* You'll then post lots of helpful advice on forums to other OO beginners suggesting that you "think in objects"...

Right now the paradigm you are used to is the machine paradigm. You have the idea of a processor running over your code, occassionally skipping chunks or doing them over and over, or repeating set chunks. It's taken a while to get fluid with this, but I bet you are comfortable. Enjoy it even.

The problem is that the paradigm is very limited. You end up with a lot of small pieces, too many for the human brain. You conceptually group stuff into modules, but it's very hard to rip a module out and replace it with another. Easier just to tweak the module you have, and the modules that use it the ones that use that...

You just get it working, then the damn customer wants you to add something else...just as you are halfway through adding caching or wotnot. One slip, and you are in a mess with thousand of procedures that all call each other.

The "something better" you are after is the ability to swap authentication or add caching and the like, by changing just one line of code. You still have to write the modules (classes) underneath, but you can flip them in and out at will. Once you start doing that, you start to think of your application in terms of these blocks. You are then thinking in objects. Trouble is, writing these objects involves writing to a new paradigm. A paradigm takes two years to learn. In the meantime you will suffer.

(To see how much you will suffer, Google for the "Satir change curve").

You suffer less if you can break the learning process into a sequence of smaller revelations, and if you can reduce the costs of your experiments.

Here is my step by step guide. I hope others will critique it, repeat it, and then take the credit when their post gets "stickied".

1) Learn the syntax by building some small, low level objects. You probably think you know the syntax already, you just read it right? You need to become super comfortable. Don't worry too much about public/protected/private (and don't ever use final), but use everything else.

Say you want to search a table of people and add/delete a row. Where you would have gone...

This is using classes just as modules. That's fine for now. Do this "bottom up". That is, with the low level mechanical stuff first. You won't yet know how to design, so going "top down" is a non-starter. You won't win much yet, but it will give you a working baseline.

2) Embrace "smart data" if you think it helps. For example, you have an array of arrays. Let's say it's a list of rows from a DB query. Wrap it in a class...

3) Learn how exceptions work. Error handling in OO can be tricky without them. It's also a nice easy way to break out of the machine view, and you can use them in procedures too.

4) Use some OO libraries to get more comfortable.

5) After a few weeks/months you will want to group the little methods into larger ones, and also pass objects from method to method. It's time to read the "Refactoring" book by Martin Fowler. The technique of refactoring is the one that allows you to experiment at low cost. It's also in this book that you will come across "unit testing".

6) Try unit testing, and later TDD. Paired with refactoring, and backed up by version control, your whole coding style will become more fluid. This new programming style, when coupled with OO, is very powerful. It amplifies the good stuff in OO, and so will allow you to see it all more clearly.

7) Can you swap a component in one line of code? See if you can find a candidate class and then actually try it. If you get stuck, and post to the forums, everyone will start to tell you about some design pattern you should use. These are ways of factoring the code to make different types of changes possible. There are a lot of them, but they are not mysterious, and by this point you will be using them already without realising.

8) Building a fully OO app. is a good thing to do right now. It won't be "reusable", but it will work once. The main thing is that you are close to your earlier productivity with procedures. By now, that was a year ago, but then you were ceiling'ed. You couldn't contemplate building an application larger than you could hold in your head. That ceiling will now start to rise.

9) Once you've got Strategy and Iterator patterns, and a couple of others, time to start reading again. Read lots on patterns and then...forget it. You want the general ideas absorbed into your subconscious, and you want to know what problems can be solved. You don't want to distort your designs by trying hard to include them. Ocasionally you want to talk about them and look them up. Then the naming is useful.

10) By now your entire apps. are probably in objects. You're probably concerned that your code is still not "reusable". Don't worry. Nothing ever is.

11) Once you are patterned out, and frankly bored, read some higher level design books such as "Object Design" by Rebecca Wirfs-Brock. Try CRC cards. The're a great way to think in objects.

12) After that you can answer forum posts telling people to "think in objects".

thanks so much mcgruff and lastcraft, very helpful posts. I think i'll need some time to absorb the wisdom provided in this thread!

I'm trying out some ideas from the extreme programming approach, mostly just finding a task/story to implement it and just doing exactly what is needed to complete that task (as opposed to dumping in every function i've ever written and never using them). But lastcraft your right, i'm probably thinking top-down when I need to think bottom-up.

Fortunately for me I guess my first OOP site is kindof straightforward. I'm happy to get it object orientated, then refactor it as I work out more stuff - as long as I can get it done and working i'll be stoked!

lastcraft, your post introduction to changing one's mentality was very interesting, and was similar to an example in Head First Java, which spelled out the benefits of OOP - as soon as you get it, its a bit like being slapped in the forehead! I'm about a month in now, there is no going back for me (i'm stubborn like that )

* Learn the syntax and build an object or two.
* You'll try it in a live project.
* You will realise that you are getting no real advantage, and you'll post your code on the forums.
* People will tell you that your objects are just "smart data", and that you should "think in objects".
* You'll start to build some top level objects, but get confused. Very confused.
* One late project and several rewrites later, you'll come to the conclusion that this OO stuff is a waste of time and go back to procedural.
* You'll repeat the whole sequence six months later.
* ...and again six months after that, but this time you won't listen to advice.
* A year after that, you'll "get it".
* You'll then post lots of helpful advice on forums to other OO beginners suggesting that you "think in objects"...

don't hold me to it but I would've thought it's fine to quote the post somewhere else as long as you acknowledge the source and possibly link back to the thread. I'm sure sitepoint would answer that question in their docs somewhere...

Class attribute visibility Vs. Interface

The thing is, if you make your private methods publicly accessible you know for sure that someone will err.

I know this should have been solved by the 'moron' by using and Adapter + factory or some other fancy way to abstract your library.

The developer is not supposed to know what functions are public or private, unless you specify it. That's why I believe specifying the visibility is part of the documentation and development process. The same goes for unit testing, exceptions… Moreover it's important to provide third-party developers with interfaces instead of a bunch of public functions that change every release. An interface never changes and if a redesign is required, then a new interface is provided.

Unit tests make assertions about public behaviours not private implementations: you would never call a private method in unit test. If you program test-first, there is no reason ever to write a single visibility keyword. They really don't do anything useful.

But following a test-first development process doesn't make your application bulletproof, unless you use all the OOP arsenal, and visibility is one of them. Like phpimpact said, you're making assumptions and mixing the private and public layers of your application. That bad practice is similar to the "separate the logic from the presentation" issue, you know mixing PHP with HTML. Moreover you can unit test your application as much as you want but if you don't make private functions private, then anyone can break your code.

About unit testing, of course it's not limited to the public implementation. The private layer is often really tricky to develop as it contains most of the logic and algorithms hidden to the class users. We provide them with a bunch of public functions or interfaces, that's all.

Originally Posted by McGruff

Describing the interface for a class is of course very important but once you've done that enforcing it isn't necessary. How often have you tried to stick your fingers in a power socket? You just wouldn't do that, provided you know it is a power socket.

Again you're assuming the developers read the documentation or know what a power socket is. You can 't enforce visibility in your documentation, you have to code it first.

Originally Posted by McGruff

It's very, very easy to make things complicated. The best programmers are those who can cut through all the clutter and confusion to make things as simple as they can be.

It's the whole point of specifying the visibility of your attributes, making things simpler. See how you already complicated things saying private and public are useless. Developers asking questions, calling the wrong functions, breaking your unit tests… this thread is becoming a dangerous place

Accessibility and listing elements in a message

I saw lastcraft and Wheeler are not using lists to enumerate elements. Know that it makes messages unaccessible to visually-impaired people for example. Using characters * and - is not a good idea, better use the message editor list feature :

An interface never changes and if a redesign is required, then a new interface is provided.

That's almost the same as a general rule of thumb I have created for myself; every change in functionality should require only addition in the source-code. Which is nice in combination with what lastcraft said about being able to change every component in a single line of code.

The Wheeler Coding Process™

Originally Posted by wheeler

thanks to all for the intellectual debate so far, I suppose it is a shame that there is not a set format to learning and coding PHP OOP but I guess we can blame that on the language itself for being so loose; there are so many ways to achieve the same thing, so naturally everyone develops their own interpretation. Must be one of those greatest strength, greatest weakness things.

Think the development kingdom as an ecosystem, a living organism, better have hundreds of species than a bunch of dead worms coding around . PHP OOP ? Seperate the language from the programming methodology. Pick your language, pick your method. Test Driven Development/eXtreme Programming ? Unified Process ? Wheeler Coding Process ? See you're already immortal, among the Gods of Development

Originally Posted by wheeler

of the db classes i've looked at, they tend to have a method to connect rather than having it in the constructor. But my thought is that I use the db on virtually every page, so it makes sense to always connect

Think simple. What's the aim of a constructor ? To build an object, not to connect to a database. You also shouldn't think of what you want but what others would want. For example I prefer to construct my object first then call its functions. Build a database object and connect to it. That way I have better control other the application flow. If the construction fails, I can report the problem. If it's a success, let's connect…

In the procedural programming paradigm it's important not to develop functions that do too many actions : construction, connection… It makes the code much more reusable. Fundamental rule : reusability. And of course is also works when OOPing

Originally Posted by wheeler

I don't yet have an error handling class to compliment any problems that may arise

I second what someones said about using exceptions. You can't just clutter your OO code with hundreds of error handling calls, tests…

Originally Posted by wheeler

I can't work out how I should handle and display an array of results

Check out the PEAR database packages and the way fetched results are handled as objects. The PHP 5 Iterator interface is really useful to parse a results set using foreach.

I also have some great online references on these subjects if you're interested : ActiveRecord, Object-Relational Mapping (ORM)…

Originally Posted by wheeler

'MySQL' might be a better class name than 'db'

MySQL, db… these are too generic names that anyone could pick. My advice is to prefix your class names, as PHP 4/5 lacks the namespace feature. It avoids conflicts with other classes, frameworks, your own projects… Why don't you coin some nice name for your project ? The Wheeler Framework ? An other solution is to prefix your classes with a short URL. For example if your project was hosted at "wheelerdb.sf.net" you would name your class "wheelerdb_sf_net_db". I know it's long but it's an example. I have a C++ and Java background so… it probably makes me an evil PHP 5 developer

About naming your class MySQL, I think it's a bad idea. What will happen if you decide to switch to PostgreSQL ? Don't make the assumption you'll ever stick to MySQL, PHP history. At first there was a bunch of PHP 4 functions, then some pseudo-classes emerged… then packages in some fruity framework… and now PDO. What's next ?

You were right, your code lacks privacy. Better private the variable as no one is supposed to access it. It's also important to choose a naming convention. $affected and affected() ? Affected what ? Rows ? Then name your variable $affected_rows. What's the aim of the function ? Document it using PHPdoc : aim, parameters, returned value… What does it do ? It returns the affected rows ? Then name it something like get_affected_rows() or getAffectedRows() depending of your conventions. Remember that a function always perform an action. I think I mentionned in a previous post, maybe in an other thread…

If you don't document your code and choose self-explicit names, you'll never be able to understand your own code in a few months.

Again using PHPdoc (/** */) instead of these ## comments. It specially useful for complex functions, your constructor is. It connects to the database, handle errors, select the database and initialize the attributes… Separate things, make things simpler. Use exceptions instead of if if if… What if you're not supposed to output HTML ? What if the developer wants to handle errors using his own system ?

Of course I'm a bit picky but It's important to think outside the box. It's easy to quick & dirty code and in a few months… you'll just flush the class

Coding your own error handling system is a lot of fun. Don't hesitate to dig into the PEAR framework manual, its code too. All functions from the database package return an object for example. It can be the results set you just queried… or an error object. It makes coding a breeze.

Seperating the error handling from the database management is also important because you often have to reuse your error handling functions. Again, think reusability. Encapsulating them would allow you to define different methods : output HTML error messages, log them in a file…

About that function, again, it does too many things. It's a simple one so a good example. getError() initializes attributes, build up an error message and returns it. What if I need the error number ? What if I want to format the error message ? Is a getError() function really supposed to return a string ? What's an Error ? An object ? A code ? Again, see PEAR. In the object parallel dimension a develop would expect an object, not a string.

Plug & Pray components

Originally Posted by Jasper Bekkers

That's almost the same as a general rule of thumb I have created for myself; every change in functionality should require only addition in the source-code. Which is nice in combination with what lastcraft said about being able to change every component in a single line of code.

Yes software components should be as Plug & Play as hardware components, not Plug & Pray. It's a joke from my more Microsoft/DirectX days, not sure if it still works

About unit testing, of course it's not limited to the public implementation.

That is simply wrong.

The garbled, stream-of-consciousness gibberish is a bit of a giveaway. You're Dr Livingston / Widowmaker / BigFatBob / etc etc aren't you? How many times do you have to be banned before you get the message?

Descartes avait raison

Originally Posted by lastcraft

You suffer less if you can break the learning process into a sequence of smaller revelations, and if you can reduce the costs of your experiments.

Read Descartes lately ? I agree as breaking things down, into smaller chunks, make solving problems simpler. But of course it can make things more complicated if you don't balance your code. Too many objects, inheritance in the way… order can bring chaos.

The garbled, stream-of-consciousness gibberish is a bit of a giveaway. You're Dr Livingston / Widowmaker / BigFatBob / etc etc aren't you? How many times do you have to be banned before you get the message?

Dr Livingston was banned? why? when can someone point me to a thread about it (if there is one)

GoF Design Patterns

Originally Posted by lastcraft

7) Can you swap a component in one line of code? See if you can find a candidate class and then actually try it. If you get stuck, and post to the forums, everyone will start to tell you about some design pattern you should use. These are ways of factoring the code to make different types of changes possible. There are a lot of them, but they are not mysterious, and by this point you will be using them already without realising.
[…]
9) Once you've got Strategy and Iterator patterns, and a couple of others, time to start reading again. Read lots on patterns and then...forget it. You want the general ideas absorbed into your subconscious, and you want to know what problems can be solved. You don't want to distort your designs by trying hard to include them. Ocasionally you want to talk about them and look them up. Then the naming is useful.

I just love the Iterator pattern

Seriously I strongly recommend reading the Design Patterns book by the Gang of Four (GoF) : Gamma, Helm, Johnson and Vissicles. Harry Fuecks's phpPatterns is also a great spot to learn more about design patterns.

Design patterns are like a second language, for developers. They're everywhere

Dr Livingston was banned? why? when can someone point me to a thread about it (if there is one)

I made a complaint about some posts by him earlier in this thread. The posts were deleted and he was banned judging by the "not a member" which now, thankfully, appears beneath his name.

I didn't mean to drag this thread off topic with the public/private stuff (and I've apologised to Wheeler for that). I expected there would be some disagreement but there's a big difference between intelligent debate and simply being abusive.

"inter-class communication"

yep, I made that name up all by myself... i'm sure there is a technical term for it

now that some basic ideas are starting to fall into place, I seem to have a real problem communicating between classes.

As an example, right now I have to:

a) instantiate a page class that handles header, footer, meta tags etc.
b) instantiate a session class that checks the permission level requirement of the current page and whether the user has sufficient privilege/is logged in
c) instantiate a database class to do typical database stuff

So on edit-account.php, say if I wanted to access a db method, I would have to go: $page->session->db->query("SELECT ...");

These 3 classes need to do a certain amount of talking to one another. My approach is to have absolute bare minimum code on the "view" pages (though i'm still miles away from understanding MVC), so I want to instantiate a Page and have the session and databases setup straight away. The flow is:
1. create a new page eg. edit-account.php
2. right away require the page class, passing the required permission (eg. guest/member/admin)
3. calling the Session class in the Page __construct, and immediately determining if the user is authorised access
4. if authorised, instantiate DB class and connect right away, otherwise redirect to login.php

I understand that one of the gains of OOP is to create reusable code, and to abstract classes into a the most accurate possible definition (eg. a dog is a dog, is a canine, is an animal, if necessary I should burrow down to a dog class).

But without perhaps grasping exactly what I should be doing particularly with object-to-object communication, I have a sneaking suspicious I will end up with a pile of spaghetti... well I guess thats inevitable but at least it could be tasty, authentic spaghetti

Is the easy beginners way to communicate between objects to pass objects at __construct time? put in a require() mid-method? These seem unlikely but I can't think of any other alternatives...

I understand that one of the gains of OOP is to create reusable code ...

I don't think that's a good way to look at it. OOP helps to organise your code. As a side effect, it may become more reusable, but that's not a primary goal and you can also achieve that with other means.
Also, try to avoid over-using inheritance. It's a common fallacy for beginners with OOP. If possible, you should usually favour composition over inheritance.

Originally Posted by wheeler

2. right away require the page class, passing the required permission (eg. guest/member/admin)
3. calling the Session class in the Page __construct, and immediately determining if the user is authorised access
4. if authorised, instantiate DB class and connect right away, otherwise redirect to login.php

Originally Posted by wheeler

Is the easy beginners way to communicate between objects to pass objects at __construct time? put in a require() mid-method? These seem unlikely but I can't think of any other alternatives...

Try to avoid creating classes inside other classes. That creates a strong dependency on the created class (Eg. you can't change the dependency, without changing the dependent). First try to pass the dependency in the method, using it. If that's impractical, try to pass it in the constructor of the dependent. If that becomes too heavy, try to combine related parameters into container objects, and pass these. There are sophisticated patterns, that make this less laborious, but it's a good start because A) It's transparent and B) It's easy to change later on.