Skip to content

Commit

Permalink
more samples
Browse files Browse the repository at this point in the history
  • Loading branch information
ejsmont-artur committed Sep 24, 2013
1 parent 703d5bc commit 1bc0582
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 10 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,41 @@ Almost every class here uses dependency injection as it is one of the most funda

All the classes depend on interfaces. This way implementations can be swapped out at any time.

# Desing Patterns and electricity ;)

I had this idea recently that some of the design patterns translate nicely into the way our power supplies work.

## Proxy

Proxy pattern preserves the same interface and adds functionality without clients knowing it. Clients
do not interact with the target directly just via the proxy.

Examples:
- extensions cord (length of the cord is the feature)
- power board with circuit breaker (safety is the feature)
- UPS power supply ()

## Adapter

Adapter translates interface of existing implementation to the interface that our clients need.
Usually it has very little code and simply translates between interfaces.

Examples:
- 220V to 110V converting adapter (changes electric parameters)
- 220V to USB adapter (changes voltage and the plug type)
- travelers plug (converts plug type only)

## Strategy

Strategy is similar to adapter but it usually does the actual work. Strategy is just an alternative
implementation of the functionality, with often examples of sorting, encryption and validation as examples
of strategy pattern. In fact it is one of he most common patterns.

Examples:
- current provided by the power plant (via the grid)
- current provided by a diesel power generator
- current provided by a solar panel

# Running tests

Execute ant composer target to download all pre-requisites:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace PhpDesignPrinciples\Patterns\Cache\Adapter\DoctrineCacheAdapter;
namespace PhpDesignPrinciples\Patterns\Cache\Adapter;

use PhpDesignPrinciples\Patterns\Cache\CacheInterface;
use Doctrine\Common\Cache\Cache;
Expand All @@ -21,6 +21,8 @@
* not be coupled to Doctrine itself. We can switch to zend or anything we want at any time without changing the app.
*
* NOTE: Adapter is also known as Wrapper, as it wraps existing functionality and presents it in different form.
*
* WARNING: this code has not been tested yet :)
*/
class DoctrineCacheAdapter implements CacheInterface {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

namespace PhpDesignPrinciples\Patterns\Http\Strategy;

use PhpDesignPrinciples\Patterns\Http\HttpClientInterface;
use \HttpRequest;
use PhpDesignPrinciples\Patterns\Http\SimpleHttpClientInterface;
use \Exception;
use \HttpRequest;

/**
* Uses PECL to fetch urls.
*
* WARNING: this code has not been tested yet :)
*/
class PeclHttpUrlLoader implements HttpClientInterface {
class PeclHttpUrlLoader implements SimpleHttpClientInterface {

/**
* Fetches content from a HTTP server.
Expand All @@ -19,7 +21,7 @@ class PeclHttpUrlLoader implements HttpClientInterface {
* @return string response from the server
*/
public function get($url) {
$request = $this->getRequect($url, HttpRequest::METH_GET);
$request = $this->getRequest($url, HttpRequest::METH_GET);
try {
// this could be parametrized using optional options interface
$options = array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface AssetServiceClientInterface {
*
* @param int $threadId
* @throws Exception on any errors or if asset does not exist
* @return AssetDto
* @return PhpDesignPrinciples\Patterns\Service\Dto\AssetDto
*/
public function getAsset($threadId);

Expand Down
13 changes: 13 additions & 0 deletions src/PhpDesignPrinciples/Patterns/Service/Dto/AssetDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ class AssetDto {
private $abstract;
private $body;

/**
* @var double this is just to see that instances are reused
*/
private $instanceUid;

public function __construct() {
$this->instanceUid = md5(microtime(true) . '-' . mt_rand(1, 10000000));
}

public function getInstanceUid() {
return $this->instanceUid;
}

public function getThreadId() {
return $this->threadId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

use PhpDesignPrinciples\Patterns\Cache\CacheInterface;
use PhpDesignPrinciples\Patterns\Service\AssetServiceClientInterface;
use PhpDesignPrinciples\Patterns\Service\Dto\AssetDto;

/**
* Caches service calls based on the method name and arguments
*
* NOTE: proxy does not extend any classes, it implements the same interface that is implemented by the
* target. Proxy is the extension cord, same plug as the hairdryer just gives you more range.
* Proxy contains reference to the target object and may delegate calls to it.
*
* WARNING: this code has not been tested yet :)
*/
class CachingProxy implements AssetServiceClientInterface {

Expand Down Expand Up @@ -42,7 +45,7 @@ public function __construct(AssetServiceClientInterface $target, CacheInterface
*
* @param int $threadId
* @throws Exception on any errors or if asset does not exist
* @return AssetDto
* @return PhpDesignPrinciples\Patterns\Service\Dto\AssetDto
*/
public function getAsset($threadId) {
$cacheKey = 'getAsset' . $threadId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
* NOTE: proxy does not extend any classes, it implements the same interface that is implemented by the
* target. Proxy is the extension cord, same plug as the hairdryer just gives you more range.
* Proxy contains reference to the target object and may delegate calls to it.
*
* WARNING: this code has not been tested yet :)
*/
class ProfilingProxy implements AssetServiceClientInterface {

Expand All @@ -32,7 +34,7 @@ public function __construct(AssetServiceClientInterface $target) {
*
* @param int $threadId
* @throws Exception on any errors or if asset does not exist
* @return AssetDto
* @return PhpDesignPrinciples\Patterns\Service\Dto\AssetDto
*/
public function getAsset($threadId) {
$startTime = microtime(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function __construct(SimpleHttpClientInterface $client, WebServiceConfig
*
* @param int $threadId
* @throws Exception on any errors or if asset does not exist
* @return AssetDto
* @return PhpDesignPrinciples\Patterns\Service\Dto\AssetDto
*/
public function getAsset($threadId) {
if ($threadId <= 0) {
Expand Down
58 changes: 58 additions & 0 deletions tests/Unit/CodeExamplesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace PhpDesignPrinciples\Tests\Unit\Patterns\Service\Strategy\HttpClientAssetServiceClientTest;

use PhpDesignPrinciples\Patterns\Service\Strategy\HttpClientAssetServiceClient;
use PhpDesignPrinciples\Patterns\Service\Config\WebServiceConfig;
use PhpDesignPrinciples\Patterns\Service\Proxy\CachingProxy;
use PhpDesignPrinciples\Patterns\Service\Proxy\ProfilingProxy;
use PhpDesignPrinciples\Patterns\Http\Strategy\PeclHttpUrlLoader;
use Doctrine\Common\Cache\ApcCache;
use PhpDesignPrinciples\Patterns\Cache\Adapter\DoctrineCacheAdapter;
use PhpDesignPrinciples\Patterns\Cache\Strategy\SimpleArrayCache;
use PhpDesignPrinciples\Patterns\Cache\Strategy\FakeCache;


/**
* This is not an actual test it just shows how we can assemble alternative configurations
* of objects
*/
class CodeExamplesTest extends \PHPUnit_Framework_TestCase {

public function testMinimalAssembly() {
$config = new WebServiceConfig();
$httpClient = new PeclHttpUrlLoader();
$rawService = new HttpClientAssetServiceClient($httpClient, $config);

// these will be different as we call the service twice
$rawService->getAsset(34)->getInstanceUid();
$rawService->getAsset(34)->getInstanceUid();
}

public function testFullAssembly() {
$this->markTestSkipped();
$config = new WebServiceConfig();
$cache = new SimpleArrayCache();
$rawService = new HttpClientAssetServiceClient(new PeclHttpUrlLoader(), $config);
$profiledService = new ProfilingProxy($rawService);
$cachedProfiledService = new CachingProxy($profiledService, $cache);

// these will be the same as the second call is cached
$cachedProfiledService->getAsset(34)->getInstanceUid();
$cachedProfiledService->getAsset(34)->getInstanceUid();
}

public function testFullAssemblyDoctrine() {
$this->markTestSkipped();
$config = new WebServiceConfig();
$cache = new DoctrineCacheAdapter(new ApcCache());
$rawService = new HttpClientAssetServiceClient(new PeclHttpUrlLoader(), $config);
$profiledService = new ProfilingProxy($rawService);
$cachedProfiledService = new CachingProxy($profiledService, $cache);

// these will be the same as the second call is cached
$cachedProfiledService->getAsset(34)->getInstanceUid();
$cachedProfiledService->getAsset(34)->getInstanceUid();
}

}
20 changes: 20 additions & 0 deletions tests/Unit/Patterns/Service/Proxy/CachingProxyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace PhpDesignPrinciples\Tests\Unit\Patterns\Service\Strategy\HttpClientAssetServiceClientTest;

use PhpDesignPrinciples\Patterns\Service\Strategy\HttpClientAssetServiceClient;
use PhpDesignPrinciples\Patterns\Service\Config\WebServiceConfig;

class CachingProxyTest extends \PHPUnit_Framework_TestCase {

public function setup() {
parent::setup();
$this->httpClient = $this->getMock('PhpDesignPrinciples\Patterns\Http\SimpleHttpClientInterface', array(), array(), '', false);
$this->config = new WebServiceConfig();
}

public function testFetchValid() {
$this->assertEquals(1,1);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use PhpDesignPrinciples\Patterns\Service\Strategy\HttpClientAssetServiceClient;
use PhpDesignPrinciples\Patterns\Service\Config\WebServiceConfig;

class FactoryTest extends \PHPUnit_Framework_TestCase {
class HttpClientAssetServiceClientTest extends \PHPUnit_Framework_TestCase {

/**
* @var SimpleHttpClientInterface|PHPUnit
Expand Down

0 comments on commit 1bc0582

Please sign in to comment.