Showing posts with label design pattern. Show all posts
Showing posts with label design pattern. Show all posts

Saturday, June 4, 2011

design patterns - null object pattern

As we know, if conditional statement is one thing that hurts the program readability. NULL object is also one approach to reduce your application's if condition statements. We are all familiar with these kind of code:

$user = $userDao->getUserById($id);
//For objects, i personally like to use instanceof for type checking
//but more usually, other programmers simply check $user !== null.
if ($user instanceof UserObject) {
       //do some logic with $user here
       echo $user->getName();
} else {
       //do some other things if $user is null
      echo 'user not exists';
}


As we can see, we usually use if conditional statement to check if $user is null or not, and then behaves differently based on the checking result. This kind of if statement checking could be all over the whole application. NULL object is here to help, for simplicity, i will ignore the interface part, let's check the code:

class User implements iUser
{
       private $_name;
       public function getName() {
               return $this->_name;
       }
}

class NullUser implements iUser
{
       public function getName() {
               return 'not exists';
       }
} class UserDao {         public function getUserById($id) {                 //query the database or do what ever to get the user                 $user = $this->find($id);                 if ($user === null) {                        return new NullUser();                 }                 return $user;         } } //Now your domain logic will become quite straight forward and more readable: $user = $userDao->getUserById($id);
echo $user->getName();


Now you can see how NULL object pattern can help simplify your business logic, however, you must be very careful with using this pattern. Although it simplifies your domain logic and increases readability, it does complicate your design and maintenance. And if a programmer is not aware of a NULL object implementation, he may redundant the null test, or he may really want to do some different thing if the object is null. Null object may also bring you issues when it comes to CURD operation, for example:
if ($user !== null) {
    //db query:
    $posts= $articleDao->getUserPosts($user);
}
//if we use null object, we will do the db query anyway,
//which might not be necessary
$posts= $articleDao->getUserPosts($user);

Personally, i totally agree that we should try to reduce if conditional statement in our application, particularly in business domain. But when it comes to checking if an object is null or not, i feel that i can accept that, because usually, the logic is not complex when an object is null, or even there is no logic when an object is null, for example:

$user = $userDao->getUserById($id);
if ($user instanceof UserObject) {
       //do some logic with $user here
       echo $user->getName();
//that is it, we don't have to do anything when $user is null




Thursday, June 2, 2011

Design Patterns - Strategy

Strategy Pattern Definition: the Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

I know a lot of websites are quite simple and some web developers only know CURD and once the domain logic becomes complex, they start to struggle and start to create crap. But, anyway, complex conditional logic is one thing that makes program hard to read & understand. To improve readability, We can replace conditional logic with strategy pattern + factory pattern.

For example, we have logic below:
//some how we get a format value dynamically
$format  = $objOne->getFormat();
$context = $objTwo->getContext();

if ($format === 'xml') {
    //start to format $context into xml format
} elseif ($format === 'txt') {
    //format text
} elseif ($format === $somethingElse && $someotherConditionCheck) {
    //another format implementation
}

Let's see how to use Strategy and Factory Pattern to improve the code.

From the definition, we know that we should define an interface for a set of algorithms, for example:

interface FormatStrategy
{
    public function format($content);
}

Now, we can implement our algorithms. Each one is a separate class that implements FormatStrategy Interface:
class XmlFormat implements FormatStrategy
{
    public function format($content)
    {
        //do some xml format
        return $content . ' in xml';
    }
}

class TxtFormat implements FormatStrategy
{
    public function format($content)
    {
        //do some txt format
        return $content . ' in text';
    }
}
We defined two for algorithms and they both implement the same interface. Next, we must define some kind of strategy selector(Factory):

class FormatStrategySelector
{
    public static function getStrategy($strategy) 
    {
        switch($strategy) 
        {
            case 'xml':
                return new HtmlFormat();
                break;
            default:
                return new TxtFormat();
                break;
        } 
    }
}

To use strategy:

$format  = $objOne->getFormat();
$context = $objTwo->getContext();

$formattedContent = FormatStrategySelector::getStrategy($format)->format($context);

Thursday, May 26, 2011

javascript design patterns - Factory

Factory pattern is used to create objects. The most normal implementation is a static method of a class(object in javascript). 

When to use Factory Pattern?
When you need to create objects that implement same interface, and you don't know(you don't need to know, and you shouldn't know) the specific class type/object type at compile time, factory pattern is the solution for you.

Suppose you have a Car interface:
//code below is not a correct interface implementation in javascript, 
//but just suppose it is an interface
var Car = function(){};
Car.prototype.run = function(){};

//suppose we have an extend() method doing the inheritance 
var Mazda = function(){};
extend(Mazda, Car);

var Ford = function(){};
extend(Ford, Car);

//Now, we need a factory method to make cars for clients.
Car.factory = function(name) {
    //here is the condition to check which car should be made.
    //usually is a switch/case, but here i simply use if else
    if (name === 'ford') {
        return new Ford();
    }
    if (name === 'mazda') {
        return new Mazda();
    }   
}

//i want a car!
var myCar = Car.factory('mazda');
//run!!!!
myCar.run();

Wednesday, May 25, 2011

javascript design patterns - observer

Design patterns are not OOP language specific. Javascript is a plasticine language, it can mimic OOP, so design patterns apply too.

Observer pattern is probably the most wildly used design pattern in frontend javascript programming. All those events and listeners, they are some sort of observer pattern implementation(Is there something called backend javascript programming? There is! And i believe one day it will dominate. Check http://nodejs.org if you are interested. Why do we have to use PHP at the backend and javascript at the frontend? Isn't it amazing we can use one langauge at both frontend and backend?)

Here is a very simple observer example:

function Observable() {
    this.observers = [];
}
Observable.prototype.addObserver = function(observer) {
    this.observers.push(observer);
};

Observable.prototype.notifyObservers = function() {
    for (var i=0; i<this.observers.length; i++) {
        this.observers[i].update();
    }
};

function Observer(id) {
this.id = id;
}
Observer.prototype.update = function() {
console.log(this.id + ' get updated');
}

var campaign = new Observable();
var userOne  = new Observer('one');
var userTwo  = new Observer('two');

campaign.addObserver(userOne);
campaign.addObserver(userTwo);

//console log:
//'one get updated' 
//'two get updated'
campaign.notifyObservers();

Observer is a great pattern for loose coupling. Instead of Observable object calling the Observer object's method, the Observer object is attached/added to the Observable object and gets notified. This concept is wildly used in event driven development. An event is triggered, and it is broadcasted to all the event's listeners

javascript design patterns - singleton

Design patterns are not language specific(Or i should say not OOP language specific). They apply to all OOP languages.

Javascript is a plasticine language, it can mimic OOP, and design patterns apply too.

When we use the object literal to create an object, we are actually getting a singleton.

//get a connection instance, a singleton
var connection = {
    type : 'sqlite',
    db: 'test',
    user: 'user',
    pwd : 'pwd'
};

In JavaScript, objects are never equal unless they are the same object, so even if you create an identical object with the exact same members, it won't be the same as the first one:

var conn = {
    type : 'sqlite',
    db: 'test',
    user: 'user',
    pwd : 'pwd'
};
//false
console.log(conn === connection);
//false
console.log(conn == connection);

Well, but that seems not that kindof singleton we are familiar with when programming with PHP or Java, doesn't it?

Singleton means we should have only one instance of a specific resource anytime, anywhere in the application scope. Database connection is a typical example of singleton. In PHP, you probably can only get a db resource in this way: DB::getInstance(). You cannot use 'new' operator to get an instance, and you can't clone this instance either. If you assign the instance to multiple variables, the variables are actually pointing to the same instance, for example:

//$one and $two point to the same instance!
//if somehow you change the status of $one, $two get affected too
$one = DB::getInstance();
$two = DB::getInstance();

Back to our javascript singleton examples. Although both connection and conn are singletons, we actually can have two instances of same resource. I don't think that is the singleton we want to have.

In javascript, we can use object literal to create an object, also we can use 'new' operator(constructor function) to create an object. So probably in a javascript project, we should set the convention that a singleton resource could only be created through 'new' operator, and we ensure the constructor function returns same instance:

//that is what we want to achieve
var connection = new Connection();
var conn       = new Connection();
//should be true
console.log(connection === conn);

So let's see how can we do it in the easiest and simplest way: using function property

var Connection = function() {

    if (typeof Connection.instance === "object") {
        return Connection.instance;
    }
    this.type = 'sqlite';
    this.db   = 'test';
    this.user = 'user';
    this.pwd  = 'pwd';

    Connection.instance = this;
}
var connection = new Connection();
var conn       = new Connection();
//should be true
console.log(connection === conn);

It is clean and easy. But the only drawback is Connection.instance is publicly accessible, so other codes might accidently change it.

To fix the drawback, we can use javascript's self-defining function

var Connection = function() {

    // the cached instance
    var instance = this;

    this.type = 'sqlite';
    this.db   = 'test';
    this.user = 'user';
    this.pwd  = 'pwd';

    // rewrite the constructor
    Connection = function () {
        return instance;
    };
}

This should serve well enough. But, you probably know that there is a drawback by using self-defining function, although that could rarely happen in practice. 

The third solution: using self-invoking function
var Connection;
(function () {
    var instance;
    //constructor
    Connection = function() {
        if (instance) {
            return instance;
        }
        instance = this;
        // all the functionality
        this.type = 'sqlite';
        this.db   = 'test';
        this.user = 'user';
        this.pwd  = 'pwd';
    };
}());

var connection = new Connection();
var conn       = new Connection();

Thursday, November 13, 2008

PHP In Action VS PHP Objects Patterns and Practice (2)

Both of these books heavily refer to some typical software development books: Design Patterns (Gang of Four), Refactoring (Martin Fowler), patterns of enterprise architecture (Martin Fowler), etc. Basically, these two books are trying to introduce concepts like design pattern, architecture, refactoring, which are common to java developers, to PHP. So, if you find these two books helpful, it is natural that the next step should be those reference books.

Both books introduce some common design patterns which may be used frequently in PHP development, for example, Factory, Singleton, Strategy, Observer, Composite, Command, Decorator.

However, I think both of them missed another important pattern: Delegate.

There are some other design patterns, which, based on my experience, are not often used in PHP development, are introduced in the two books. PHP In Action shows us Adapter, and the other book explain Interpreter.

Saturday, October 4, 2008

singleton, static, defensive programming

below quoted from PHP 5 CMS Framkwork Development.
"The singleton appears repeatedly, especially for the handler objects described later. In theory, handlers could be implemented as class methods, but in PHP5 a class is not itself a first class object and it is more effective to use singleton objects. Other objects are naturally singletons, such as the session object, since PHP5 handles only a single request at a time.

They(signleton classes) arise naturally in designing systems where a range of related services is needed. Sometimes, this is done by creating a class that consists only of static methods. But that is both inefficient, and inflexible. Dealing with an instance of a class is generally more efficient than dealing with static methods, and in many cases a singleton object will know quite a lot of potentially complex information. Since a class of this kind is a manager or handler, there should never be a need for more than a single instance of the class, hence the name singleton. "

Friday when i was looking into the codes of our system, i found piece of codes like below:

public function f($keyword, $country)
{
if ($keyword === 'a') {
$keyarray = $config[$country]['a'];
} elseif ($keyword == 'b') {
$keyarray = $config[$country]['b'];
}

foreach($keyarray as $key) {
......
}
}

What is the problem of the above code? First, $keyarray is not initialised! if $keyword is neither 'a' nor 'b', the program will still try to run the next codes and throw a notice: Undefined variable and a warning 'Warning: Invalid argument supplied for foreach()'.

In the above case, at lease we should put one more 'else{$keyarray = array()}' at the end to ensure $keyarray is initialised. It is better to check with isset to make sure $config is set up correctly. However, since many php programmers don't do this in practice.

My friend who was working in GE told me that none of PHP programmers are professionals, or all PHP programmers are amateur because PHP is designed for amateur to develop simple database driven website quickly. However, since PHP plays increasingly important role in web app development, enterprises tends to employ PHP developers for their web applications. As usual, they define the criteria like 3-5 years experiences, etc, etc. They never thought that PHP programmers with 3,5 years experiences means they don't have any formal, scientific software development methodology. Probably they know more detail of PHP language. They know more functions in PHP manual. But they don't have OOP in mind. They don't have design patterns in mind. They don't have refactoring in mind.