Five Tips To Make Good Object-Oriented Code Better

« »

Last week, I did a talk at the Frederick Web meetup about tips and tricks for improving your object-oriented code. A lot of these tips were adapted from a fabulous presentation by Stefan Priebsch but the ideas are by no means original to him, and they’re exceptionally good ideas when you’re talking about object-oriented code. Slides are at the end of this blog post, and I’m happy to do this talk over again for local groups.

#1 Use Objects. Lots of Objects
This point is taken directly out of Stefan’s slides, because it’s such a good point. There seems to be a perception in the PHP world that using lots of objects is slow, cumbersome, or plain difficult to maintain. But the reality is that this is not true at all (for example the object model in PHP 5.3 is vastly improved over older models).

By using lots of objects, you can make sure that each object has one job and only one job. You don’t have to make objects smart, either; instead you can rely on other objects to do work for you, and give you the things that you need. Adding lots of objects makes it easy, once you understand the architecture, to make changes without having to change massive amounts of code. The best object-oriented framework I ever worked on often required only one or two line changes to make massive improvements in performance, features, or the resolution of bugs.

Hardware is inexpensive, and there are options to optimize and improve your performance. You should make use of them.

#2 Use Interfaces To Make APIs Predictable
Interfaces are a great way to enforce a design. The concept of “design by contract” is the point of interfaces: you establish your contract, and you then use it.

Interfaces allow for strict typehinting, and by typehinting you can ensure that certain methods are always available for your use. Beyond that, interfaces make your API consistent, which is a big boon, especially as your team gets larger. Each interface will provide the model to utilize, and your teams will know that they have to implement a few methods each time they wish to make use of a particular interface.

#3 Use Dependency Injection
For the longest time I didn’t realize the importance of dependency injection. But dependency injection is critically important, especially if you want to write or utilize a framework or do any kind of unit testing.

Many programmers attempt to instantiate objects directly in their code, or grab objects out of singletons. This is a bad approach, because it makes testing impossible. You cannot inject a mock object; you also have trouble with mock data. For example, if you create your database object inside your controller object, you always have to create a database to test with, which adds another variable for possible failure of your unit test.

Learn to use dependency injection. It will make testing and feature addition easier.

#4 Composition Over Inheritance
There are two concepts that are critical in object-oriented programming: the concept of an object having an “is-a” relationship versus a “has-a” relationship.

For example, an apple “is a” fruit, while an apple “has a” seed. You would never say that a fruit could be a seed, but you could say that a fruit could be an apple. This distinction is important.

Stefan mentions that well-written classes can be extended no matter the circumstances, and I think he’s right. I also know that the more simple your classes, the better off they are in terms of abstraction. Always carefully consider whether or not objects are doing their jobs and what those jobs are.

#5 Create Loosely Coupled Classes
Often times when a developer gives each object only one responsibility, they tightly couple objects together. This is a mistake, because it makes reuse harder later on. Objects will often request information from other objects, and while this is not avoidable in all situations, these tightly coupled classes that rely on one another’s functionality makes pulling those objects apart impossible.

Zend Framework offers a good example of classes that are more loosely coupled. You can generally make use of Zend components without using the entire Zend Framework; likewise, you can opt to use the entire framework, but this is entirely optional. I make use of a number of the Zend components (Zend_Validate, for example), without using the MVC pattern that Zend utilizes.

Summary
These tips will enhance and improve your object-oriented projects. Architecture is difficult, but the more time and effort you spend doing it the easier developing will become.

Slides – Five Tips Talk

Brandon Savage is the author of Mastering Object Oriented PHP and Practical Design Patterns in PHP

Posted on 10/28/2009 at 1:00 am
Categories: PHP 5, Technology, Best Practices, System Architecture
Tags: , , ,

Mikael (@mikaelgramont) wrote at 10/28/2009 9:34 am:

Hi Brandon,
I’m not sure I understand this

“Often times when a developer gives each object only one responsibility, they tightly couple objects together.”

Can you explain ?

Mikael

Brandon Savage (@brandonsavage) wrote at 10/28/2009 9:39 am:

For example, a developer will create an object that establishes a database connection, and another object which requests that database connection rather than allowing it to be injected. Or, they’ll create a request class (a class that holds the request data), but then have methods that send that data to the controller, rather than letting the controller request it. These are tight couplings that are unnecessary.

Daniel (@coderguy64) wrote at 10/28/2009 10:10 am:

Brandon,

Thanks for the write up I appreciated the read.

Daniel

ivanjovanovic (@ivanjovanovic) wrote at 10/28/2009 12:46 pm:

Regarding the #5.

I see the properly designed application as pile of layers stacked one on other. Like the onion. When it comes to class design it must have only one function and to be just in one layer, not to be spread across them. Also, the connectivity among layers should be that you do not skip the layers. Information should flow through layers as Brandon is telling, without unnecessary couplings.

Cheers,
Ivan

Sergey wrote at 10/28/2009 1:00 pm:

> Zend Framework offers a good example of classes that are more loosely coupled. You can generally make use of Zend components without using the entire Zend Framework;

Haha((( do you ever tryed this? i tried to use Zend OpenId component without Zend Framework… oh, there was much easy to write new library((

David Clark (@dmclark) wrote at 10/28/2009 1:08 pm:

I always learn so much from your posts -thanks so much.
I do not know about dependency injection – do you have any links that do not require subscription?

Anis uddin ahmad (@ajaxray) wrote at 10/28/2009 2:18 pm:

Thanks a lot for great tips!
Can u plz explain ‘one object – one job’ concept?
My view is :
An object is to represent the state and perform one/some related actions of an ‘Entity’. And each method of this objest should perform exactly ‘One job’.
Don’t u think so?

Daniel Freudenberger wrote at 10/28/2009 7:16 pm:

Thanks for your post. I’d love to use DI in php but I didn’t find an easy to use DI-Implementation. I’m used to StructureMap in c# and I’m really loving it! Do you have any suggestions?

Stephan Hochdoerfer (@shochdoerfer) wrote at 10/29/2009 3:47 am:

Mentioning DI and ZF in one blog post seems really odd to me.

@David:
Maybe this helps as a starting point: http://en.wikipedia.org/wiki/Dependency_injection

Mikael (@mikaelgramont) wrote at 10/29/2009 3:55 am:

Allright Brandon, so what you’re saying is sometimes people do one thing right (one object / one job) but end up doing another one wrong (tight coupling). For some reason, I was confused. Thanks for clarifying that for me.

thinsoldier (@thinsoldier) wrote at 10/30/2009 5:30 pm:

For so long I’ve only seen Dependency Injection mentioned in relation to Testing and (this sounds so bad) I’m honesly YEARS away from unit testing anything. So, I’ve just ignored DI. But now that you mention “feature addition” I suddenly realized that an old non-OO project of mine is full of “dependency injection” that I had to retrofit in order to add flexibility. I now see a ton of potential headaches in every piece of OO code I’ve written this year.

I’m hoping to soon have similarly enlightening moments for Interfaces, composition, factories, and coupling.

Your #1 point hit the nail on the head.
I spent the last 3 days trying to decide whether or not to bring a Value Object class into the picture for my database classes. In the end I chose not to.

Could you give an example of what the Zend Validate code would be like if it was too tightly coupled to the rest of ZFW.

shfx (@shfx) wrote at 11/4/2009 8:31 am:

Thanks for the post. Those things are not so obvious until somebody write them down ;).

As for Dependency Injection, there is some nice interface at http://components.symfony-project.org/ but i never used it.

Jon Wahl wrote at 11/15/2009 12:56 pm:

I am a PHP developer who is keenly interested in fine tuning my object oriented programming skills. I write OO code (using the CodeIgniter framework), but I absolutely know that a lot of what I’m writing is not making use of the features of OO programming properly. I tend to write procedural code in my classes. I find object variables “handy” because they are global within the scope of the object. I really want to advance my skill/knowledge, but most of the articles written about object oriented programming in php tend to focus on the basics: What is object oriented programming; what are objects, methods, etc.. Your article was one of the first that addressed something I’m looking for: I understand the basics of OO programming but I want to do better. Do you know of any other online or book form resources that use php that addresses this?

Great article and great blog.

« »

Copyright © 2023 by Brandon Savage. All rights reserved.