jump to navigation

Getting Started with Aspect Oriented Programming (AOP) in PHP July 29, 2014

Posted by Tournas Dimitrios in PHP.
Tags: ,
add a comment

Smiley Face

The benefits of Object Oriented Programming (OOP) is that it lets us encapsulate – abstract data and functionality away (which is the key for building large systems). We could achieve the same results with other paradigms, but it seems that OOP is especially helpful in this regard. Aspect Oriented Programming (AOP) is a follow-on development to OOP, developed with the intention of solving some of the practical limitations of OOP. The majority of applications a developer writes will contain common functionality that will be shared across the codebase (mailing, logging, caching, debugging, user-notification, security –ACL–, opening a database connection, etc….. ) . Such functionality is generally described as “cross-cutting concerns” because it’s not specifically relevant to any one piece of code where it might be embedded[used]. An example will better illustrate this subject (the following code is meant for illustrative purposes only; any design issues are beside the point) :

namespace MyNamespace\Controllers;

use MyNamespace\Services\Logger;
use MyNamespace\Services\Mailer;
use MyNamespace\Services\Security;
use MyNamespace\Services\AclException;
use MyNamespace\Models\User;

class UserController
{
     /*
     ..................
     Code truncated
     ..................
     */

    /**
    *
    * @param String $username Name of the new User
    */
    public function createNewUser($username)
    {
        $dateTime = date('l jS \of F Y h:i:s A');
        if (!$this->security->isGranted('Security::ROLE_ADMIN'))
        {
            throw new AclException('Only root can assign new users');
        }

        try {
            $user = new User($username);
            $this->entityManager->persist($user);
            $this->entityManager->flush();
        } catch (Exception $e) {
            $this->logger->error('User create error'. $e->getMessage());
            $this->mailer->send('User create error at : '. $dateTime);
        }

            $this->logger->info("User {$username} created at : " . $dateTime);
            $this->mailer->send("User {$username} created at : " . $dateTime);
    }
}

It is evident from the above code that the main role of the UserManager object is to manage users, but beyond this, UserManager has to borrow services from other objects in order to fulfill its operations. Most likely the same motif can be spotted across many places of our application (ie Logging, Mailing and Acl functionality will be used  by many objects).  The aforementioned motif is considered bad practice because it violates fundamental design principles and will lead to a system that isn’t easily maintainable-extendable over time. Let us identify a few of those violations :

  • SoC (Separation of Concerns) : Our UserManager object is tightly coupled to other objects. Distributing / Reusing the UserManager class into other projects has a dependency which must be taken into account.
  • SOLID : The above motif clearly violates the “O” of SOLID (ie the Open/Close principle). For instance, if for some reason one of those service-objects on which UserManager depends, change its functionality, this will affect UserManager (but also all objects that might use those service-objects). Having the task to update the relevant code throughout the entire system is not pleasant at all 🙂

Cross-cutting concerns  tends to increase the complexity of an application. AOP is a way of modularizing cross-cutting concerns much like object-oriented programming is a way of modularizing common concerns.

(more…)