It's Majax
"Any sufficiently advanced technology is indistinguishable from magic." - Arthur C. Clarke
  • Projects and Tools
  • GitHub Projects
  • Talks
  • Contact Me
  • What is Software?

About the Proxy Pattern

December 15, 2012 jmather Code Snippets, Patterns, PHP, Programming, Tutorials 12 Comments

Edit: Added an update with a more concrete example further down.

I just wanted to share and provide a further explanation on the Proxy Pattern example I gave at the Ann Arbor PHP/MySQL User Group today.

Source: https://gist.github.com/4302634

Now, Dan had mentioned that this could be done through simple inheritance instead of via interface contract, and after some thought, I realized that I disagree.

Typically with an API object, you will initialize with a remote URL, and perhaps a token:

public function __construct($api_url, $auth_token)

public function __construct($api_url, $auth_token)

But remember our new Cache API proxy only takes an API object and a Cache object.

public function __construct($cache, $api)

public function __construct($cache, $api)

This fundamentally changes the contract that the initial API object creates, and as such, should then NOT extend the original API implementation.

Part of doing OOP well involves the management of contracts we establish. Changing the rules of a function in a sub-classed entity violates the Liskov substitution principle (as referenced in SOLID object oriented design).

Now, you COULD subclass the MyApi class, and add the Cache control via setter injection, but personally I don't think that implementation is nearly as clean as providing a proxy object to add the caching functionality.

 

p.s. I'll leave QuickTime running but I think it did eat the recording of the presentation -- sorry guys! I'll put the slides up soon but I don't know how much context they will provide given how light they were compared to the commentary that went along with it.

 

Update (12/07/2012):

It has been pointed out that my example was perhaps a little too contrived, so I think I found a better one.

Let's say you're building a system out, and you know you want logging, but you don't know what sort of implementation you want to do for said logging. Given that instance, let's start with our basic interface:

1
2
3
4
5
6
interface Logger
{
  public function info($message);
  public function debug($message);
  public function fatal($message);
}

interface Logger { public function info($message); public function debug($message); public function fatal($message); }

Ok, great! So, because production schedules are tight, we decide to give a very basic implementation first:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyBasicLogger implements Logger
{
  public function info($message)
  {
    error_log('INFO: '.$message);
  }
 
  public function debug($message)
  {
    error_log('DEBUG: '.$message);
  }
 
  public function fatal($message)
  {
    error_log('FATAL: '.$message);
  }
}

class MyBasicLogger implements Logger { public function info($message) { error_log('INFO: '.$message); } public function debug($message) { error_log('DEBUG: '.$message); } public function fatal($message) { error_log('FATAL: '.$message); } }

Alright! We now have our basic logger implemented!

Oh, what's that you say? You want to use Monolog in place of error_log() in production? sure!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class MyMonologLogger implements Logger
{
  protected $monolog;
 
  public function __construct($monolog)
  {
    $this->monolog = $monolog;
  }
 
  public function info($message)
  {
    $this->monolog->addInfo($message);
  }
 
  public function debug($message)
  {
    $this->monolog->addDebug($message);
  }
 
  public function fatal($message)
  {
    $this->monolog->addCritical($message);
  }
}

class MyMonologLogger implements Logger { protected $monolog; public function __construct($monolog) { $this->monolog = $monolog; } public function info($message) { $this->monolog->addInfo($message); } public function debug($message) { $this->monolog->addDebug($message); } public function fatal($message) { $this->monolog->addCritical($message); } }

Now we have two ways of logging messages. Now comes the constraint that we want to be emailed when fatal errors are logged. Your first instinct would be to extend MyMonologLogger and add it by overloading fatal(), but then we can't use that functionality on any other logger we ever build. How do we build this functionality in a way that we can reuse over and over again? The Proxy pattern.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class MyEmailingLoggerProxy implements Logger
{
  protected $logger;
 
  public function __construct(Logger $logger)
  {
    $this->logger = $logger;
  }
 
  public function fatal($message)
  {
    $this->logger->fatal($message);
    mail('admin@example.com', 'A fatal error has occurred', $message);
  }
 
  public function info($message)
  {
    $this->logger->info($message);
  }
 
  public function debug($message)
  {
    $this->logger->debug($message);
  }
}

class MyEmailingLoggerProxy implements Logger { protected $logger; public function __construct(Logger $logger) { $this->logger = $logger; } public function fatal($message) { $this->logger->fatal($message); mail('admin@example.com', 'A fatal error has occurred', $message); } public function info($message) { $this->logger->info($message); } public function debug($message) { $this->logger->debug($message); } }

And now, no matter what we choose as our logging backend, now or in the future, we will always easily be able to have those fatal errors emailed to us by simply putting our chosen logging system inside an instance of MyEmailingLoggerProxy.

I hope this clears some things up!

Introduction to PHPUnit and Selenium Testing

December 3, 2012 jmather Code Snippets, Open Source, PHP, Programming, Testing, Tutorials No Comments

So over the weekend I gave a talk at the Ann Arbor PHP User Group about how to ramp up with Selenium testing using PHPUnit. If the video shows this is something of interest for you, please feel free to check out the GitHub repository and get started!

Building your first Selenium test with PHPUnit

November 30, 2012 jmather Code Snippets, Open Source, PHP, Programming, Testing 3 Comments

So I put together a quick example of how to go about building your first Selenium test with PHPUnit.

Why PHPUnit? Because there are less moving parts to understand at first.

Remember, the most important part of testing is to have tests to run. You can work on how you build those tests later.

Split by Jordi Boggiano

November 27, 2012 jmather Open Source, Programming No Comments

This is an awesome little game by @seldaek for the GitHub Game Off 2012. You should go check out! Tons of fun!

How to act like you (maybe actually) care about your work – Ann Arbor PHP/MySQL Group – November 17th 2012

November 27, 2012 jmather Programming No Comments

Here is the video from my talk about how to be a better developer. For more information, check out my page dedicated to the talk.

«‹ 6 7 8 9›»

About Jacob Mather

I have been developing websites professionally for over 10 years. I like to help solve complex problems, and have a knack for break down sophisticated systems into simple functional pieces. I advocate strongly about the value of community, and really love talking about how to be a better developer.

Recent Posts

  • Introduction to building a programming language – Open West 2015
  • Testing Browser JavaScript Completely – Open West 2015
  • Give Your Engineers Wings, not Anchors: Building Tools for the Cloud – Open West 2015
  • Managing technical debt extraction within a large code base
  • The why of the thing

Recent Comments

  1. Edwin on How to fix the heck out of your Brother Control Center in OS X!
  2. fredrik on How to fix the heck out of your Brother Control Center in OS X!
  3. Michael Adams on How to fix the heck out of your Brother Control Center in OS X!
  4. Yined on Much more Eggs than Bacon: A Development Environment Cookbook – Code PaLOUsa 2014
  5. Samir on Building your first Selenium test with PHPUnit

Categories

  • Business
  • Code Snippets
  • Design
  • Life
  • Open Source
  • OS X
  • Patterns
  • PHP
  • Programming
  • Responsive
  • San Francisco PHP
  • Silex
  • Symfony
  • Symfony2
  • Testing
  • Tutorials

Archives

  • May 2015
  • November 2014
  • June 2014
  • March 2014
  • February 2014
  • November 2013
  • October 2013
  • August 2013
  • May 2013
  • March 2013
  • February 2013
  • January 2013
  • December 2012
  • November 2012
  • October 2012
  • September 2012
  • August 2012
  • July 2012
  • June 2012
  • April 2012
  • March 2012
  • February 2012
  • August 2011
  • April 2011
  • March 2011
  • January 2011
  • November 2010
  • October 2010
  • July 2010

↑

© It's Majax 2025
Powered by WordPress • Themify WordPress Themes