Have you every considered how many times “Hello World” has been re-implemented? It’s the ultimate missed opportunity for re-use! A cautionary tale about design patterns...

Design Patterns Berserk

1)

The idea that design patterns can be abused and over-used is not a new one. (See DesignPatternsConsideredHarmful.) What I have here is an example. I’ve implemented a “Hello world” command-line script, using about 160 lines of object-oriented PHP 5 code. The principle has been to add design patterns for no good reason.

It does a little bit more than just print “Hello world”. It will print it in two alternative ways and echo some addtional text you input. The equivalent plain script would be about 4 or 5 lines. Maybe it needs a use case diagram?

The program has several design patterns including Model-View-Controller, Observer, Strategy, Decorator, Factory Method and Facade.

It would be interesting to try to squeeze all the Gang of Four patterns into it, and I’m sure I could bring it up to 1000 lines, but I have other things to do.

Some things I noticed as I was writing it:

  • How impressive it seemed, considering its worthlessness.
  • How satisfying it was to get the mechanics to work, futile though they may be.
  • How, as the program’s complexity grows, more opportunities present themselves for adding still more useless design patterns.

All of these observations are apalling when seen in a larger perspective. The example seems to support the notion that design patterns can cause problems which are easy to get into, hard to diagnose and hard to resolve.

If this code had been slightly more sophisticated and less obviously meaningless, it might be quite hard to refactor. It’s like a labyrinth. The smell of decay from dead design patterns is not a very distinct one.

And the program works. In spite of its deadness, it executes and produces a result. You might say it’s like one of those severed frog’s legs that twitch when you apply current.

Contrast it with the typical hacker product. It may not be a nice place to visit, but there is an emergency exit. Simple, well-known refactorings make the job of improving this type of code relatively straightforward. (Though, if you really want to prevent refactoring, one-letter variable names and a liberal use of global variables could be effective.)

<?php
/********************************************************************
Model-View-Controller implementation according to POSA
(Pattern-Oriented Software Architecture
  http://www.hillside.net/patterns/books/Siemens/book.html)
********************************************************************/
 
class HelloWorldController {
    private $model;
    function __construct($model) {
        $this->model = $model;
    }
 
    function handleEvent($args) {
        $this->model->setStrategy($args[2]);
        $this->model->addText($args[1]);
    }
}
 
 
class HelloWorldModel {
    private $text;
    private $observers = array();
    private $strategy;
    
    function attach($observer) {
        $this->observers[] = $observer;
    }
 
    function getData() {
        $facade = new HelloWorldFacade($this->strategy);
        return $facade->getHelloWorld().$this->text."\n";
    }
 
    function addText($text='') {
        $this->text = $text;
        $this->notify();
    }
 
    function setStrategy($strategy) {
        $this->strategy = $strategy;
    }
    
    function notify() {
        foreach ($this->observers as $observer) {
            $observer->update();
        }
    }
}
 
class HelloWorldView {
    private $model;
 
    function initialize($model) {
        $this->model = $model;
        $model->attach($this);
        return $this->makeController();
    }
 
    function makeController() {
        return new HelloWorldController($this->model);
    }
 
    function update() {
        $this->display();
    }
 
    function display() {
        echo $this->model->getData();
    }
}
 
 
/*********************************************************************
"Business logic"
********************************************************************/
 
class HelloWorld {
   function execute() {
       return "Hello world";
   }
}
 
class HelloWorldDecorator {
   private $helloworld;
   function __construct($helloworld) {
       $this->helloworld = $helloworld;
   }
 
   function execute() {
       return $this->helloworld->execute();
   }
}
 
abstract class HelloWorldEmphasisStrategy {
    abstract function emphasize($string);
}
 
class HelloWorldBangEmphasisStrategy extends HelloWorldEmphasisStrategy {
    function emphasize($string) {
       return $string."!";
    }
}
 
class HelloWorldRepetitionEmphasisStrategy extends HelloWorldEmphasisStrategy {
    function emphasize($string) {
       return $string." and ".$string." again";
    }
}
 
class HelloWorldEmphasizer extends HelloWorldDecorator {
   private $strategy;
   function HelloWorldEmphasizer($helloworld,$strategy) {
       $this->strategy = $strategy;
       parent::__construct($helloworld);
   }
 
   function execute() {
       $string = parent::execute();
       return $this->strategy->emphasize($string);
   }
}
 
class HelloWorldStrategyFactory {
    static function make($type) {
        if ($type == 'repetition') return self::makeRepetitionStrategy();
        return self::makeBangStrategy();
    }
 
    static function makeBangStrategy() {
        return new HelloWorldBangEmphasisStrategy;
    }
    static function makeRepetitionStrategy() {
        return new HelloWorldRepetitionEmphasisStrategy;
    }
}
 
class HelloWorldFormatter extends HelloWorldDecorator {
   function execute() {
       $string = parent::execute();
       return $string."\n";
   }
}
 
class HelloWorldFacade {
    private $strategy;
    function __construct($strategyType) {
        $this->strategy = HelloWorldStrategyFactory::make($strategyType);
    }
 
    function getHelloWorld() {
        $formatter = new HelloWorldFormatter(
                new HelloWorldEmphasizer(
                    new HelloWorld,$this->strategy));
        return $formatter->execute();
    }
}
 
$model = new HelloWorldModel;
$view = new HelloWorldView;
$controller = $view->initialize($model);
$controller->handleEvent($_SERVER['argv']);
 
?>

A challenge: the HelloWorldFormatter class currently only supports formatting “Hello World” for the command line. This clearly needs to be extended to support HTML, like “Hello World&lt;br&gt;”. And if you’re supporting HTML, what about XHTML? “Hello World&lt;br /&gt;” is a must. Pick your patterns...

1) The author of this article, Dagfinn Reiers&oslash;l, has been designing and developing Web applications, Web content mining software, Web programming tools and text analysis programs in PHP and Perl since 1997. He also has a long history as a technical writer mostly of software manuals.

design/hello_world_in_patterns.txt · Last modified: 2005/10/15 21:47