Joseph Hallenbeck


September 23, 2013

CodeIgniter’s God Complex

Filed under: Software Development — Tags: , , , — Joseph @ 9:00 am

Flattr this!

I have worked with Code Igniter almost exclusively for the last nine months. In that time, I have found it to be a massive step ahead over working with some of the major CMS systems on the market (WordPress, I am looking at you). Nevertheless, there remains some major architectural and blind spots that exist in CodeIgniter as a framework. Some of these issues are resolvable (CodeIgniter’s presumption that you would only ever want to validate the POST superglobal), while others are inherent in it’s design. In this series I hope to look at some of these issues that I have found with CodeIgniter, showcase work-arounds where I can, or simply rant where no good solution exists. Today’s topic will be of the latter variety.

The God Object AntiPattern

Lets dip over to WikiPedia for the definition of a God Object:

In object-oriented programming, a god object is an object that knows too much or does too much… a program’s overall functionality is coded into a single “all-knowing” object, which maintains most of the information about the entire program and provides most of the methods for manipulating this data. Because this object holds so much data and requires so many methods, its role in the program becomes god-like (all-encompassing). Instead of program objects communicating amongst themselves directly, the other objects within the program rely on the god object for most of their information and interaction.

The God Object in CodeIgniter

CodeIgniter started as an early MVC framework that has maintained backwards compatibility with PHP5.2. It’s maintainers have insisted on maintaining this compatibility which has limited CI from taking advantage the advances that PHP5.3, 5.4, and 5.5 introduced to the language.

There remains nothing truly wrong with PHP5.2. While 5.3+ offers us many great advantages, a SOLID framework is still possible using the older version. CI’s architectural issues do not stem necessarily from it’s usage of the older version but rather the violation of SOLID principles in archetyping it’s interpretation of MVC.

In CI we have the CI super class (the idea of a super class alone should be a code smell) that is globally available via the get_instance() function. This returns an instance of CI_Controller, our main application controller handling the current request. This instance is our elusive beast. The God Object itself. We’ll call this object CI from here on out.

In any one request there can be only one instance of CI — it is essentially a singleton responsible for:

  1. Loading models
  2. Processing the request
  3. Returning the response

Overloaded Models

Here is where we get into the meat and potatoes.

The CI object begins its life by loading resources, that is it begins by loading various models and libraries and maintaining links to each of them like so:

public function __construct()
{
  $this->load->model('news');
  $this->load->model('events');
}

This code instantiates an instance of the news model and assigns a reference to news. It then instantiates an instance of events. In this manner every model that comes into existence during request process is held as a reference by the CI object and can be access latter on in the request, e.g.

public function index()
{
  $data = array();
  $data['articles'] = $this->news->get( 3 );
  $this->load->view( 'news', $data );
}

Once more, something very peculiar is done during this process. CI not only instantiates an instance of the given model but it also copies these references to every subsequently loaded model.

Thus every object that is loaded in this manner becomes aware of every object that had been loaded up-to that point regardless of whether that object really needed access to the behaviors of those objects. The model becomes unnecessarily bloated and the difficulty of debugging the behaviors of a given model increases. Unintended behaviors might be caused not by the model itself but by the combination of that particular model and the order or selection of previously loaded models.

Examine a Model’s State? No way.

Take for example the simple act of using var_dump to see the state of an object in memory. If we were to var_dump our instance of news we might as well call it a day as news contains a reference to everything that has been loaded into memory for our request. The server will proceed to dump the entirety of our application to the screen for us to wade through!

No Public Property is Safe

A larger issue is the assigning of the references themselves. Since the first act of initiating the model object is to copy CI’s massive registry of references to the model any properties or references set in the model’s constructor is at the mercy of the controller overwriting the model. Take for example, the events model. Let’s say the following was in the constructor:

public function __construct()
{
  $this->news = new News();
}

Following substantiation of the events object the Events object CI will immediately overwrite the news property with it’s own instance of the news property. Thus the events model would either need to make the news property private or protected which would generate an error when CI attempts to access it or we would always need to take care to keep our model properties from existing in the same namespace as CI.

I actually ran into a horrible bug where this very thing happened. I had a class named Validator that I loaded in with the controller. I also intended each of my models to load their own instances of the Validator class and to initialize their instances with own unique validation parameters. However, since the controller had already loaded an instance of Validator it immediately overwrote each of my model’s Validator‘s forcing them all to use the same instance of the class. The resolution to this problem was to have to name each instance of Validator something different, thus we had EventValidator, NewsValidator, etc.


September 16, 2013

NextGEN Gallery 2.0.21 Lightbox Fix

Filed under: Journal — Tags: , , , — Joseph @ 9:00 am

Flattr this!

I decided to share my fix for lightboxing in NextGEN Gallery 2.0.21. This version of the WordPress plugin for some odd reason breaks support for lightboxing the gallery images (that is having the gallery image “pop out” in front of the page when clicked).

This fix does not modify the NextGEN gallery itself so we can easily revert to using NextGEN’s lightboxing whenever it gets fixed.

Follow these steps:

1. Turn off NextGEN Lightbox Effect

Log into the dashboard of your WordPress installation and navigate to Gallery >> Other Options and select Lightbox Effects. There select from the drop down No lightbox

2. Install Lightbox 2 v2.6

It is important to have the most up-to-date version of Lightbox because of compatiblity issues with jQuery 1.10. Go to the Lightbox 2 website and download the latest version of lightbox, unzip the download and upload the resulting directory into your theme’s directory on your server (it should be in /wp-content/themes/).

3. Update header.php To Load Lightbox 2

Now from the WordPress dashboard select Appearance >> Editor >> header.php. For those of you without programming experience this might seem arcane but follow along. Between the <head> and </head> tags include the following lines of code:

<style type="text/css" media="screen">
        @import url( '<?= get_theme_root_uri() ?>/THEME/lightbox/css/lightbox.css' );
</style>
<script 
  type="text/javascript" 
  src="<?= get_theme_root_uri() ?>/THEME/lightbox/js/lightbox-2.6.min.js">
</script>        

Where THEME is the name of your current WordPress theme.

4. Add Custom Script to Your Footer

There is two ways of going about this. First navigate this time to `Apperance >> Editor >> footer.php. We can either append the javascript directly to the end of this file, or (the better solution) you could create an external javascript file and load it.

To do the latter, you simply create a file named lightfix.js and paste the script below minus the <script> and </script> tags. Then include it in your file the same way that you included lightbox-2.6.min.js above only this time append the include to the end of the footer.php.

If you want to just put the script directly in footer.php just copy the text below directly into the file:

<script>
( function( $, images ) {
  $(img).each( function() {
    if( $(this).parent().is('a') {
      $(this).parent().attr('rel', 'lightbox');
    }
  }
})( jQuery, '.storycontent img');
</script>

You might need to modify .storycontent img to fit your own theme. This script selects all the img html elements in the div with a class name storycontent it then loops through each of these images and if they are contained inside an anchor tag then it transforms that image into a lightbox. Since each picture in the NextGEN gallery is wrapped in an anchor tag linking to the image source this should automatically work alongside Lightbox 2 to return the lightbox functionality to our gallery.


September 14, 2013

New Wind-Up Post: Fez

Filed under: Journal — Joseph @ 11:22 pm

Flattr this!

Fez Screenshot

I have a new post over on the Wind-Up Culture Blog concerning the the extraordinary polish of Fez. Right now, I’m at 82% of Fez completed and the game continues to blow my mind away with the complexity of this indie title.


Galleries are Broken

Filed under: Journal — Joseph @ 8:18 pm

Flattr this!

I just noticed today that a combination of the newest version of the nextgen-gallery plugin with my custom jQuery and lightbox code succeeding in completely breaking support of both such that neither the nextgen galleries used in the Art and Photography sections nor the lightboxes used in various blog posts really work.

If I have some time this weekend this will all be fixed up shortly.

Updated: The problem seems to be documented already with the 2.0.21 build of NextGen. Since there is no fix for the problem and since I already have a lightbox solution installed in the theme for automatically adding lightbox to any non-lightboxed image in a post, I decide to just disable NextGen’s implementation of lightbox and add a little javascript magic to solve the problem.




Copyright 2011 - 2017 Joseph Hallenbeck Powered by WordPress