Explore Aspect Oriented Programming with CodeIgniter, Part 1

Tweet
This entry is part 1 of 3 in the series Explore Aspect Oriented Programming with CodeIgniter

Explore Aspect Oriented Programming with CodeIgniter

Have you ever heard of Aspect Oriented Programming (AOP) before? It’s a widely used concept in developing enterprise level systems, although it hasn’t seen much use in PHP. I’m going to use this article as an opportunity to introduce PHP developers to AOP.

This tutorial will be delivered to you as a 3-part series. In this part I’ll explain the concepts of AOP. In part 2 I’ll show you the practical uses of AOP and creating a AOP rules structure. Finally, I’ll show you how to integrate AOP functionality using CodeIgniter in part 3.

What is AOP?

In application development we often find required functionality that needs to be used in multiple points in our code but which is not actually related to business logic. Checking authentication to make sure a user is logged in before executing a specific task is a good example. Such tasks are called cross-cutting concerns. Let’s take a look at the definition of cross-cutting concerns as given by Wikipedia:

In computer science, cross-cutting concerns are aspects of a program which affect other concerns. These concerns often cannot be cleanly decomposed from the rest of the system in both the design and implementation, and can result in either scattering (code duplication), tangling (significant dependencies between systems), or both.

Now that you have a basic idea of what cross-cutting concerns are, let’s see what they look like in code.

Consider the situation where you are the editor of a blog like SitePoint. You need to login in order to create posts, approve posts, edit post, etc. If you are not logged in, you should be directed to the login screen. In order to ensure this behavior, the code must validate authentication before each of the tasks mentioned above.

<?php
class BlogPost extends CI_Controller
{
    public function createPost() {
        if (!Authentication::checkAuthentication()) {
            // redirect to login
        }
        else {
            // proceed
            Messages::notifyAdmin();
        }
    }

    public function approvePost() {
        if (!Authentication::checkAuthentication()) {
            // redirect to login
        }
        else {
            // proceed
        }
    }

    public function editPost() {
        if (!Authentication::checkAuthentication()) {
            // redirect to login
        }
        else {
            // proceed
        }
    }

    public function viewPost() {
        // ...
    }
}

Look at the above code and you can see that checkAuthentication() is called inside every method which needs the user to be logged in, and notifyAdmin() is called to notify administrators when new posts are created. Not only is this duplicated code, but the BlogPost class should be only responsible for managing posts. Authentication and notifications should be done separately. We have violated the Single Responsibility Principle:

The single responsibility principle states that every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

So now we’ve come to a place where we can understand the meaning of AOP. Cross-cutting concerns can be grouped into objects called “aspects,” and the process of separating cross-cutting concerns from our core code is called Aspect Oriented Programming.

AOP Terminology

There are few specific terms used in AOP to explain its features. Understanding these terms will likely be the key to successfully integrating AOP into your PHP projects.

  • Aspect
  • Advice
  • Joinpoint
  • Pointcut

We just learned what an aspect is, so now let’s see what the other three terms mean.

Advice

The functionality of an aspect is called an advice. As the name suggests, advices define what to do in certain situations and when to do it. In our previous example, checking authentication (the what) is the advice, and it should be applied before executing code (the when) inside specific methods.

Joinpoint

Joinpoints are places in the application where we can create advices. Looking back at the sample code, you can find several places where I have called functionality that is not directly related to the business logic. In createPost(), for example, cross-cutting concerns occurs before the executing any logic with the authentication check, and afterwards with sending a message to administrators. These are both possible joinpoints.

Joinpints can be defined anywhere in your application’s code, but applying advices will only be available to certain points according to your AOP framework features and will be discussed later in this tutorial.

Pointcut

Pointcut defines a way of matching advices to certain joinpoints. Though we have a couple joinpoints in our example, you could have thousands of joinpoints in your application and you might not need to apply advice to all of them. In such situations, we can match a subset of joinpoints, which is known as poincuts, and apply advices to the selected elements only.

Assume that we want to advice createPost(), approvePost(), and editPost(), but not viewPost(). We have to somehow match those 3 methods and apply the advices. Later we will be creating an XML file with aspect details which will contain regular expressions to match joinpoints.

So to summarize, when a cross-cutting concern occurs in the application, we create an aspect that advices the application functionality in certain joinpoints selected using a pointcut.

AOP Advice Types

There are few ways we can advice our code. As I mentioned earlier, the availability of these advice types depends on the type of AOP framework you use, but some types you should be familiar with are:

  • Before advice
  • After returning advice
  • After throwing advice
  • Around advice

Before Advice

Before advice will be applied before a specific point in your code, normally a method call.

I have used advices inside methods so far to simplify the concept and help you understand it quickly. But in the real-world, advices usually don’t come inside methods. There should be a separate global controller where each method should go in, and inside the method we can wrap the AOP functionality. This global controller is run inside the system and is not be visible to us.

<?php
class PathController
{
    function controlPaths($className, $funcName) {
        Authentication::checkAuthentication();
        $classObj = new $className();
        $classObj->$funcName();
    }
}

Here I’ve created a dummy class to show you how it actually happens. Assume the controlPaths() method acts as the global entry point for the application, and each method call will be passed through this method. In the above code we have applied the advice checkAuthentication() before desired method call is actually performed. This is called before advice.

After Returning

This advice will be applied once specific functionality is completely executed and returned to the calling point. Consider the following code:

<?php
class PathController
{
    function controlPaths($className, $funcName) {
        $classObj = new $className();
        $classObj->$funcName();
        Database::closeConnection();
    }
}

See here that once the method is completed we clean up the database resources. This is called after returning advice.

After Throwing

If the function throws an exception in the execution process, After throwing advice can be be applied. Here, the after throwing advice is the error reporting.

<?php
class PathController
{
    function controlPaths($className, $funcName) {
        try {
            $classObj = new $className();
            $classObj->$funcName();
        }
        catch (Exception $e) {
            Error::reportError();
        }
    }
}

Around Advice

A fourth type of advice is around advice, which is a combination of both before advice and after returning advice.

<?php
class PathController
{
    function controlPaths($className, $funcName) {
        Logger::startLog();
        $classObj = new $className();
        $classObj->$funcName();
        Logger::endLog();
    }
}

Summary

In this article I introduced you to AOP. You should have a basic understanding of what AOP tries to accomplish, and be familiar with some of the basic AOP terms. In the next part of this series I’ll show you where AOP is needed in real world projects and how we can use CodeIgniter hooks to create AOP functionality. Stay tuned!

Image via Fotolia

Explore Aspect Oriented Programming with CodeIgniter

Explore Aspect Oriented Programming with CodeIgniter, Part 2 >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://zenshadow.com Trevor Geene

    So if I understand this article series right, it is all about using external functionality to help support another set of functionalities. As well as figuring out when and where it is best to use each method.

    I generally already use these kind of things in my CodeIgniter applications, but it is nice to finally have proper terms for it as well as find out what the best practices are.

  • L

    Hi,
    Looks nice. Would you like to show AOP in Laravel too?

  • Kevin

    L
    Laravel utilizes a base control so you’d just create checkAuthentication there and it would be globally available for any controller. Even better, I’d use Laravel’s routing system which is a more intuitive way of handling application flow than a rigid controller.

  • http://github.com/dublinan Andre Dublin

    Really great intro to AOP, after reading it took me a while to see the benefit of using AOP in Codeiginter when there are hooks that execute during the request life cycle. But AOP to me seems more arbitrary. Look forward to the next two installments!

  • http://www.nine10.ca/blog/ Richard Podsada

    To me this looks a lot like event-driven design. Essentially each method has event triggers (joinpoints) for events that call event handlers (advices.) The XML schema assigns event handlers to triggers (pointcut.) I love and agree with this concept but don’t understand why we need to complicate teaching this by defining a whole new set of confusing terminology to it. Coders with too much time on their hands maybe? ;)

    • Rocco

      I completely agree. It seems to me that everyone is focusing on building “frameworks” and “patterns” instead of doing one simple thing: write quality robust simple code. I would love to see more people focused on security and performance instead of “inventing” new fancy ways of naming things under the cover of the revealing “the proper way of doing things”.

      In the good old days we just called it OOP and be done with it, now, every way of logic encapsulation needs to have it’s own terminology.

      The fact is that bad application design cannot be prevented by hiding behind these fancy words and the more “patterns” you use inside your application the more likely is to serve the framework instead of what’s really important: the application itself.

      Following Pareto’s principle it seems obvious to me that classical OOP is more than enough for implementing any requirements.

      When was the last time anyone asked you to build a new framework or a software design pattern ?

  • http://www.alexanderb.se Alexander

    Nice article series, i find it very useful!

    And the link to next part in series goes straight to part 3 :O

    • http://www.innovativephp.com Rakhitha Nimesh

      Hi Alexander

      Thanks and I am glad that you enjoyed my tutorial series.

      Opps. I’ll get it fixed to include part 2 :)