Resolve Promises Using Composite Pattern

When creating an object oriented CRUD operation, often you’ll have a case where an object will have children that are independently managed resources. Each child is simply associated to the parent, but when editing the entire object it’s likely that a better guest experience calls for one screen, rather than many.  The editor shouldn’t have to care if they’re updating one or many objects at once.

If the parent is dependent on the children objects to complete their operations before the parent can complete theirs, then you’ll have to create a dependency tree.  Each child would likely have other dependents, and would thusly need to wait until their dependencies are saved before continuing up the tree.

We cannot simply start with the last child process and work our way back up, this could result in orphaning the children that are in the outer-most parallel branches of the tree. We’ll need to begin from the parent, and recursively work our way down the branches until we’ve resolved each child’s process.  Using the composite pattern, we can treat each child the same way as a single instance of an object, and in this case each one is an ngResource.

app.service 'resourceService', ['$resource', '$rootScope', '$q', ($resource, $rootScope, $q)->
    $rootScope.resources = {}
    resourceService      = 
        newResource : (tag, url, paramDefaults = {}, actions = {}, options = {})->
            if !$rootScope.resources[tag]
                actions = _.extend actions,
                    update : 
                        method : 'PUT'

                resource = $resource(url, paramDefaults, actions, options)
                $rootScope.resources[tag] = resourceService.extendResource resource
            $rootScope.resources[tag]
    
        autoQuery : (tag, url, paramDefaults = {}, actions = {}, options = {})->
            resourceService.newResource(tag, url, paramDefaults, actions, options).query()

        getResource : (tag)->
            $rootScope.resources[tag]

        convertToResource : (obj, resource)->
            if Array.isArray obj
                obj = (item = resourceService.convertToResource item, resource for item in obj)
            else
                proto  = Object.create resource.prototype
                obj    = _.extend proto, obj
                obj    = resourceService.extendResource obj

            obj

        extendResource : (resource)->
            if Array.isArray resource
                resource = (r = resourceService.extendResource r for r in resource)
            else
                # Since JS won't do this for me, let's create a hash for each resource.
                resource._hash = Math.random().toString(36).substring(7)

                # Create a child for this resource
                resource._children = []

                resource.getResourceId = ()->
                    @_hash

                resource.addChild = (child)->
                    # locate the hash and remove it if applicable
                    hash = child.getResourceId()
                    @_children = _.reject @_children, (child)-> return child.id == hash
                    @_children.push
                        id : hash
                        resource : child

                resource.setCallbacks = (@successCallback, @errorCallback, @notifyCallback)->
                    resource
                
                resource.resolve = ()->
                    children = @_children
                    promises = []
                    promises.push $q.when child.resource.resolve() for child in children
                    combined = $q.all promises
                    parent = @
                    combined.then(()-> parent._children = [])
                        .then(@successCallback, @errorCallback, @notifyCallback)

            # return the resource
            resource

    resourceService
]

 

Advertisements

PHPUnit – Testing Interface Injection Mocks

I hate PHPUnit… ok, maybe not hate, but I don’t like writing more code to test the code I originally wrote.  Plus when the amount of code required for the test is usually twice as much, that just seems a bit inefficient.

Digressing a bit, there are amazing benefits to testing your code! By simply writing unit tests you will ensure that you can catch errors early, refactoring becomes easier, and much more.  I like to apply a bit of Grey Box Testing methodology to Unit Testing.  I think that testing too much of the internal workings of the function or application will result in a full refactor of the unit tests when the code is refactored.  Thus rendering the unit tests useless.

The best way to ensure that you can meet your code standards, catch problems early, and be agnostic to refactoring, is by testing the input and output of the methods.  You will obviously try to test each possible outcome, so you’ll have to know the  internal working of each method a bit more.

Zend Framework 2, among others, implements a dependency injection system.  While this is very beneficial for writing code,  it’s great for testing as well, as long as your tests don’t have to inject every single dependency each time.  That would be too time consuming and likely a pain in the ass as well.  When things are too tedious, or difficult, most developers will tend to make it a “ToDo” and move on.  With ZF2, there’s an easy setup for interface dependency injection.  We can apply this same configuration to PHPUnit:

Gist url here

<?php
use PHPUnit_Framework_TestCase as TestCase,
    PHPUnit_Framework_MockObject_MockBuilder as MockBuilder,
    PHPUnit_Framework_MockObject_MockObject as MockObject;

trait ZF2InterfaceInjectionTrait extends TestCase
{

    /**
     * Provides the default mocks for each of the interfaces defined in your test configuration
     * @param  String|Object $mock if provided a string, I will create the mock for you, if not, I will apply the mocks to the object provided.
     * @param  array  $args
     * @return Object
     */
    protected function interfaceAwareMock($mock, array $args = array())
    {
        $config    = InterfaceAwareMockBuilder::getConfig();
        $instance  = is_string($mock) ? $this->getMock($mock, $args) : $mock;
        if (isset($config['dependencies'])) {
            foreach ($config['dependencies']['interfaces'] as $interface => $invoke) {
                if ($instance instanceof $interface) {
                    $instance->$invoke['method']($this->getMockBuilder($invoke['invokable'])->disableOriginalConstructor()->getMock());
                }
            }
        }
        return $instance;
    }

    /**
     * Provides the default mocks for each of the interfaces defined in the test configuration
     * @param  String|Object $mock If this method is provided a string, it will create the mock, if not, it will apply the arguments to the provided mock.
     * @param  array  $args
     * @return Object
     */
    protected function interfaceAware($mock, array $args = array())
    {
        $instance  = is_string($mock) ? $this->getInterfaceAwareMockBuilder($mock)->setMethods($args)->disableOriginalConstructor() : $mock;
        return $instance;
    }    

    /**
     * Returns a builder object to create mock objects using a fluent interface.
     *
     * @param  string $className
     * @return PHPUnit_Framework_MockObject_MockBuilder
     * @since  Method available since Release 3.5.0
     */
    public function getInterfaceAwareMockBuilder($className)
    {
        return new InterfaceAwareMockBuilder(
          $this, $className
        );
    }

    /**
     * Shorthand use for simple mock writing!
     * example use:
     *    $this->testObj = $this->interfaceAware('MyServiceMyClass', array('__construct'));
     *    $this->mock    = $this->getMockBuilder('MyServiceMyClassOtherMock')->disableOriginalConstructor();

     *    $mock          = $this->mock->getMock();
     *
     *    // Interface aware mocks will support the getMockSetup as a chain
     *    $localTest = $this->testObj->getMockSetup(array(
     *        'methodIAmOverwriting' => array(
     *            'expects' => $this->once(),
     *            'will' => $this->returnValue($mock)
     *        ),
     *    ));

     *    // Simple use case
     *    $this->getMockSetup($this->mock, array(
     *        'save' => array(
     *            'expects' => $this->exactly(1),
     *            'with' => $otherMock
     *        ),
     *    ));
     *
     * @param PHPUnit_Framework_MockObject_MockObject $mock
     * @param array $methods
     */
    public function getMockSetup($mock, array $methods = array())
    {
        if ($mock instanceof MockBuilder) {
            $mock = $mock->setMethods(array_keys($methods))->getMock();            
        }
        foreach ($methods as $method => $definition){
            $chain = $mock->expects($definition['expects'])->method($method);
            unset($definition['expects']);
            foreach ($definition as $key => $value){
                if (is_array($value)) {
                    call_user_func_array(array($chain, $key), $value);
                } else {
                    call_user_func(array($chain, $key), $value);
                }
            }
        }
        return $mock;
    }
}

class InterfaceAwareMockBuilder extends MockBuilder
{
    public static function getConfig()
    {
        return array(
            'dependencies' => array(
                'interfaces' => array(
                    'SomeServiceServiceAwareInterface' => array(
                        'setMethod' => 'setService', 
                        'invokable' => 'SomeService'
                    ),
                ),
            ),
        );
    }

    public function getMock()
    {
        $instance  = parent::getMock();
        $config    = self::getConfig();
        if (isset($config['dependencies'])) {
            foreach ($config['dependencies']['interfaces'] as $interface => $invoke) {
                if ($instance instanceof $interface) {
                    $mock = $this->testCase->getMockBuilder($invoke['invokable'])->disableOriginalConstructor()->getMock();
                    $instance->$invoke['setMethod']($mock);
                }
            }
        }
        return $instance;
    }

    public function getMockSetup(array $methods = array())
    {
        return $this->testCase->getMockSetup($this, $methods);
    }
}

 

ZF2 – Dependency Injection

When using the service locator, you’ll find that interface injections are a common pattern applied.  The setup is simple, in your class you simply implement the existing interface injector:

namespace MyCacheService;

use ZendServiceManagerServiceLocatorAwareInterface,
    ZendServiceManagerServiceLocatorAwareTrait,
    MyCacheFlyWeightCacheAwareInterface,
    MyCacheFlyWeightCacheAwareTrait;

/**
 * Default strategy used to determine of an HTTP request can be cached
 */
class ExampleCanCacheStrategy extends DefaultCanCacheStrategy implements ServiceLocatorAwareInterface, FlyWeightCacheAwareInterface
{
    use ServiceLocatorAwareTrait, FlyWeightCacheAwareTrait;

    public function canCacheRequest(RequestInterface $request)
    {
        {...} // other code etc.
        $settings  = $this->getServiceLocator()->get('config');
        $path      = $request->getPath();
        $cacheable = $this->getFlyweightCache()->{function($path, $settings){
            foreach ($settings as $cacheableService) {
                if (preg_match('/' . $cacheableService['servicePath'] . '/', $path) === 1) {
                    return (bool) $cacheableService['cacheable'];
                }
            }
            return true;           
        }}($path, $settings);
        return $cacheable;
    }
}

I’ve used a trait to add in the additional interface requirements:

namespace MyCache;
use ZendCachePatternAbstractPattern;
trait FlyWeightCacheAwareTrait
{
    /**
     * @var AbstractPattern
     */
    protected $flyweightCache;

    /**
     * Sets the CacheAdapter for use within this interface
     * @param CacheAdapter $cacheAdapter
     */
    public function setFlyWeightCache(AbstractPattern $cachePattern)
    {
        $this->flyweightCache = $cachePattern;
    }

    /**
     * returns the cache adapter to the user.
     * @return CacheAdapter The current CacheAdapter
     */
    public function getFlyWeightCache()
    {
        return $this->flyweightCache;
    }
}

The interface is below:

namespace MyCache;
use ZendCachePatternAbstractPattern;
interface FlyWeightCacheAwareInterface
{
    /**
     * Sets the CacheAdapter for use within this interface
     * @param CacheAdapter $cacheAdapter
     */
    public function setFlyWeightCache(AbstractPattern $cachePattern);

    /**
     * returns the cache adapter to the user.
     * @return CacheAdapter The current CacheAdapter
     */
    public function getFlyWeightCache();
}

Once this is implemented you can create your dependencies and inject them into the instance that’s been created, or you can use the initializer injection system that’s automatically run when you generate an instance using the service locator.

namespace MyCache;

use ZendServiceManagerInitializerInterface,
    ZendServiceManagerServiceLocatorInterface,
    MyCacheFlyWeightCacheAwareInterface;

class CacheAwareInitializer implements InitializerInterface {
    public function initialize($instance, ServiceLocatorInterface $serviceLocator)
    {
        // HACK for View, Controller, AND Service!
        $sm = (method_exists($serviceLocator, 'getServiceLocator')) ? $serviceLocator->getServiceLocator() : $serviceLocator;
        {...} // Additional injection code

        if ($instance instanceof FlyWeightCacheAwareInterface) {
            $callbackCache = ZendCachePatternFactory::factory('callback', array('storage' => $sm->get('callbackCache')));
            $instance->setFlyWeightCache($callbackCache);
        }
    }
}

Any time you try to get an instance using the service locator, this function will run, and inject your dependency directly into your instance.

GitHub Enterprise Pull Request Notifier

Since I’m currently working in Github enterprise, I’ve modified the original code for the GitHub Pull Request Notifier to allow for GitHub Enterprise connections.

My current project is using git submodules to track multiple modules, and is getting increasingly larger all the time. I needed a way to have one location showing which pull requests I need to pay attention to.

https://github.com/donniewa/pull-request-notifier

 

ZF2 – Service Manager – Using factories in a controller

One of my pain points, was trying to call a factory from the controller using the magic __get method, whilst using an alias.

I had setup a service factory, called “pcms” that I wanted to call via the controller:

return array(
    'service_manager' => array(
        'factories' => array(
            'pcms' => function() {
                return new PCMSService(
                    PCMS_SITE_ID,
                    array( ... )
                );
            }
        ),
    ),
);

in my controller, I’d planned on using:

$this->pcms->{functionnamehere}(...);

If I had used an alias in my config, It wouldn’t work:

return array(
    'service_manager' => array(
        'factories' => array(
            'PCMSService' => function() {
                return new PCMSService(
                    PCMS_SITE_ID,
                    array( ... )
                );
            }
        ),
        'aliases' => array(
            'pcms' => 'PCMSService',
        ),
    ),
);

Forego the alias, and simply name the factory whatever you want.

ZF2 – Database Changes from ZF1

ZF2 has some big game changers for database connectivity.  The Zend_Db_Table is no longer, and has since been replaced by the new TableGateway.  What I’m finding so far is that the default database adapter is no longer used, or I’m unsure how to initialize it, so that you must pass the database adapter into each table you use.  This can get crazy, but if you develop a wrapper for your database connections it isn’t so bad.

// somewhere in your db model, which must implement ZendServiceManagerServiceManagerAwareInterface 
$this->adapter = $this->getServiceManager()->get('db');
$table  = new TableGateway("my_db_table", $this->adapter);

The database setup is similar to the original application.ini setup in ZF1:

<?php
// database loading informaiton
return array(
    'service_manager' => array(
        'factories' => array(
            'ZendDbAdapterAdapter' => 'ZendDbAdapterAdapterServiceFactory',
        ),
        'aliases' => array(
            'db' => 'ZendDbAdapterAdapter',
        ),
    ),
    'db' => array(
        'driver' => 'pdo',
        'pdodriver' => 'mysql',
        'host' => 'localhost',
        'database' => 'db_name',
        'username' => 'db_user',
        'password' => 'db_pass',
        'driver_options' => array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'"),
    ),
);

Another fun thing that I found was actually easier than in ZF1 was to switch databases while keeping the same exact credentials:

$serviceManager = $this->getServiceManager();
$databaseAdapter = $serviceManager->get('db');

$dbParams = $databaseAdapter->getDriver()->getConnection()->getConnectionParameters();
$dbParams['database'] = $siteDetail['database_location'];

/**
 * Edited 10/15 - found a defect with trying to set the connection parameters, 
 * found that it worked 100% of the time when you simply returned a new instance
 * of the adapter.
 */
return new Adapter($dbParams);

 

ZF2 – Configuration Merging

One big change in ZF2 is the complete change for inheritance with configuration files; Meaning it’s no longer supported.  This can be a difficult change to make from ZF1 especially if you’ve built any or all configurations in a way that does this type of inheritance.

There are solutions to helping you obtain environmental configuration setups but that will only get you a global config, with a simple localized override.  While I don’t completely agree with non-inherited configurations, I can see the benefits.  Loading a configuration and merging it is expensive, but nothing that can’t be cached.

ZF2 didn’t completely remove this logic, they’ve hidden it, here’s a way to merge an 2 existing configurations together:

{
    "_base" : {
        "label" : "base label",
        "properties" : {
            "i" : {
            }
        }
    },
    "attribute" : {
        "_extends" : "_base",
        "label" : "attribute label override."
    }    
}

 

use ZendConfigFactory;
use ZendStdlibArrayUtils;

public function loadConfig($type)
{
    $loadedConfig = Factory::fromFile('config/objects.json');
    $config = isset($loadedConfig->{$type}) ? $loadedConfig->{$type} : null;
    if (isset($config['_extends'])) {
        $configBase = $loadedConfig[$config['_extends']];
        $config = ArrayUtils::merge($configBase, $config);
    }

    return $config;
}

Using the ZF1 JSON variable “_extends” in your config you can see that there’s a one to one load of the configuration file and it’s extension.  This doesn’t recursively call the function but it could easily be updated to do that.  Once the config is generated, it should be cached and returned.  This operation can get expensive and may not hold up well to load.

ZF2 – Using Cache

One does not simply cache in ZF2. The best way I’ve found is to create a factory in the Service manager to use cache.

<?php
return array(
    'modules' => array(
        'Application',
        'Rest'
    ),
    'module_listener_options' => array(
        'config_cache_enabled' => false,
        'cache_dir' => 'data/cache',
        'config_glob_paths'    => array(
            'config/autoload/{,*.}{global,local}.php',
        ),
        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
    'service_manager' => array(
        'factories' => array(
            'ZendCacheStorageFactory' => function() {
                return ZendCacheStorageFactory::factory(
                    array(
                        'adapter' => array(
                            'name' => 'filesystem',
                            'options' => array(
                                'dirLevel' => 2,
                                'cacheDir' => 'data/cache',
                                'dirPermission' => 0755,
                                'filePermission' => 0666,
                                'namespaceSeparator' => '-db-'
                            ),
                        ),
                        'plugins' => array('serializer'),
                    )
                );
            }
        ),
        'aliases' => array(
            'cache' => 'ZendCacheStorageFactory',
        ),
    ),
);

Above is an example of my applicaiton.config.php file.  I’ve created a new StorageFactory object using the alias of “cache”.  This will allow me to create a service manager alias that I can then reference in my application.  The next step involves my controller and a class that is serviceManagerAware.

public function IndexAction()
{
        $this->assembler  = new Assembler($controller->getServiceLocator());
}

My Assembler class implements ServiceManagerAwareInterface and in the construct will simply set the service manager to the passed $sm parameter:

namespace ApplicationModelObj;

use ZendServiceManagerServiceManager;
use ZendServiceManagerServiceManagerAwareInterface;

class Assembler implements ServiceManagerAwareInterface
{
    /**
     * Creates the configuration for the service assembler
     * @param ZendServiceManagerServiceManager $request
     */
    public function __construct(ServiceManager $sm)
    {
        $this->setServiceManager($sm);
        $this->cache = $this->getServiceManager()->get('cache');
    }

    public function setServiceManager(ServiceManager $sm)
    {
        $this->_sm = $sm;
    }

    public function getServiceManager()
    {
        return $this->_sm;
    }
}

Using the cache is slightly different than ZF1.  You no longer can save tags with your cache.

# Simply return a key from the cache
$result = $this->cache->getItem($key);
if (!empty($result)) {
    return $result;
}

# Store a result into cache using the key, $saved will result in a boolean value.
$saved = $this->cache->addItem($key, $value);

# Tag the key when saving
$this->cache->setTags($key, array('tag1', 'tag2'));

 

ZF2 – Service Manager

The Service Manager for ZF2 is the new Zend_Registry from ZF1.  This class will allow you to create factories on the fly, but more importantly, will allow you to inject simple setups into your application.  Databases, and Cache are the two examples that I’ll use to show the examples of how easy it will be to access these objects from everywhere in your application.

<?php
return array(
    'modules' => array(
        'Application',
        'Rest'
    ),
    'module_listener_options' => array(
        'config_cache_enabled' => false,
        'cache_dir' => 'data/cache',
        'config_glob_paths'    => array(
            'config/autoload/{,*.}{global,local}.php',
        ),
        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
    'service_manager' => array(
        'factories' => array(
            'ZendCacheStorageFactory' => function() {
                return ZendCacheStorageFactory::factory(
                    array(
                        'adapter' => array( 
                            'name' => 'filesystem', 
                            'options' => array( 
                                'dirLevel' => 2, 
                                'cacheDir' => 'data/cache',
                                'dirPermission' => 0755,
                                'filePermission' => 0666,
                                'namespaceSeparator' => '-db-'
                            ), 
                        ), 
                        'plugins' => array('serializer'), 
                    )
                );
            }
        ),
        'aliases' => array(
            'cache' => 'ZendCacheStorageFactory',
        ),
    ),  
);

Notice that there’s a Closure function for the factory.  If you’ve run into the error that the class you’re trying to create is not a valid ZendServiceManagerAbstractFactoryInterface, then you simply have to wrap the object you’re going to return in a Closure function to fix.