Chronicles of a build - the theme framework 12

The global/static evil part of the abstract factory

In my earlier post I wrote my own delusional user story asking for the possibility to write something like

Controllers::ControllerName()->show();

but that would probably involve using a lot of static/global variables in the Controllers class to keep track of all the controllers around the installation and that would be evil in object-oriented and test-driven development perspective.
I could very well point to something like

// file index.php

... some other code here...

\SomeNamespace\SomePluginOrTheme\Views::create('someView')->show();

... some other code here...

which is as evil using static methods and some static variables. But I can cope with it for the love of clarity and in an scale of evilness would score little.

Maybe I’m decided?

The change of plans I’m having about this framework is amazing in a disturbing way but I think the call above, the second one, might actually be worth exploring in its ablative nature: reading it later I might be able to understand I’m asking SomePluginOrTheme to show SomeView and, even ignoring the inner workings, I think it makes code readability on pair with something like

somePluginOrTheme_show_someView();

which would be the standard call to a prefixed globally defined function in WordPress.
If the plugin or theme took care of registering the autoload path with the SPL autoloader class I’ve blatantly copied from GitHub user jwage’s repository and included, crediting, in my code then the call should succeed.

Dissecting my dream framework call

Left to right in the above call, the namespaced one, I can see that

  • \SomeNamespace\SomePluginOrTheme\Views is a static factory class extending the static <code\TAD\Helpers\AbstractFactory class and will take care to create and return an instace of…
  • some View class that will then probably include a view, some as-plain-HTML-as-possible template file, and echo it to the page via the show method.

Laying the factory base

The \SomeNamespace\SomePluginOrTheme\Views factory class is clearly defined in the plugin or theme folder: leveraging this fact I can make my future work of defining an extending factory class as little tedious as possible moving all the hassle of finding components and preparing them for autoloading in a base Views class. The class responsibility is simply to contextually create and return an instance of the requested view class.
Since the base AbstractFactory class I’ve implemented in the libraries reads like

<?php
namespace TAD\Helpers;
abstract class AbstractFactory{
    static public function create($args = null){
        static::init($args);
        return static::createInstance($args);
    }
    abstract static protected function init($args = null);
    abstract static protected function createInstance($args = null);
}

I need to implement the createInstance and init static methods and find the components around the factory class itself. Since there will be no tests guiding me I’d like to keep this evil non-testable code as little as possible.

An evil factory

The “evil” joke has made its time but here it is the once again abstract factory class that’s expected to be extended by a concrete factory class in any theme or plugin implementation. The class simply removes the chore of nosing around for the framework components leaving the extending class the responsibility to deal with business logic that might be involved into choosing which view to display

<?php
namespace TAD\MVC\Factories;
abstract class AbstractViewFactory extends \TAD\Helpers\AbstractFactory {
    static protected $viewsFilePath;
    abstract static protected function createInstance($args = null);
    static protected function init($args = null){
        // get the file the extending class was defined into
        $className = get_called_class();
        $classInfo = new \ReflectionClass($className);
        $classFile = $classInfo->getFileName();
        $filePathResolver = new TAD\MVC\Helpers\FilePathResolver($classFile);
        // set the views folder
        static::$viewsFilePath = $filePathResolver->getViewsPath();
        // get the extending class namespace
        $ns = $classInfo->get_namespace_name();
        // register the view components for autoloading
        $classLoader = new \jwage\SplClassLoader($ns, dirname($classFile));
        $classLoader->register();
    }
}

and an extending class might be very few lines

<?php
namespace SomeNamespace\SomePluginOrTheme;
class Views extends \TAD\MVC\Factories\AbstractViewFactory{
    static public function createInstance($arg = null){
        return new \SomeNamespace\SomePluginOrTheme\SomeView();
    }
}