JavaScript: Asynchronous Script Loading and Lazy Loading

Most of the time remote scripts are included at the end of an HTML document, right before the closing body tag. This is because browsers are single threaded and when they encounter a script tag, they halt any other processes until they download and parse the script. By including scripts at the end, you allow the browser to download and render all page elements, style sheets and images without any unnecessary delay. Also, if the browser renders the page before executing any script, you know that all page elements are already available to retrieve.

However, websites like Facebook for example, use a more advanced technique. They include scripts dynamically via DOM methods. This technique, which I’ll briefly explain here, is known as “Asynchronous Script Loading”.

Lets take a look at the script that Facebook uses to download its JS library:

(function () {
    var e = document.createElement('script');
    e.src = 'http://connect.facebook.net/en_US/all.js';
    e.async = true;
    document.getElementById('fb-root').appendChild(e);
}());

When you dynamically append a script to a page, the browser does not halt other processes, so it continues rendering page elements and downloading resources. The best place to put this code is right after the opening body tag. This allows Facebook initialization to happen in parallel with the initialization on the rest of the page.

Facebook also makes non-blocking loading of the script easy to use by providing the fbAsyncInit hook. If this global function is defined, it will be executed when the library is loaded.

window.fbAsyncInit = function () {
    FB.init({
        appId: 'YOUR APP ID',
        status: true,
        cookie: true,
        xfbml: true
    });
};

Once the library has loaded, Facebook checks the value of window.fbAsyncInit.hasRun and if it’s false it makes a call to the fbAsyncInit function:

if (window.fbAsyncInit && !window.fbAsyncInit.hasRun) {
    window.fbAsyncInit.hasRun = true;
    fbAsyncInit();
}

Now, what if you want to load multiple files asynchronously, or you need to include a small amount of code at page load and then download other scripts only when needed? Loading scripts on demand is called “Lazy Loading”. There are many libraries that exist specifically for this purpose, however, you only need a few lines of JavaScript to do this.

Here is an example:

$L = function (c, d) {
    for (var b = c.length, e = b, f = function () {
            if (!(this.readyState
            		&& this.readyState !== "complete"
            		&& this.readyState !== "loaded")) {
                this.onload = this.onreadystatechange = null;
                --e || d()
            }
        }, g = document.getElementsByTagName("head")[0], i = function (h) {
            var a = document.createElement("script");
            a.async = true;
            a.src = h;
            a.onload = a.onreadystatechange = f;
            g.appendChild(a)
        }; b;) i(c[--b])
};

The best place to put this code is inside the head tag. You can then use the $L function to asynchronously load your scripts on demand. $L takes two arguments: an array (c) and a callback function (d).

var scripts = [];
scripts[0] = 'http://www.google-analytics.com/ga.js';
scripts[1] = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js';

$L(scripts, function () {
    console.log("ga and jquery scripts loaded");
});

$L(['http://connect.facebook.net/en_US/all.js'], function () {
    console.log("facebook script loaded");
    window.fbAsyncInit.hasRun = true;
    FB.init({
        appId: 'YOUR APP ID',
        status: true,
        cookie: true,
        xfbml: true
    });
});

You can see this script in action here (right click -> view page source).

Review: Zend Framework 1.8 Web Application Development

Zend Framework is one of the most popular and hottest open-source frameworks being used today. The number of books about Web development using Zend Framework has increased over the last couple of years.

Packt Publishing sent me a copy of the book Zend Framework 1.8 Web Application Development by Keith Pope to review. I found this book to be a good introduction to the topics that a Zend Framework developer will need to know when developing enterprise Web applications. The book is also aimed at advanced users, considering there were a couple of things that I learned about this framework from reading the book. The book not only shows you how the Zend Framework works, but also how to write an application for real-world usage. The book covers access control, performance optimization, testing, debugging and application design. The writing is clear, the code examples are good and Keith does an excellent job of walking you through the life-cycle of a request, explaining how things work and how you can extend the framework to fit your needs.

Here’s an example of the Storefront application:
http://code.google.com/p/zendframeworkstorefront/source/browse

Conclusion

The book is very well-written, nicely structured and full of highly practical advice. Overall, I’m happy to say that Zend Framework 1.8 Web Application Development fulfilled my expectations.

Other Reviews

Raphael Stolt

“The content of the book is delivered in a fluent, very enthusiastic and ‘knowledge-pillowed’ writing tone. By implementing or working through the Storefront application seasoned web developers using older versions of the Framework will get a good blue sheet on new components like Zend_Application and it’s implication in the bootstrapping process; while new developers tending towards picking up the Zend Framework will get a current and well compiled guide, which might first start off with a steep learning-curve but will turn into profund knowledge once hanging in there.”

Fred Wu

“The flow of this book is heavily inspired by the famous Ruby on Rails book, Agile Web Development with Rails, where the author invites you to join the process of building a demo application, which in both cases is a shopping cart system. Judging by the feedback of the Rails book, most people feel quite comfortable learning a framework this way, some don’t. I guess if you are not a fan of following a defined learning structure, this book probably isn’t for you.”

Zend Framework DAL: DAOs and DataMappers

A Data Access Layer (DAL) is the layer of your application that provides simplified access to data stored in persistent storage of some kind. For example, the DAL might return a reference to an object complete with its attributes instead of a row of fields from a database table.

A Data Access Objects (DAO) is used to abstract and encapsulate all access to the data source. The DAO manages the connection with the data source to obtain and store data. Also, it implements the access mechanism required to work with the data source. The data source could be a persistent store like a database, a file or a Web service.

And finally, the DataMapper pattern is used to move data between the object and a database while keeping them independent of each other. The DataMapper main responsibility is to transfer data between the two and also to isolate them from each other.

Here’s an example of the DataMapper pattern:

Database Table Structure

CREATE TABLE `user` (
 `id` int(11) NOT NULL auto_increment,
 `first_name` varchar(100) NOT NULL,
 `last_name` varchar(100) NOT NULL,
 PRIMARY KEY  (`id`)
)

The User DAO

The DAO pattern provides a simple, consistent API for data access that does not require knowledge of an ORM interface. DAO does not just apply to simple mappings of one object to one relational table, but also allows complex queries to be performed and allows for stored procedures and database views to be mapped into data structures.

A typical DAO design pattern interface is shown below:

interface UserDao
{
    public function fetchRow($id);
    public function fetchAll();
    public function insert($data);
    public function update($id, $data);
    public function delete($id);
}

class UserDatabaseDao implements UserDao
{
    public function fetchRow($id)
    {
        $dataSource = Zf_Orm_Manager::getInstance()->getDataSource();
        $db = $dataSource->getConnection('slave');
        $query = $db->select()->from('user')->where('id = ?', $id);
        return $db->fetchRow($query);
    }

    public function fetchAll()
    {
        $dataSource = Zf_Orm_Manager::getInstance()->getDataSource();
        $db = $dataSource->getConnection('slave');
        $query = $db->select()->from('user');
        return $db->fetchAll($query);
    }

    public function insert($data)
    {
        $dataSource = Zf_Orm_Manager::getInstance()->getDataSource();
        $db = $dataSource->getConnection('master');
        $db->insert('user', $data);
        return $db->lastInsertId();
    }

    public function update($id, $data)
    {
        $dataSource = Zf_Orm_Manager::getInstance()->getDataSource();
        $db = $dataSource->getConnection('master');
        $condition = $db->quoteInto('id = ?', $id);
        return $db->update('user', $data, $condition);
    }

    public function delete($id)
    {
        $dataSource = Zf_Orm_Manager::getInstance()->getDataSource();
        $db = $dataSource->getConnection('master');
        $condition = $db->quoteInto('id = ?', $id);
        return $db->delete('user', $condition);
    }
}

The User Entity

An Entity is anything that has continuity through a life cycle and distinctions independent of attributes that are important to the application’s user.

class User
{
    protected $id;
    protected $firstName;
    protected $lastName;

    public function setId() {
    }
    public function getId() {
    }
    public function setFirstName() {
    }
    public function getFirstName() {
    }
    public function setLastName() {
    }
    public function getLastName() {
    }
    public function toArray() {
    }
}

The User DataMapper

class UserDataMapper extends Zf_Orm_DataMapper
{
    public function __construct()
    {
        $this->setMap(
            array(
                'id'         => 'id',
                'first_name' => 'firstName',
                'last_name'  => 'lastName'
            )
        );
    }
}

Source Code: http://fedecarg.com/repositories/show/datamapper

The User Repository

Repositories play an important part in DDD, they speak the language of the domain and act as mediators between the domain and data mapping layers. They provide a common language to all team members by translating technical terminology into business terminology.

Lets create a UserRepository class to isolate the domain object from details of the DAO:

class UserRepository
{
    private $databaseDao;

    public funciton setDatabaseDao(UserDao $dao)
    {
        $this->databaseDao = $dao;
    }

    public function getDatabaseDao()
    {
        if (null === $this->databaseDao) {
            $this->setDatabaseDao(new UserDatabaseDao());
        }
        return $this->databaseDao;
    }

    public function find($id)
    {
        $row = $this->getDatabaseDao()->fetchRow($id);
        $mapper = new UserDataMapper();
        $user = $mapper->assign(new User(), $row);

        return $user;
    }
}

The User Controller

class UserController extends Zend_Controller_Action
{
    public function viewAction()
    {
        $userRepository = new UserRepository();
        $user = $userRepository->find($this->_getParam('id'));
        if ($user instanceof User) {
            $id = $user->getId();
            $firstName = $user->getFirstName();
            $lastName = $user->getLastName();
            // get an array of key value pairs
            $row = $user->toArray();
        }
    }
}

That’s all, I hope you’ve found this post useful.

The Little Manual of API Design

This manual gathers together the key insights into API design that were discovered through many years of software development on the Qt application development framework at Trolltech (now part of Nokia). When designing and implementing a library, you should also keep other factors in mind, such as efficiency and ease of implementation, in addition to pure API considerations. And although the focus is on public APIs, there is no harm in applying the principles described here when writing application code or internal library code.

The Little Manual of API Design (PDF)

An Alternative to Zend_Controller

Zend Framework is very flexible and one of its strengths is that it allows developers to implement their own components. The Zend_Controller component, for example, is very powerful. Of course, it’s not my intention to replace it, but to offer an alternative that decreases the number of decisions a developer needs to make when developing an application.

Meet Zf_Controller. The Zf_Controller component has the following goals:

  • Abstract complexity: Try to reduce the level of details so the developer can focus on a few concepts at a time.
  • Emphasize Convention over Configuration: Emphasize CoC, meaning that the user only needs to specify unconventional aspects of the application.
  • Maintain backwards compatibility: Allow the developer to replace Zf_Controller with Zend_Controller in case the application grows in size or complexity.
  • Improve performance: Load less classes, execute less code.
  • Remove circular references: Avoid circular references.
  • Remove Singleton classes: Avoid implementing the Singleton pattern.
  • Research: Learn more about the framework, what it does, how it works.

Project Structure

Zend_Controller allows you to use the project structure that best suits your needs. On the other hand, Zf_Controller is more rigid, it only allows you to use the standard project structure:

project/
  app/
    config/
    controllers/
      ErrorController.php
      IndexController.php
    views/
      layouts/
      scripts/
        error/
        index/
          index.phtml
  domain/
    Model/
      Example.php
  lib/
    Zend/
    Zf/

Zf_Controller classes:

Zf/
  Controller/
    Action/
      Helper/
        Layout.php
    Action.php
    Front.php

Bootstrap File

Zend_Controller:

define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../app'));
set_include_path(APPLICATION_PATH . '/../lib'
    . PATH_SEPARATOR . get_include_path());

require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();

$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$routes = include_once APPLICATION_PATH . '/config/routes.php';
$router->addRoutes($routes);

$layout = Zend_Layout::startMvc();
$layout->setLayoutPath(APPLICATION_PATH . '/views/layouts');

$frontController->dispatch();

Zf_Controller (no Router):

define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../app'));
set_include_path(APPLICATION_PATH . '/../lib'
    . PATH_SEPARATOR . APPLICATION_PATH . '/../domain);

require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();

$frontController = new Zf_Controller_Front();
$frontController->setLayoutPath(APPLICATION_PATH . '/views/layouts');
$frontController->dispatch();

Action Controller

The default action controller and the default action are named “index”:

class IndexController extends Zf_Controller_Action
{
  public function indexAction()
  {}
}

Error Controller

Zend_Controller:

class ErrorController extends Zend_Controller_Action
{
  // Action used by Zend_Controller
  public function errorAction()
  {
    $error = $this->_getParam('error_handler');
    echo $error->exception->getMessage();
  }
}

Zf_Controller:

class ErrorController extends Zf_Controller_Action
{
  // Action used by Zf_Controller
  public function indexAction($e)
  {
    echo $e->getMessage();
  }
}

Rendering a View Script

Zf_Controller does not use the ViewRenderer helper class. To make the code more readable and testable, you need to call the render() method and return a value:

class IndexController extends Zf_Controller_Action
{
  public function indexAction()
  {
    $view = $this->initView();
    $view->message = 'Hello';

    // Renders views/scripts/index/index.phtml
    return $this->render();
  }

  public function testAction()
  {
    $view = $this->initView();
    $view->message = 'Goodbye';

    // Renders views/scripts/index/index.phtml
    return $this->render('index');
  }}

index.phtml file:

<p><?php echo $this->message ?></p>

Using a Layout

By setting the path to your layouts in the Bootstrap file, you automatically enable the default layout “layout.phtml”:

$frontController = new Zf_Controller_Front();
$frontController->setLayoutPath(APPLICATION_PATH . '/views/layouts');

To disable the layout:

class IndexController extends Zf_Controller_Action
{
    protected $_isLayoutEnabled = false;
}

To use a different layout:

class IndexController extends Zf_Controller_Action
{
    protected $_layoutScript = 'main.phtml';
}

main.phtml file:

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php echo $this->headTitle() ?>
<?php echo $this->headScript() ?>
<?php echo $this->headStyle() ?>
</head>
<body>
<div id="content"><?php echo $this->layout()->content ?></div>
</body>
</html>

Source Code:
http://svn.fedecarg.com/repo/Zf/Controller/

Implementing your own Front Controller in Zend Framework

There’s no doubt that the additional complexity of implementing the default Front Controller in ZF results in a number of benefits. The most important ones are flexibility and extensibility. The Front Controller implementation takes into consideration the future growth of your application and its design reduces the level of effort required to extend it. A good example of this is the plugin architecture.

But, what if after evaluating the requirements of your system, you determine that there’s not sufficient complexity to implement the default Front Controller? What if you don’t need all that flexibility, a URL mapper, a ViewRendered plugin or an ActionStack helper. Maybe all you need is just a couple of controllers, and that’s it. It’s clear that the standard Front Controller does provide more options and meets every possible use case requirement, but at the cost of complexity and a lot of classes.

So, what to do? Do you choose a different tool for the job, or replace the default Front Controller with your own implementation? How hard can it be? Is it really that difficult to replace the most important component of the Zend Framework and maintain backwards compatibility?

You are about to find out.

In this series of posts, I’ll try to cover a few things I’ve learned about implementing my own Front Controller in Zend Framework. Most of the ideas and code are based on my previous posts:

Will simplicity finally meet power?

Domain-Driven Design: Sample Application

Last updated: 15 Feb, 2010

Part 1: Domain-Driven Design and MVC Architectures
Part 2: Domain-Driven Design: Data Access Strategies
Part 3: Domain-Driven Design: The Repository

Some of the Domain-driven design concepts explained above are applied in this sample application.

Directory Structure

app/
    config/
    controllers/
        UserController.php
    domain/
        entities/
            User.php
            UserProfile.php
        repositories/
            UserRepository.php
    views/
lib/
public/

The domain layer should be well separated from the other layers and it should have few dependencies on the framework you are using.

User Entity

The User and UserProfile objects have a one-to-one relationship and form an Aggregate. An Aggregate is as a collection of related objects that have references between each other. Within an Aggregate there’s always an Aggregate Root (parent Entity), in this case User:

class User
{
    private $id;
    private $name;

    /* @var UserProfile */
    private $profile;

    public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }

    public function setProfile(UserProfile $profile)
    {
        $this->profile = $profile;
    }

    public function getProfile()
    {
        return $this->profile;
    }
}

class UserProfile
{
    private $id;

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

Users Collection

A collection is simply an object that groups multiple elements into a single unit.

class Users
{
    private $elements = array();

    public function __construct(array $users)
    {
        foreach ($users as $user) {
            if (!($user instanceof User)) {
                throw new Exception();
            }
            $this->elements[] = $user;
        }
    }

    public function toArray()
    {
        return $this->elements;
    }
}

User DAO

The UserDAO class allows data access mechanisms to change independently of the code that uses the data:

interface UserDao
{
    public function find($id);
    public function findAll();
}

class UserDatabaseDao implements UserDao
{
    public function find($id)
    {
        $dataSource = Zf_Orm_Manager::getInstance()->getDataSource()
        $db = $dataSource->getConnection('slave');
        $query = $db->select()->from('user')->where('id = ?', $id);
        return $db->fetchRow($query);
    }

    public function findAll()
    {
        ...
        return $db->fetchAll($query);
    }
}

interface UserProfileDao
{
    public function find($id);
    public function findByUserId($id);
}

class UserProfileDatabaseDao implements UserProfileDao
{
    public function find($id)
    {
        ...
    }

    public function findByUserId($id)
    {
        $dataSource = Zf_Orm_Manager::getInstance()->getDataSource()
        $db = $dataSource->getConnection('slave');
        $query = $db->select()->from('user_profile')->where('user_id = ?', $id);
        return $db->fetchRow($query);
    }
}

User Repository

A Repository is basically a collection of Aggregate Roots. Collections are used to store, retrieve and manipulate Entities and Value objects, however, object management is beyond the scope of this post. The Repository object can inject dependencies on demand, making the instantiation process inexpensive.

class UserRepository
{
    /* @var UserDatabaseDao */
    private $userDao;

    /* @var UserProfileDatabaseDao */
    private $userProfileDao;

    public function __construct()
    {
    	$this->userDao = new UserDatabaseDao();
    	$this->userProfileDao = new UserProfileDatabaseDao();
    }

    public function find($id)
    {
        $row = $this->userDao->find($id);
        $user = new User($row['id'], $row['name']);

        $row = $this->userProfileDao->findByUserId($id);
        if (isset($row['id'])) {
            $profile = new UserProfile($row['id']);
            $user->setProfile($profile);
        }

        return $user;
    }

    public function findAll()
    {
        $users = array();
        $rows = $this->userDao->findAll();
        foreach ($rows as $row) {
            $users[] = new User($row['id'], $row['name']);
        }
        return new Users($users);
    }
}

Usage:

$repository = new UserRepository();
$user = $repository->find(1);
$profile = $user->getProfile();
$users = $repository->findAll();

Source Code

http://svn.fedecarg.com/repo/Zf/Orm

Links

If you’re interested in learning more about Domain-driven design, I recommend the following articles:

Domain Driven Design and Development In Practice
Domain-Driven Design in an Evolving Architecture