Clean Code – UpCloo Web Framework

24 January 2014

 

I have written about the UpCloo Web Framework few months ago (click here) and, as the README.md says, the micro-framework (App.php) is quite a bit messy. At this time is important, before starting add new features, clean the code base a little bit and move on with the microframework. In order to do this I want to apply the Boy Scout Rule: “Always leave the campground cleaner than you found it”. First of all I ran all tests and I discover that App.php is poorly covered (only 46%) and many key features not at all (at commit c70375e6).

Its time to cover much more than this in order to change the code base. I see that the “bootstrap” operation is completely uncovered and the same is valid for listener registration and other important things. Its time to cover the application dispatching.

In commit a3fb91b I have added tests in order to cover all aspects of the framework. After that I have removed functional testing through Selenium that are useless at this time.

One of the first things that I don’t like is: all statements that checks ifs a particular configuration section exists or not.

<?php
private function registerRouter() {
    if (!array_key_exists("router", $this->conf)) {
        $this->conf["router"] = array();
    }
    ...
}

For that reason I decided to start the framework with base configuration and users can override this one through the constructor. In commit e4ad8459 I made this change, where in practice I get a general app configuration at the beginning:

<?php
class App
    ...

    public function __construct(array $configs)
    {
        $conf = $this->getAnEmptyConf();
        foreach ($configs as $confFile) {
            $conf = array_replace_recursive($conf, $confFile);
        }
        $this->conf = $conf;
    }

    private function getAnEmptyConf()
    {
        return [
            "router" => [],
            "services" => [
                "invokables" => [
                    "UpCloo\\Renderer\\Jsonp" => "UpCloo\\Renderer\\Jsonp"
                ],
                "aliases" => [
                    "renderer" => "UpCloo\\Renderer\\Jsonp",
                ]
            ],
            "listeners" => []
        ];
    }
    ...
}

I continued on this way until I found that the code base is quite clear, i think, at the commit: acd5e6c50de and I have tagged this release as 0.0.8.

Now, In my opinion the App.php has at least 3 responsibilities: configuration, bootstrap (setup) and run (dispatch) requests. I want to separate responsibilities in three different sections.

I separated key features in separate objects: ArrayProcessor to merge configuration together, Boot to setup the application and the last one the Engine class in order to run the application. I work on this in a separate branch (from 6d695f684 to 87ad7e73). In this process I introduced a single BC, the app configuration process. At the beginning is something like:

<?php
$app = new \UpCloo\App([
    include __DIR__ . '/config/conf1.php',
    include __DIR__ . '/config/conf1.prod.php',
]);

$app->run();

I changed this into this:

<?php
$config = new UpCloo\App\Config\ArrayProcessor();
$config->appendConfig(include __DIR__ . '/configs/conf1.php');
$config->appendConfig(include __DIR__ . '/configs/conf1.prod.php');

$boot = new UpCloo\App\Boot($configs);

$engine = new \UpCloo\App\Engine();

$app = new UpCloo\App($engine, $boot);
$app->run();

It is much verbose, but in this way I left open the possibility to change the engine (event driven) with a new implementation, the bootstrap section with a different boot and also a different configuration processor.