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).

(more…)

Wednesday, October 28th, 2009 @ 1:00 am | Comment (13) | Categories: Technology, Best Practices, System Architecture, PHP 5
Tags: , , ,

Accessing Databases with PDO: A Primer

With the introduction of PHP 5, the PHP Data Object was introduced as core functionality. PHP 5.1 turned on a minimum level of support for SQLite, by default, and PDO supports most of the major database engines. PDO offers a number of enhancements and improvements over the various database libraries (e.g. mysql_*, mysqli_*, pg_*), the biggest one being consistency. Still, the high level of code that involves direct use of the various database libraries means that PDO still isn’t as widely accepted as it should be.

This primer will show the various uses of PDO, and outline some of the benefits.

(more…)

Monday, October 5th, 2009 @ 1:00 am | Comment (4) | Categories: Best Practices, System Architecture, PHP 5
Tags: , ,

Peer Review: You Have Not Because You Ask Not (Requests & Responses)

This entry is part of an ongoing series involving the review of a code sample and it’s refactoring. For the original code sample, see here.

The topics discussed in this entry may be fairly advanced. Please feel free to ask questions, and discuss best practices.

If you’ve been following this series from the beginning, take a moment to look at the original code sample and compare it with where we are now. We’ve come a long way!

There is one last area that I want to address, and this has everything to do with object-oriented principles and code reusability. For those who are familiar with OO programming, they realize that the use of classes does not make something object oriented by nature. In this final part of the series, we’ll move one step closer to being object-oriented, by introducing the concepts of request and response objects.

At the moment, our object takes arguments like most functions do. This has some limitations. The first limitation is that the object must be aware: that is, it must have an understanding of the request it is being passed, and the response that it is getting from Twitter, as well as the response it will give back to our application. This means that in the event that something ever changes about the way that response is organized, we have to change this code, explicitly. I would like to avoid that.
(more…)

Monday, September 21st, 2009 @ 1:00 am | Comment (6) | Categories: Best Practices, System Architecture, PHP 5
Tags: , , ,

Custom Apps: Some Strategies For Easy Configuration Files

One of the decisions that has to be made each time an application is written for distribution is how best to set up the configuration files. There are a number of different approaches taken to this: some opt to use the define() function and define constants, while others use large arrays. The purpose of this post is to discuss a couple of configuration options that sometimes are overlooked by developers (including myself until last year).

Class Constants
One of the biggest struggles in OOP programming is how to go about setting up the default values and configuration values. For example, if you have a database class, how do you define the connection parameters?

(more…)

Wednesday, September 16th, 2009 @ 1:00 am | Comment (11) | Categories: Best Practices, System Architecture, PHP 5
Tags: , ,

Peer Review: Testable Code And Architecture

This entry is part of an ongoing series involving the review of a code sample and it’s refactoring. For the original code sample, see here.

Now that we’ve worked out the abstraction issues and the logic questions, we should take a moment to focus our attention on a few of the issues relating to the architecture and testability of the class we’ve worked out.

A couple of big architecture issues raise their heads early on. The first one is this set of code:

<?php
// class_Twitter.php - NPC TWITTER AUTO-FEED
error_reporting(E_ALL); 

// DO NOT RUN THIS SCRIPT STANDALONE (HAS PASSWORD)
if (count(get_included_files()) < 2) {
    header("HTTP/1.1 301 Moved Permanently"); header("Location: /"); exit;
} 
&#91;/sourcecode&#93;

This raises a number of architectural issues that we should address. My recommendation is that we remove this code altogether. The first line, about error reporting, really should be set at the application level, rather than the script level. As for the redirect, this is intended to prevent the script from being called directly. However, it's a good idea to place classes like this outside the document root anyway, meaning that they would never be called directly. When including this file, there's the potential that you'll not have included enough files and you'll inadvertently redirect your user. So let's drop these lines altogether. This will improve reusability and improve the architecture.

There's another line of code that is particularly troubling:

&#91;sourcecode language="php"&#93;
$this->http->setHost($this->baseHost . "statuses/update.json?status=".urlencode(stripslashes( urldecode($message))));

It may not look obvious at first, but this code relies on the assumption that the magic_quotes_gpc directive is set to on.

For those who don’t know, magic_quotes_gpc automatically adds slashes to all GET, POST and COOKIE variables that come into an application. This deprecated feature represents a poor programming practice, and its use is discouraged. Though it remains on by default in PHP installations, it should be turned off altogether if at all possible. It’s slow, and potentially dangerous. Additionally, it will be removed in future versions, meaning that code relying upon magic_quotes_gpc will break in the future.

Now, oftentimes programmers don’t have direct access to the magic_quotes_gpc directive in php.ini, but it can be set on the htaccess level, if your hosting provider allows you to access PHP variables in this way.

I’m going to make the assumption that we’ve disabled magic_quotes_gpc, as is recommended by the PHP manual.

Another problem that we need to address is the fact that this object gets thrown away after it’s been used. We have the property $done, which gets set when a tweet is successful. Unless there’s a good reason for it, objects should never be designed this way. We’ll remove this code in the final draft (see below).

Moving on to testing, again we have to ask ourselves about abstraction. Where testing is concerned, it would be very easy to abstract the testing out of this object. Making use of things like the HTTP_Request2_Adapter_Mock class will help us to “test” the Twitter interface without actually posting a tweet. Unit testing software like PHPUnit will give us reports on code coverage.

If we opt to leave the test code in the object itself, it should be abstracted into its own method. But I don’t recommend this course at all, because testing should be conducted at the application level. Moving testing out of the class also allows us to remove references to the $done property, and remove the $you property as well as the test() method, the $test property, and a large bit of code from the tweet() method. All of this code will then not be loaded on each request of our class. Not a bad improvement.

Something else that we’ll do in order to improve testability is we will inject (rather than create) the HTTPRequest object into the class. This allows us to both inject an object that is a mock object, and it also allows us greater control over the environment when we do our testing.

It was pointed out by the blog PHP In Action that one of the things that we should have done first is write unit tests. I think that this is good advice for most applications. Obviously, the small size of this class make unit testing less critical, but it is a good practice to write unit tests first, and then refactor.

A good example of this is the work being done by web2project with regards to bug fixes. According to Keith Casey, one of the leads on the project, their rule now is that any time a bug is fixed, a unit test identifying the bug must be submitted along with the bug fix. This has allowed them to significantly improve their testing system, and it’s a great idea for existing projects that don’t have unit tests but want to implement them.

Testing is not to be underestimated. Testing allows you to refactor methods and the internal workings of a class, and still know that the results are right. It allows you to work on a very small part of an application without necessarily understanding the whole application, because you can run a unit test suite and see if your code works properly. And writing tests first, even on bug fixes, forces you to think about how you expect your code to work, and face the assumptions you’ve made about that process, as well.

We’ve made a good number of changes to the code, and we’ve made a vast number of improvements. Let’s take a look at what we’ve got:
(more…)

Monday, September 14th, 2009 @ 1:00 am | Comment (4) | Categories: Usability, Best Practices, System Architecture
Tags: , , ,

Peer Review: Improving The Business Logic

This entry is part of an ongoing series involving the review of a code sample and it’s refactoring. For the original code sample, see here.

So far, we’ve done quite a bit of work on our Twitter class, making it better. There’s still work to be done, though, especially improving the logic.

The Twitter class we have now has a number of logical flaws in it that we need to address. Additionally, there are some logical flaws that we started with that I want to highlight, even though we’ve already fixed them. Let’s get started with those.
(more…)

Tuesday, September 8th, 2009 @ 1:00 am | Comment (10) | Categories: System Architecture, Debugging, Best Practices
Tags: , , ,

« Older Entries Newer Entries »

Copyright © 2023 by Brandon Savage. All rights reserved.