PapayaSoft - Phuket web development

What Is Dependency Injection?

| Comments

For quite some time, I have been working on getting my head around best practices for structuring my web applications. One of the strongest messages that has come through is to use dependency injection to facilitate unit testing.

As many others have noted, dependency injection is a very simple concept. If one thing (the “consumer”) depends upon something else (the “dependency”) to do its work, then the consumer should be given the dependency. The consumer should depend upon an agreed set of functionality that the dependency performs, but it should not care how the dependency actually gets the job done.

An easy example

A radio receives transmissions and plays sounds through its speakers. Nothing special there. But it needs a power source to function. The power source’s adapter has to fit into the hole on back of the radio. And there has to be some compatibility of voltages and currents and all that electrical magic. The radio is the consumer and the power source is the dependency. You can’t run the radio without the power source.

Note that, in principle, the power source could be a pack of AA batteries. Or it could be a solar cell. Or it could be a collection of gerbils running on flywheels. As long as it outputs the right voltage and current and the plug fits into the hole, then all is cool. The radio is not concerned by the power source implementation as long it lives up to what we expect a power source to do (i.e., its interface).

How about some code?

Using our radio and power source example, we could imagine PHP objects and interfaces as follows:

interface PowerSourceInterface 
{   
    public function getPower($numberOfPowerUnits);
}

class PowerSourceGerbils implements PowerSourceInterface
{
    protected $_gerbils;
    
    public function __construct($gerbils)
    {
        $this->_gerbils = $gerbils;
    }
    
    pubic function getPower($numberOfPowerUnits)
    {
        // Make the gerbils run like hell on the flywheel
        // to generate the requested amount of power.
    }
}

class Radio 
{
    protected $_powerSource;
    
    public function __construct(PowerSourceInterface $powerSource)
    {
        $this->_powerSource = $powerSource;
    }
    
    public function play()
    {
        // Call upon $this->_powerSource->getPower()
        // Feed that power into the various electrical 
        // components of the radio and push the sound
        // out through the speakers.
    }
}

The idea is that by clearly defining the responsibilities, we can create independent object that fulfill those responsibilities. Even better, by defining interfaces, we can set up a contract for what a particular consumer expects his dependencies to be able to do for him.

So, who cares? Unit testing cares.

Suppose you are a company that makes radios. You hire the best radio engineers and work out all the details for what makes a radio great. Maybe you have amazing noise-reduction algorithms that filter out static. Maybe your radios have balance and equalizer controls to allow the user to tweak the sound he gets out of your box. Maybe your radios are super efficient so that they pull less power from the power source, allowing them to play longer before recharge. Or maybe you simply put them in colorful plastic shells featuring photos of some random pop star.

The point is that your expertise is in the areas highlighted above. You make no representation to be experts in power generation; you are a power consumer. The quality of your work can only be fairly judged when the power source functions properly. Hey, man, if the power source tanks, then all bets are off, right?

So as part of your manufacturing process, you do a whole bunch of unit-testing on your radios using a “mock” power source, a power source that definitely functions correctly. This approach – explicitly defining and passing dependencies, combined with supplying mock dependencies during unit testing – clearly defines responsibilities and allows you to focus on fulfilling yours without worrying that the problem lies in someone else’s area of responsibility.

What’s the downside?

Well, creating objects is now a bit of a pain the neck. Consider what is required now just to play a radio.

$gerbils = new GerbilCollection();  // guess we need a Gerbil class and a GerbilCollection class, too
$powerSource = new PowerSourceGerbils($gerbils);
$radio = new Radio($powerSource);
$radio->play();

So, every time I want to play a radio, I need to construct a power source (which might have its own dependencies, like the gerbils in this case), feed that power source into the radio, and then hit the play button.

I gotta do all these steps just to play a freaking radio? Can’t I do the radio setup once – create and plug in the power source – and then when I want to listen to some music, all I have to do is hit play?

I will address this in the next post: Poor Man’s Dependency Injection using Zend Framework.

Unit Testing for Placeholder-based View-helpers in Zend Framework

| Comments

Just got bitten by an interesting little issue.

I have a Zend Framework view-helper that I use to add a CSS class to an HTML <body> tag. Usage in a view-script is:

$this->bodyTag()->addClass('someclass');

Then in a layout, I’d output it using:

<?= $this->bodyTag() ?>

The class itself is very simple:

/**
 * A body tag
 *
 * @author David Weinraub <david@papayasoft.com>
 */
class PapayaSoft_Zend_View_Helper_BodyTag extends Zend_View_Helper_Placeholder_Container_Standalone
{
    public function bodyTag()
    {
        return $this;
    }

    public function toString()
    {
        $tag = array();
        $tag[] = '<body';

        $storage = $this->getContainer();

        if (count($storage) > 0){
            $classes = array();
            foreach ($storage as $class){
                $classes[] = $class;
            }
            $tag[] = sprintf(' class="%s"', implode(' ', $classes));
        }
        $tag[] = '>';
        return implode('', $tag);
    }

    public function addClass($class)
    {
        $this->getContainer()->append($class);
        return $this;
    }
}

I’ve begun moving this kind of stuff out into my own library, which I will manage in its own project under source control. I can then import it into multiple projects, just as I would with the libs for Zend or Doctrine or HTML Purifier.

Consequently, it’s now time – actually long past-due – to really get into the discipline of unit-testing. A simple class like this seems a decent place to start.

Unit-tests for the BodyTag class looked something like this:

/**
 * Test BodyTag class
 *
 * @group Zend_View_Helper
 * @author David Weinraub <david@papayasoft.com>
 */
class PapayaSoft_Zend_View_Helper_BodyTagTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var PapayaSoft_Zend_View_Helper_BodyTag
     */
    private $_bodyTag;

    public function setUp()
    {
        $this->_bodyTag = new PapayaSoft_Zend_View_Helper_BodyTag();
    }

    public function tearDown()
    {
        unset($this->_bodyTag);
    }

    public function testRenderOnNoAddedClasses()
    {
        $this->assertEquals('<body>', (string) $this->_bodyTag);
    }

    public function testRenderOnSingleAddedClass()
    {
        $this->_bodyTag->addClass('myclass');
        $this->assertEquals('<body class="myclass">', (string) $this->_bodyTag);
    }
    
    public function testRenderOnMultipleAddedClasses()
    {
        $this->_bodyTag = new PapayaSoft_Zend_View_Helper_BodyTag();
        $this->_bodyTag->addClass('someclass')->addClass('anotherclass');
        $this->assertEquals('<body class="someclass anotherclass"<', (string) $this->_bodyTag);
    }
}

Pretty straightforward. Or so I thought.

The last test failed, reporting the following:

BodyTagTest::testRenderOnMultipleAddedClasses()
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-<body class="someclass anotherclass">
+<body class="myclass someclass anotherclass">
It seemed as if result of running the penultimate method testRenderOnSingleAddedClass() was still in effect when testRenderOnMultipleAddedClasses() started. When the testRenderOnSingleAddedClass() method is removed, the testRenderOnMultipleAddedClasses() passes.

What’s going on here? The whole point of tearDown() and setUp() is to reset the test environment to a clean state, in this case by unsetting and re-instantiating the $_bodyTag member variable.

Well, the whole key here turns out to be state of the system. It’s not sufficient to simply reset the object in the member variable if it has made other changes to the state of the system. Sort of like selling the cow that crapped in your living room, but forgetting to clean up the mess he made. And that’s actually what appears to be happening.

The framework’s own unit test for Zend_View_Helper_HeadTitle, another Zend_View_Helper_Placeholder_Container_Standalone-extended class, offers some hint of this. The setUp() method is as follows:

/**
     * Sets up the fixture, for example, open a network connection.
     * This method is called before a test is executed.
     *
     * @return void
     */
    public function setUp()
    {
        $regKey = Zend_View_Helper_Placeholder_Registry::REGISTRY_KEY;
        if (Zend_Registry::isRegistered($regKey)) {
            $registry = Zend_Registry::getInstance();
            unset($registry[$regKey]);
        }
        $this->basePath = dirname(__FILE__) . '/_files/modules';
        $this->helper = new Zend_View_Helper_HeadTitle();
    }

So there is some Zend_Registry stuff in there that needs to be cleared, as well. Adding the registry-clearing code from the ZF unit-test into my own solved the problem.

Live and learn.

CRISP-y Goodness: Tracking Phuket Internet Speeds

| Comments

I am pleased to report that we have launched the new version of CRISP – Customers Reporting Internet Speeds in Phuket.

For some years, well-known computer columnist and baker Woody Leonhard (see AskWoody.com for his opinions on Windows patches or his columns in the Windows Secrets Newsletter, or his various Windows for Dummies books, not to mention his bakery business and his Phuket Sandwich Shoppes) has led a group of Phuket internet users in running speed tests on their internet connections and storing this data in an app developed and hosted by Henry Habermacher. The data was freely available as a CSV download to anyone who wanted to perform their own analysis on it.

Woody’s prime motivations were to provide Phuket internet users with real usage data on which to base their ISP choices and to clearly demonstrate the significant discrepancy between speeds advertised by ISP’s in Phuket and those that are actually delivered.

As of this writing, the db has over 15,000 speed reports dating back to 2008.

Henry was unable to host it going forward, so we needed to move it to a new home. But rather than simply migrate, we decided to do a rewrite in PHP and I got the call. Using a design by Seth Bareiss, my re-implementation is built on Zend Framework and the Doctrine 1 ORM. Relative to the previous version, it features some enhanced searching and user management, including registration and profile management.

If you are a Phuket-based internet user, come on over, register, and start contributing to the tracking effort.

http://www.khunwoody.com/phuket-internet-speed/

Greeting

| Comments

$papayasoft->wishesYou(array(
    new Christmas('merry'),
    new Year(array('happy', 'healthy', 'prosperous')),
));
$this->assert($papayasoft->isGeek());

Zend Framework Default Routing for Hyphenated and camelCase URL’s

| Comments

Using the default routing in Zend Framework (v1.x), I always forget how certain URL patterns map to action and view-script names. So just a quick post, mostly for myself, to record them here.

URL: mycontroller/test-me
Controller: mycontroller
Action: testMe
Script: test-me.phtml

URL: mycontroller/testMe
Controller: mycontroller
Action: testme
Script: test-me.phtml

That’s it!

Naming Conventions for Database Tables and Fields

| Comments

@JeremyKendall recently asked a great question on Twitter:

Do you have a DB naming convention? camelCase? under_scores? Singular or plural table names? I can never settle on anything.

He got some great answers. Since I will certainly need to reference these opinions at some later date – and Twitter will not keep the history forever – I am recording them here.

@konrness
I find it’s easier to follow my PHP code’s naming convention, so: camelCase for table names and columns. Under_score for DBs. Oh yeah, I usually do plural table names.

@stuardo_str
namespaced_under_scored

@cancehgarcia
i once read that “best practice” is singular and underscores. but as long as you’re consistent in the db, you should be good.

@cryptographite
CamelCase (ucfirst) for tables, and pre_desc for columns. User.u_id, UserProperties.up_value… It’s not perfect but it works

@calevans
single table names, camleCase attributes and PK is always id

@maphpia
namespaced_underscore_name, singular, and ‘id’ as PK

@guice
for us; id is always tablename_id to avoid name conflicts between joins. We use underscore (oracle). Singular names.

@akrabat
Plural table names; lowercase, underscore separated field names; PK is always id.

@avalanche123
lowercase underscore plural table names, id is the PK, _id is the FK to table name

@h (which is an awesome Twitter handle)
Singular Table names, first char upper case. Allows you to create models that match exactly.

@tommygeorge
Depends on the project, but I hate camelcase, and if I’m doing models/objects, I generally do plurals for table names.

@brodrigu
plural under_scores ftw!

I actually chimed in with my own support for @avalanche123′s suggestion: lowercase underscore plural table names, id is the PK, _id is the FK to table name. Semantically, I find this compelling since you end up with SQL queries of like “SELECT * FROM users” which reads better to my eye than “SELECT * FROM user”.

The only downside to this is that dealing with irregular plurals can sometimes be a pain. Consider a table containing properties. As noted above, I prefer the semantics that follow from calling that table “properties”. But a convention for a FK into that table “<singular_table_name>_id” would yield a field named “property_id”. The disconnect between the singular and plural can sometimes be problematic. Sure, there are Inflector classes (like this one) that know enough about English pluralization rules and their exceptions to do the mapping, but it’s one more hassle. So there are times when I bite the bullet, abandon the superior semantics, and simply hold my nose and go with singular table names.

What are your preferences and rationale?

Cheers!

Siam Real Estate – Redesigned

| Comments

Just completed a redesign for Siam Real Estate, specializing in Phuket villa rentals and property sales.

The graphic design – including much of the markup and CSS – was done by Blue D.Zine here in Phuket.

Much of the front-end has been redeveloped, including new property-renderers. New features include:

  • Improved site navigation
  • Map-based criteria selection for property searching
  • Google maps for property locations
  • Owner self-add of properties

Also included are many performance optimizations and code-refactoring, both on the server-side and on the client-side.

Check out the complete site at: http://www.siamrealestate.com/

Gotcha – SQL Count() Query With LIMIT Clause

| Comments

Bumped into an interesting feature today. Well, whether it’s a feature or a gotcha appears to be in the eye of the beholder. And, I’ll tell ya, for this particular beholder, it was a gotcha.

I’ve got some code that builds a SQL query from a variable set of parameters. Most parameters are involved with building a dynamic WHERE clause. Other parameters are for pagination, setting a LIMIT clause on the query that eventually gets built. Another parameter is whether to make the query a COUNT() query or whether to actually pull rows from the db.

In the case where I build a COUNT() query, I was carelessly allowing a zero-based LIMIT clause – something like LIMIT 0,10 – to be appended to the query. No sweat, I figured, since I really only need the single-row containing the count I am requesting.

However, it turns out that this LIMIT was actually be applied *before* the COUNT()-ing, not after. So, my COUNT() was completely wrong, often returning 0.

There’s an hour of my life – spent in furious frustration – that I’ll never get back.

Onward!

Martin Gardner and Me

| Comments

martin_gardnerjpeg

I just read on AskWoody.com that Martin Gardner, the longtime author of the Scientific American column “Mathematical Games”, has died at the age of 95.

I am a bit surprised at how it is affecting me.

As a kid, I loved his column. I took pride in solving the puzzles. The activity taught me focus and concentration. It taught me problem solving. It taught me to think.

But most of all, it gave me my first exposure to the notions of logical incompleteness and unequal infinities.

With the naivety of youth, I believed that the universe was black and white. Statements were either true or false, and essentially all knowledge (using a sufficiently large book) could be expressed in language.

Further, infinity was infinity. the biggest thing there is. Nothing bigger than that, despite the common schoolyard escalation of taunts:

“You have cooties.”

“Well, you have cooties plus one.”

“You have cooties plus two.”

“Oh, yeah? You have cooties times one hundred”, cleverly upping the stakes by switching from simple addition to the more powerful multiplication.

“Well, you have cooties times infinity!”

“Oh yeah? You have cooties times infinity-plus-one.”

… and so on.

Still, infinity came to connote – at least to me – a sense of maximality, the sum totality of everything, of the universe. Of The Universe.

Martin Gardner’s column exposed me to Gödel’s Incompleteness Theorem and Cantor’s Theorem about cardinalities.

Gödel’s Incompleteness Theorem states that no consistent system of axioms whose theorems can be listed by an “effective procedure” (essentially, a computer program) is capable of proving all facts about the natural numbers. For any such system, there will always be statements about the natural numbers that are true, but that are unprovable within the system.

This has profound implications for reductionist attempts – to which I was inherently attracted in my youth – to reduce all knowledge to a set of indisputable, logically consistent axioms and deduction mechanisms. Essentially, if you depend upon axiomatic logic and consistency, you are limited in what you can prove. There exist statements that are expressible within the given system, but whose truth or falsity are not provable using only the tools of the system.

This result undermines language as the sole medium of defining knowledge, since language will always produce statements that are outside the reach of provable truth or falsity. It casts doubt on the binary notion of truth, opening up the mathematical discipline of fuzzy logic.

It even strikes closer to home for me, contradicting something my father explicitly told me when I was a child, one of his core beliefs: “If you can’t describe what you know, then you do not know it.”

429px-diagonal_argument_2svg

Gödel’s method of proof was his famous Diagonal Lemma, in which he starts with the logical system, its symbols and its constructs, and then proceeds to build an example of his elusive unprovable statement.

Using a similar diagonalization technique, Georg Cantor was able to demonstrate that the infinity that represents the natural numbers (1, 2, 3, 4…) was a “lesser” infinity than the infinity representing the real numbers (the numbers that represent measurable distances on a line), the former being a “countable” infinity and the latter an “uncountable” one. Further, he proved that there are ever-higher, unlimited levels of “greater” infinities, all of which are “uncountable”.

All this just blew me away. It fired my imagination. It opened my mind to an extraordinary universe, to universes, to multiverses. It inspired me to embrace the beauty of abstraction. It led me to study mathematics, first as an undergraduate, then as a graduate student, through to my doctorate degree.

Abstraction, modeling, language, truth, philosophy, knowledge, infinities, alternate possibilities, universes.

For me, it all started with Martin Gardner. My life would not be the same without the contribution that he made to it. I’m saddened at the news of his passing, but grateful for the door he opened for me.