Blog
OpenEnergyMonitor

Ideas for improving the emoncms framework

I've been looking again at writing the developer documentation for emoncms, in particular Id like to document how to build the core framework from scratch, explaining the design decisions and implementation of things like the front controller, modules folder structure, MVC pattern.

In doing this exercise and reading up more widely about the various parts I started to get ideas for improvements.

1) Changing the controller structure to better reflect the client side javascript nature of views

The first insight I had followed from reading Jean Claude Wipplers post about really going all the way with client side javascript (and server side for that matter :) using angular js and other technologies: http://jeelabs.org/2013/01/07/technology-decisions/ "...Think about the change in mindset: no server-side templating… n o n e !"

Emoncms UI is already largely client-side javascript with javascript making 41% of the emoncms code base. But there are still quite a few parts that are generated by server-side templating - the user account page being one notable example.

The framework was initially built with server side templating in mind with the result of the model being passed to a view and the view being constructed with php. The current emoncms application architecture documentation page reflects this idea, see the Views section in particular which shows a minimal example of creating a feed list using php.

However the way the feed list view is actually made in emoncms is using client side javascript to create a dynamic view that shows the feeds updating in realtime. The feed list data is requested from the server using jquery AJAX every 5 seconds.

Letting go of the idea that we might want to do server side php templating for most of the module views and reassessing the framework controller code in particular, the following as described on the controller part of the application architecture page no longer makes much sense:

if ($action == 'list' && $_SESSION['read'])
{
  $feeds = get_user_feeds($_SESSION['userid']);

  if ($format == 'json') $output = json_encode($feeds);
  if ($format == 'html') $output = view("feed/list_view.php", array('feeds' => $feeds));
}

Here in response to a request from the client for a feed list we first get the data from the model and second either output it as json or wrap it in a view. But if the view no longer needs the feeds array passed to it (as it is getting the feeds data via an AJAX request) it makes no sense for the view to be called after getting the data from the model.

So I think a clearer structure for the controller is to divide it into two parts:

The first part deals with html page requests and is essentially loading the client side application from the server to the client:

if ($format == 'html')
{
  if ($action == 'list') $output = view("feed/list_view.php", array());
  if ($action == 'view') ...
}

The second part placed directly below the above in the controller deals with the JSON API to the model

if ($format == 'json')
{
  if ($action == 'get') $result = get_feed(get('userid'),get('feedid'));
  if ($action == 'list') $result = get_user_feeds(get('userid'));

  $output = json_encode($result);
}

2) Straight mysqli instead of db.php abstraction

While rewriting the core framework from scratch it hit me that the db.php abstraction I created that converts mysqli class calls into global scope db_query etc functions is not really that useful and probably just confusing. db.php never did anything useful on top of mysqli like input sanitisation or anything like that so I think it would just be better to write straight mysqli.

Which leads on to the next point:

3) Models as classes

After using the mysqli class with the $mysqli->query() $class->method() type interface I started to experiment with using php classes for the emoncms models instead of just a file full of functions. Here's an example for the feed class with only one method for loading a users feed list (notice also how $mysqli is passed into the class for use)

class Feed
{
  private $mysqli;

  public function __construct($mysqli)
  {
    $this->mysqli = $mysqli;
  }

  public function list($userid)
  {
    $feeds = array();
    $result = $this->mysqli->query("SELECT * FROM feeds WHERE `userid` = '$userid');
    while ($row = $result->fetch_object()) $feeds[] = $row;
    return $feeds;
  }

}

To use this in the application we first create an instance of the class

$feed = new Feed($mysqli);

and then call the methods needed:

$result = $feed->list($userid);

This gives us a nice interface to the feed model in the rest of the application, it's a clearer naming convention model_name->method_name() and its clearer that model methods and properties belong to that model. There are also a whole load of other potential benefits as time goes on such as extending the class and so on (all standard stuff in most frameworks)

4) The fat model and thin controller

In reading more on the model view controller pattern I came across this article which really made a lot of sense to me: http://blog.astrumfutura.com/2008/12/the-m-in-mvc-why-models-are-misunderstood-and-unappreciated/

The question of what should be in the controller and what should be in the model is something that I had been a bit unsure about and so far I have usually put input validation and any error reporting in the controller while trying to confine the model to primarily data access. 

But looking again at this and with the clarity of that article, it makes sense to me that input validation and error reporting should be in the model instead.

When coupled with the class based model that model then becomes a very complete and portable class that can be used in different applications or frameworks as the article suggests with all the validation and error reporting intact.

The controller's role then becomes: translation of the external http api to model method calls , fetching of input via $_GET and $_POST and passing these to the model method parameters and checking to see if the user has the correct privileges to call the model method.

5) php code formatting standards 

Here's another interesting resource I came across only yesterday phptherightway.com. There's lots of valuable information on there including details on 4 standards including a code formatting standard for php produced by many of the large php frameworks and application projects, I think it would be good to adopt these in emoncms.

On the client 

6) Move all the user interfaces over to client side javascript

As mentioned above emoncms user interfaces are already largely constructed with client side javascript interacting with the server via AJAX requests but there are still several interfaces like the user account page that are constructed using php templating. I'd like to explore ways of modularising the client side code, making the code as clear as possible, it all gets rather complex and a bit messy there pretty fast at the moment. I'm also intrigued to explore AngularJS which Jean Claude Wippler is using as that looks like it might be a solution to some of the javascript jquery complexity woes that I have been having.

Next steps...

One of the good things about the server side changes proposed above is that many of them are only minor changes to existing code and they can be introduced incrementally, so we can run old code alongside new.

My plan is to start by completing the emoncms architecture documentation: how to build the emoncms framework from scratch then go on to convert the user module over to the controller and model design as detailed above and complete a nice javascript enabled user login/register page and a user account and profile page.


To engage in discussion regarding this post, please post on our Community Forum.