• 2010-02-02 12:00:00

    Design Patterns - Factory

    A note about these series. It appears that Giorgio Sironi and I had the same idea regarding Design Patterns and blogging about them. He covers the Factory design pattern thoroughly in his blog post, which is recommended reading.

    The Problem

    I started off my IT career as a network administrator. This was back in the good old Novell 3.11 days. After that it was Novell 4.0, Microsoft Servers etc. Following that I got more and more involved with Visual Basic and when Microsoft decided to move everyone to .NET I chose not to follow and ended up coding in PHP.

    Since my programming knowledge came from within (studying, reading articles, trial and error), the problems that I was facing on a daily basis are the same as almost every developer faces. One particularly challenging problem that I had in the VB days as well as the PHP days was repetition of code and how to eliminate it.

    When I started programming for the Ferrari Fans Fun Forecast site I was running the site using my apartment's ADSL line. In the beginning there were only 20 users or so, therefore that setup was fine. The scripts were VBScript against a local instance of Microsoft SQL Server. Later on though, I switched to PHP while keeping Microsoft SQL Server.

    Initial implementation

    I knew that I would have to change my scripts later on to work against MySQL since I was to change the hosting of the site. Through laziness or poor design (you can pick either or both :)) I chose to create a class for Microsoft SQL and later on I would just change it to the MySQL. It seemed the easiest thing to do at the time.

    So my class was something like:

     class DbMSSQL
    {
        private $_conn = null;
    
        public function connect()
        {
            // Connect
            // This is where we have the connection parameters
            include_once 'connection.inc.php';
    
            $this->_conn = mssql_connect($host, $user, $password);
            if (!$this->_conn) {
                throw new Exception('Cannot connect to the database.');
            }
        }
    
        public function disconnect()
        {
             // Disconnect
            mssql_close($this->_conn);
        }
    
        public function selectdb()
        {
             // Select the db
            $db = mssql_select_db($database, $this->_conn);
            if (!$db) {
                throw new Exception('Cannot select the database');
            }
        }
    
        public function query($sql)
        {
         // Query the db
            $_result = mssql_query($sql);
    
            if (!$_result) {
                throw new Exception('Error in query : ' . $sql);
            }
    
            $data = array();
    
            while ($row = mssql_fetch_assoc($_result)) {
                $data[$row['id']] = $row;
            }
    
            mssql_free_result($_result);
    
            return $data;
        }
    }
    

    Everything worked fine so I did not worry about a thing. A few months later though I was forced to move the database (as I expected) to MySQL. I could not move everything in one go so I had to move some of the tables initially and a week later everything else.

    To tackle this requirement I created a second class to handle operations against MySQL. The class that I ended up with was:

    class DbMySQL
    {
        private $_conn = null;
    
        public function connect()
        {
            // Connect
            // This is where we have the connection parameters
            include_once 'connection.inc.php';
    
            $this->_conn = mysql_connect($host, $user, $password);
            if (!$this->_conn) {
                throw new Exception('Cannot connect to the database :' . mysql_error());
            }
        }
    
        public function disconnect()
        {
             // Disconnect
            mysql_close($this->_conn);
        }
    
        public function selectdb()
        {
             // Select the db
            $db = mysql_select_db($database, $this->_conn);
            if (!$db) {
                throw new Exception('Cannot select the database : ' . mysql_error());
            }
        }
    
        public function query($sql)
        {
         // Query the db
            $_result = mysql_query($sql);
    
            if (!$_result) {
                throw new Exception('Error in query : ' . mysql_error() . "\n" . $sql);
            }
    
            $data = array();
    
            while ($row = mysql_fetch_assoc($_result)) {
                $data[$row['id']] = $row;
            }
    
            mysql_free_result($_result);
    
            return $data;
        }
    }
    

    You can easily see the problem here. There is a lot of repetition in the code, not so much as the actual method properties but the methods themselves. Both classes have connect(), disconnect(), selectdb() and query() as methods. In reality the code changes only slightly since the call for an operation against Microsoft SQL Server is mssql_* while for MySQL is mysql_*. During the transition week I was in programming hell. At some point I mixed the class names, I was trying to read and update the wrong server etc. (see Jani Hartikainen's post about 6 programming project mistakes you should avoid - I did all that!).

    That week though taught me that I need to pay more attention in designing rather than going full speed ahead with programming and later on paying the consequences.

    After thorough research, I discovered a library that would support both platforms. The library that I found was ADOdb which is a perfect example of the Factory Pattern. I used that library later on for a different project, but just looking at the code and understanding the flow of operations as well as the implementation of the pattern itself was invaluable to me.

    Interfaces

    First of all I need to explain what an interface is and why we need them. According to PHP.net:

    Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.

    So imagine an interface something like a graft, a blueprint on what I need to construct. The Interface will have the common methods and properties that I need to implement.

    When dealing with database connections to two different database servers (Microsoft SQL Server and MySQL), I can clearly define a few methods that will follow CRUD (Create, Read, Update, Delete). Those are:

    • Connect to the database server
    • Select database
    • Insert record
    • Delete record
    • Update record
    • Select record(s)
    • Close connection to the database server

    My interface would therefore be:

    interface iDatabase
    {
        public function connect();
        public function disconnect();
        public function selectdb();
        public function query($sql);
    }
    

    Design Patterns - Factory

    A class implementing the Factory Pattern is like a car manufacturing plant producing three different cars on the same assembly line. All cars have common characteristics like 4 wheels, 4 doors (well most of them), a steering wheel, a dashboard etc. and all of them perform certain operations i.e. drive, reverse etc.

    In my problem earlier I could have used the Factory Pattern to create one class that would have implemented my blueprint, the interface which defines the CRUD operations that I need. So based on the above, the implementation will result in three classes.

    MSSQL class - stored in the file Db_mssql.php
    class Db_mssql implements iDatabase
    {
        private $_conn = null;
    
        public function connect()
        {
            // Connect
            // This is where we have the connection parameters
            include_once 'connection.inc.php';
    
            $this->_conn = mssql_connect($host, $user, $password);
            if (!$this->_conn) {
                throw new Exception('Cannot connect to the database.');
            }
        }
    
        public function disconnect()
        {
             // Disconnect
            mssql_close($this->_conn);
        }
    
        public function selectdb()
        {
             // Select the db
            $db = mssql_select_db($database, $this->_conn);
            if (!$db) {
                throw new Exception('Cannot select the database');
            }
        }
    
        public function query($sql)
        {
         // Query the db
            $_result = mssql_query($sql);
    
            if (!$_result) {
                throw new Exception('Error in query : ' . $sql);
            }
    
            $data = array();
    
            while ($row = mssql_fetch_assoc($_result)) {
                $data[$row['id']] = $row;
            }
    
            mssql_free_result($_result);
    
            return $data;
        }
    }
    
    MySQL class - stored in the file Db_mysql.php
    class Db_mysql implements iDatabase
    {
        private $_conn = null;
    
        public function connect()
        {
            // Connect
            // This is where we have the connection parameters
            include_once 'connection.inc.php';
    
            $this->_conn = mysql_connect($host, $user, $password);
            if (!$this->_conn) {
                throw new Exception('Cannot connect to the database :' . mysql_error());
            }
        }
    
        public function disconnect()
        {
             // Disconnect
            mysql_close($this->_conn);
        }
    
        public function selectdb()
        {
             // Select the db
            $db = mysql_select_db($database, $this->_conn);
            if (!$db) {
                throw new Exception('Cannot select the database : ' . mysql_error());
            }
        }
    
        public function query($sql)
        {
         // Query the db
            $_result = mysql_query($sql);
    
            if (!$_result) {
                throw new Exception('Error in query : ' . mysql_error() . "\n" . $sql);
            }
    
            $data = array();
    
            while ($row = mysql_fetch_assoc($_result)) {
                $data[$row['id']] = $row;
            }
    
            mysql_free_result($_result);
    
            return $data;
        }
    }
    

    Notice that both these classes are almost identical to the initial implementation shown earlier in this post. The only difference is that they are both implementing the iDatabase interface.

    So what is different now? The class that implements the Factory Pattern.

    class Db
    {
        public static function factory($type)
        {
            $fileName = 'Db_' . strtolower($type) . '.php';
            if (!file_exists($fileName)) {
                throw new Exception('File not found : ' . $fileName);
            }
    
            $className = 'Db_' . strtolower($type);
    
            return new $className;
        }
    }
    

    What this class does now is it allows me to load the relevant database connection class on the fly. If I want a Microsoft SQL connection I would call:

        $mssql = Db::factory('mssql');
    

    while for MySQL the command becomes:

        $mysql = Db::factory('mysql');
    

    Again since both underlying classes implement the iDatabase interface, I know exactly what to expect as far as methods and functionality is concerned from each class.

    Conclusion

    The Factory Design Pattern is one of the most powerful design patterns. It provides 'decoupling' i.e. breaks the inherited dependency of a class and its subclasses. It also allows for great flexibility while keeping the same interface for your clients.

    Zend Framework uses the Factory Pattern in Zend_Db. Specifically the example on the site shows:

    // We don't need the following statement because the
    // Zend_Db_Adapter_Pdo_Mysql file will be loaded for us by
    // the Zend_Db factory method.
    
    // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
    
    // Automatically load class Zend_Db_Adapter_Pdo_Mysql
    // and create an instance of it.
    $db = Zend_Db::factory(
        'Pdo_Mysql', 
        array(
            'host'     => '127.0.0.1',
            'username' => 'webuser',
            'password' => 'xxxxxxxx',
            'dbname'   => 'test'
        )
    );
    

    The Zend_Db factory accepts the name of the adapter used for the database connection as the first parameter while the second parameter is an array with connection specific information. With the use of the Factory Pattern, Zend_Db exposes a common interface which allows programmers to connect to a number of databases using the same methods. Should in the future the application needs to access a different database, the impact to the developer is minimal - in most cases a change to the adapter name (first parameter of the factory class) is all it takes.

  • 2010-01-22 12:00:00

    Design Patterns - Singleton

  • 2010-01-06 12:00:00

    Design Patterns in PHP Series

    A lot of developers – including myself – have at some point in their programming careers found themselves repeating a task that they have completed for a previous project or for a previous part of the same project.

    This problem of repeating code is solved by design patterns. A design pattern is the way that the code must be structured so that the problem at hand can be solved. The characteristics of design patterns are:

    • Name – it lets other programmers know what this pattern does.
    • Problem – where the pattern can be applied
    • Solution – how this pattern is implemented

    In the course of the next few weeks, I will publish a series of blog posts, where I will try to present you with some common design patterns and how I have understood their use. Most books and online materials concentrate on just presenting the issue at hand and do not focus on how we ended up there. In these blog post series I will try to show you what I found along the way and how I solved each problem in turn.

    As usual comments are more than welcome.

    The design patterns I will discuss in posts of these series are as:

    • Singleton Pattern
    • Factory Pattern
    • Registry Pattern
    • Decorator Pattern
    • Adapter Pattern
    • Iterator Pattern
    • Strategy Pattern
    • Active Record Pattern
    • Value Object Pattern
    • Model View Controller Pattern
    • MockObject Pattern
    • Observer Pattern
    • Proxy Pattern
    • Table Data Gateway Pattern
    • Data Mapper Pattern

    You can check this blog every week, subscribe to the RSS feed, follow me on Twitter or follow my Google Reader (or all of the above).

  • 2009-12-15 12:00:00

    URL beautification in PHP

    Preface

    The last few years I have been using Quicken to manage the home bank accounts and spending. My wife never had any problems with me doing so and it helps us manage our cash flow better. Of course like every couple we buy things that we need and always provision a small amount of money for personal expenses.

    Some time ago when downloading the transactions from our bank, I noticed a rather odd name coming in for a very small charge (less than 20 dollars). So I asked my wife what that shop is. Her response was Beautification. My reply was What do you mean? You don't need anything - you are gorgeous as is.... Although this did earn me brownie points it also infuriated my wife since she was thinking I was auditing her. My sole purpose of that question was to assess the category of the expense and move on. I was not interested the least about the particulars of the expense. I got my reply - a detailed one - as to what the item was for (makeup really) and once my wife finished I explained to her that all this explanation was unnecessary and all I needed was Personal Care.... The night ended in laughter as you can imagine and since then we always refer as Beautification when we pass the makeup area in the grocery store.

    The purpose of this post is not to try to make you go buy makeup. It is however a post that can show you how you can make your application's behavior as far as URLs are concerned prettier.

    Beautification in URLs is also known as Pretty URLs. It is a method where mod_rewrite is used to make a URL look easier to remember. Although this process started in an attempt to increase SEO and make a site's URLs easier to index/follow, it has now become a must for every site that wants to create awareness and make people remember as much as possible so that they can revisit. Wordpress (this blog's blogging software) as well as other blogging software use this methodology to ensure that the posts are easily indexed and remembered (see the URL of this post and the title of this post).

    Beautification

    First Step

    Instead of rewriting my whole application to have beautiful and easy to remember URLs, I started with changing the way I processed parameters. Imagine the scenario where I have a site with various pages and one script that processes everything. My URL could be something like:

    ..../site.php?page=contact-us
    ..../site.php?page=about
    

    Following discussions with other developers and reading the web the URL was beautified as:

    ..../site.php?page/contact-us
    ..../site.php?page/about
    

    This is one parameter, so in my bootstrap I have the following snippet:

    $getData      = array();
    $params       = explode('/',$_SERVER['QUERY_STRING']);
    $params[]     = '';
    $paramsLength = sizeof($params);
    
    for ($counter = 0; $counter < $paramsLength; $counter++) {
        $getData[$params[$counter]] = (isset($params[$counter + 1])) ? $params[$counter + 1] : '';
    }
    
    unset($_GET);
    

    The $getData array contains the parameters that have been passed and allows all search engines to index the URL a lot easier since this is considered to be one parameter.

    Please note that I am not going to expand on security here. In my production code there are multiple checks on the variables passed so as to ensure that there are no SQL injection vulnerabilities.

    A better approach with .htaccess

    In order to make the URL look a lot more beautified, I need to remove the script name and the question mark of the query string. So my URL can easily be like:

    ..../page/contact-us
    ..../page/about</pre>
    

    To achieve this, I need (in Apache) modrewrite enabled and a couple of directives in httpd.conf

    Options +FollowSymLinks
    RewriteEngine On
    

    If your configuration is on a virtual host, you can add these directives in your vhosts file.

    The .htaccess file that I have in the root folder of my site has the following directives:

    Options       +FollowSymLinks
    RewriteEngine On
    RewriteCond   %{SCRIPT_FILENAME} !-d
    RewriteCond   %{SCRIPT_FILENAME} !-f
    RewriteRule   .* site.php [L]</pre>
    

    What the above file does is pass everything in the site.php script. The processing now falls in the site.php script. At the top of the script I have:

    <?php
    
    // This is where we get all the parameters
    $params = $_SERVER['REQUEST_URI'];
    
    if (substr('/', $params) > 0) {
        switch ($params) {
            case '/page/contact-us':
                include 'contact_us.php';
                break;
            case '/page/about':
                include 'about.php';
                break;
            default:
                include 'filenotfound.php';
                break;
        }
    
    // No parameters passed - display something default
    } else {
       include 'filenotfound.php';
    }
    

    From here on the possibilities are endless. I can add more logic to the rewrite rules so that everything ends in .html for instance, making search engines think that they are visiting unique html pages. Discussion forum software uses this technique to make their content easily searchable. For instance a URL like:

    /showpost.php?p=557799
    

    can be shown as:

    /show/post/post/557799
    

    or

    /show/post/post-557799.html
    

    Something like the above can be achieved with the following rule in .htaccess:

    Options       +FollowSymLinks
    RewriteEngine On
    RewriteRule   ^post-([0-9]+)+\.html$ /showpost.php?p=$1 [NC,L]</pre>
    
    Zend Framework

    If I want to push the envelope further I will need to use Zend Framework to do all this effortlessly. Zend Framework's front controller provides amazing flexibility in terms of how my application URLs can be displayed on the web.

    Zend_Controller_Router_Route, Zend_Controller_Router_Route_Static and Zend_Controller_Router_Rewrite are some of the types of routes available in the front controller. Using a configuration file or issuing relevant directives in the bootstrap file are options that I can use to manipulate my application's URLs.

    By default the front controller uses the controller/action scheme but I can easily change this using a router and adding that router to my controller.

    $router = $frontController->getRouter();
    
    $router->addRoute(
        'post',
        new Zend_Controller_Router_Route(
            'post/:post',
            array('controller' => 'post',
                  'action' => 'show'))
        );
    

    This is a small example on how a simple controller/action sequence can still work as expected and the resulting URL is beautified.

    Final thoughts

    Having easy to remember URLs in an application is a must. It will not only help search engines crawl your site easier - thus making your site more easily discoverable - but it will also help your users remember key areas of your site.

    Zend Framework is by far one of the best solutions available, since it introduces a small learning curve in terms of routing and mod_rewrite while providing pretty URLs. However, for more a complicated rewriting scheme your application might need a very sophisticated .htaccess file.

  • 2009-12-11 12:00:00

    Variables in php.ini

    In my workplace we have been using Zend Framework for more than a year primarily as a glue framework. We have managed to integrate a lot of components from the framework to suit our needs and slowly we are moving towards the full MVC pattern.

    In the meantime our own framework, or collection of code if you prefer, is slowly evolving with every new project. New classes are added while others are enhanced more to provide more flexible input/output. Add to that the continuous evolution of Zend Framework and we are faced with at least one version of our own codebase per project.

    Lately we have been following a more Test Driven Development approach, where we create tests for every component we create or alter. After all this is the purpose of TDDevelopment - to make sure that your code has 100% coverage and that it works!

    The same thing applies when a new version of Zend Framework is released. We download the latest version on the development boxes and run our tests against it. If something has changed and/or is broken we just fix it and our framework is ready for the next project.

    Following this approach, the bulk of our projects are running the latest code (Zend Framework and our own framework). There are however a number of projects that we need to run against an older version of Zend Framework. The reasons for not are not enough money for updating, not enough time, it works so don't tinker with it to name a few.

    So how do we deal with the issue of having different versions of Zend Framework on our servers and including the correct version to the relevant project? The solution that we use is variables in php.ini.

    For starters we have a network share mounted on all of our development servers (the ones that are in house). This share we call it /resources. In there we have all the needed Zend Framework versions i.e.:

    gemini ~ # ls -la /resources/ZendFramework/
    total 0
    drwxrwxr-x 8 webuser webdev 192 Nov  5 05:48 .
    drwxr-xr-x 7 webuser webdev 168 Jul 17 10:55 ..
    drwxrwxr-x 3 webuser webdev  72 Jun 23 13:48 1.0.3
    drwxrwxr-x 5 webuser webdev 216 Apr 21  2009 1.5.2
    drwxrwxr-x 7 webuser webdev 280 Apr 21  2009 1.6.2
    drwxrwxr-x 8 webuser webdev 304 Apr 21  2009 1.7.8
    drwxrwxr-x 8 webuser webdev 296 Jun  8  2009 1.8.3
    drwxrwxr-x 8 webuser webdev 296 Oct 26 12:52 1.9.5
    

    Since this is a network share, all we do is update one location and all servers have access to the same pool of files.

    We also modify the php.ini file of each server, adding the following directives at the end of the file:

    [ZendFramework]
    ZF_LATEST="/resources/ZendFramework/1.9.5/library"
    ZF_1_9_5="/resources/ZendFramework/1.9.5/library"
    ZF_1_8_3="/resources/ZendFramework/1.8.3/library"
    ZF_1_7_8="/resources/ZendFramework/1.7.8/library"
    ZF_1_6_2="/resources/ZendFramework/1.6.2/library"
    ZF_1_5_2="/resources/ZendFramework/1.5.2/library"
    ZF_1_0_3="/resources/ZendFramework/1.0.3/library"
    

    Restarting apache gives us access to those variables using the get_cfg_var PHP function. So in our bootstrap file (called init.php) we have the following:

    $zfPath = get_cfg_var('ZF_1_9_5');
    
    $root = dirname(__FILE__);
    
    set_include_path(
        $zfPath           . PATH_SEPARATOR .
        $root    . '/lib' . PATH_SEPARATOR .
        $root             . PATH_SEPARATOR .
        get_include_path()
    );
    

    Changing to a different version of the Zend Framework can be as easy as changing the path of the ZF_* directive in the php.ini file (and restarting Apache) or by changing the variable we need to use in the init.php file of each project.

    This approach allows us to keep our include_path free from any Zend Framework paths since the server has projects that use different versions of the Zend Framework as well as ours. It also helps us in testing, since we can easily check whether a particular project works as expected in a newer or older version of each framework.

    We opted out from using constants inside .htaccess files, due to the fact that we have many projects and this would have meant that we had to change every .htaccess file, should we wanted to change the version of Zend Framework used.

    php.ini has a lot of directives that can prove useful for the PHP developer. Extending those directives to each project or collection of projects can save you time and headaches.

  • 2009-12-01 14:00:00

    The world with Angular - Part III

    Continued from Part II

    Presentation of Data

    Presenting data with <angular/> is really easy. All we need to do is to tell <angular/> how we want the data to be presented and where.

    From Part II you have seen that I have declared an entity called Incident. Also in the <body> tag I have initialized the <angular/> engine, requested all() the Incident objects and stored them in the incidents variable.

    <body ng-entity="incident=Incident" ng-init="incidents=Incident.all()">
    

    I am creating a HTML table where I will display all the records. The header of the table is as follows:

    <tr>
      <th> </th>
      <th>Date</th>
      <th>Shift Start/End</th>
      <th>Animal Code</th>
      <th>Situation Code</th>
      <th>Resolution Code</th>
      <th>City</th>
      <th>State</th>
      <th>Description</th>
    </tr>
    

    Now I need to show the data on screen. I can reference the variables that I have used earlier in my input elements i.e. incident.shiftstart, incident.shiftend, incident.animalcode etc. The variables represent the fields of each record so incident is the document/record if you like and animalcode is the field. If I add them just like that, <angular/> will correctly show me data but only one record since it will not know otherwise. As usual I will need a loop for this. The loop will work directly on the <tr> definitions to give me a row per record.

    <tr ng-repeat="record in incidents">
      <td class="centercell" style="white-space:nowrap;">
        E D
      </td>
      <td class="centercell">{{record.shiftdate}}</td>
      <td class="centercell">{{record.shiftstart}}<br />{{record.shiftend}}</td>
      <td class="centercell">{{record.animalcode}}</td>
      <td class="centercell">{{record.situationcode}}</td>
      <td class="centercell">{{record.resolutioncode}}</td>
      <td class="centercell">{{record.city}}</td>
      <td class="centercell">{{record.state}}</td>
      <td>{{record.details}}</td>
    </tr>
    

    I am using the ng-repeat directive to repeat that block of code. Since I am using it in a <tr> the ng-repeat will match the closing tag for that element i.e. </tr>. ng-repeat repeats that block of code for every recordin incidents. incidentsis the variable I have stored all the results earlier from the <body> declaration. Each piece of information is stored in the database and referenced the same way that it was stored. Note that I have used the variable name recordto access the loop elements but I could have used anything I liked. recordrefers to one object of the incidentsvariable at a time.

    The full block of code is below:

    <table style='width:100%'>
    <tr>
      <th> </th>
      <th>Date</th>
      <th>Shift Start/End</th>
      <th>Animal Code</th>
      <th>Situation Code</th>
      <th>Resolution Code</th>
      <th>City</th>
      <th>State</th>
      <th>Description</th>
    </tr>
    <tr ng-repeat="record in incidents">
      <td class="centercell" style="white-space:nowrap;">
        E D
      </td>
      <td class="centercell">{{record.shiftdate}}</td>
      <td class="centercell">{{record.shiftstart}}<br />{{record.shiftend}}</td>
      <td class="centercell">{{record.animalcode}}</td>
      <td class="centercell">{{record.situationcode}}</td>
      <td class="centercell">{{record.resolutioncode}}</td>
      <td class="centercell">{{record.city}}</td>
      <td class="centercell">{{record.state}}</td>
      <td>{{record.details}}</td>
    </tr>
    </table>
    

    So now I have a basic application that allows me to store and display data. If you have tried this code so far and run it, you will see that the data is entered immediately on the screen and there are no page refreshes which significantly enhances the user experience.

    You might have noticed that I have "E D" in the first column of every row of the HTML table. These are for Edit and Delete.

    Editing Data

    Each record has a unique identifier as I showed you earlier when adding records. In order for the "E" to link to the respective record, I need to use that id. The hyperlink around the "E" becomes then:

    <a href="#incident={{record.id}}">E</a>
    

    Every document/record has an id field. I can it as usual with the double brackets and referencing the incident loop variable (inside the <tr> loop). Note that since I have decided to name my entity incident, I am referencing each record with that parameter in the URL. If my entity's name was different, say testentity, then the URL would have changed to:

    <a href="#testentity={{record.id}}">E</a>
    

    html

    Deleting Data

    To delete data, instead of referencing the unique identifier of each record, I will use the record variable and the $delete() method on it. Note that the recordvariable is the one that allows us to have access to every object in the incidentsvariable and it is used in the display data loop.:

    <a href="#" ng-action="record.$delete()">D</a>
    
    Searching Data

    The initial design never catered for emptying the database in regular intervals. Therefore a search function is in order to ensure quick retrieval of information. As you will see it is really easy and it does not need any <form> elements or anything else.

    The search box is just an <input> element with a specific name (which can be whatever you like)

    [ Search: <input name="wrlfilter" /> ]
    

    This piece of code appears above the table that displays data in my example. I need to make one more change to ensure that the data is filtered. The change is in the <tr> statement where I run the loop to display the data. So the block of code:

    <tr ng-repeat="record in incidents">
    

    becomes

    <pre class="brush:html"><tr ng-repeat="record in incidents.$filter(wrlfilter)">
    

    As you can see I am using the $filter() method and the parameter passed is the name of the input box that I have defined earlier. This way whatever I type in the search box, <angular/> will try to match it with the currently displayed data and filter accordingly, thus giving me the search functionality that I want.

    Sorting data

    Another easy task in <angular/> is sorting. Since I already have a table that I present data with, I am going to use that and its table headings to allow my user to sort. Also I am going to have a default sorting option of Shift Date descending and Shift Start descending.

    In general sorting is done by the $orderBy(), $orderByToggle() and $orderByDirection() methods. The + or - prefixing the name of a field passed defines ascending or descending order. To create a compound sorting key with multiple fields I need to enclose the field names in quotes and separate them with commas.

    First of all I need to initialize the sorting mechanism. The best place for that is the table that displays the data. Therefore I get:

    <table style='width:100%' ng-init="wrlorder=['-shiftdate','-shiftstart']">
    

    This statement initializes the wrlorder variable to contain a shiftdate and a shiftstart field in descending order. Note that the shiftdate and shiftstart are the same names of the fields that I have used throughout this article.

    I save my changes and reload the page but there is no sorting. I actually haven't told <angular/> what data to sort. Since the data that I want to sort are in the table, I will enhance my $filter() method with an $orderBy(). This is the statement that we have worked with earlier.

    <tr ng-repeat="record in incidents.$filter(wrlfilter).$orderBy(wrlorder)">
    

    Save and refresh and voila! The results are sorted by Shift Date descending and Shift Start descending. If I enter a new record, it will be displayed on screen sorted in the correct position. Note that the statement above allows for a combination of methods to be run against the incidents variable (filter and sort).

    For the purposes of this exercise and for debugging, I have also added the wrlorder variable next to the search box so that I know what my sort fields are.

    [ Search: <input name="wrlfilter" /> ] - [ Order: {{wrlorder}} ]
    

    Refreshing the page shows me now

    - [ Order: -shiftdate, -shiftstart ]
    

    I am nearly there. All I need to do now is to make the table headings clickable so that the data is sorted anyway I want to. I will use the $orderByToggle() and $orderByDirection() methods on the wrlorder variable. My table heading becomes:

    <th> </th>
    <th>
        <a href="" 
           ng-action="order.$orderByToggle('shiftdate')" 
           ng-class="order.$orderByDirection('shiftdate')">Date</a>
    </th>
    <th>
        <a href="" 
           ng-action="order.$orderByToggle('shiftstart')" 
           ng-class="order.$orderByDirection('shiftstart')">Shift Start</a>/
        <a href="" 
           ng-action="order.$orderByToggle('shiftend')" 
           ng-class="order.$orderByDirection('shiftend')">End</a>
    </th>
    <th>
        <a href="" 
           ng-action="order.$orderByToggle('animalcode')" 
           ng-class="order.$orderByDirection('animalcode')">Animal Code</a>
    </th>
    <th>
        <a href="" 
           ng-action="order.$orderByToggle('situationcode')" 
           ng-class="order.$orderByDirection('situationcode')">Situation Code</a>
    </th>
    <th>
        <a href="" 
           ng-action="order.$orderByToggle('resolutioncode')" 
           ng-class="order.$orderByDirection('resolutioncode')">Resolution Code</a>
    </th>
    <th>
        <a href="" 
           ng-action="order.$orderByToggle('city')" 
           ng-class="order.$orderByDirection('city')">City</a>
    </th>
    <th>
        <a href="" 
           ng-action="order.$orderByToggle('state')" 
           ng-class="order.$orderByDirection('state')">State</a>
    </th>
    <th>
        <a href="" 
           ng-action="order.$orderByToggle('details')" 
           ng-class="order.$orderByDirection('details')">Description</a>
    </th>
    

    The ng-action allows for the interchange in sorting order (ascending/descending) while the ng-class shows a nice arrow next to the header name, indicating the current sort order.

    Refreshing the page shows me the final product. I can now sort in any way I like and the sorting is compounded.

    Widgets

    <angular/> has a lot of widgets that can be used as validators but also as means to enhance the user experience. One of them is the DatePicker. I am going to use it to collect data in the shiftdate field. So the:

    <input name="incident.shiftdate" />
    

    becomes:

    <input name="incident.shiftdate" ng-widget="datepicker" size="8" />
    

    and that's it. Now when I click on the input box or when it gets focus, a nice dropdown calendar appears that allows me to select the date.

    Final thoughts

    The example above is not the final product for the WRL. There are some things missing, such as clearing up the order, enhancing the search, expanding/collapsing the add new record etc. This article is not meant as the final solution but more as a guide on what is feasible.

    <angular/> is definitely a new way of looking at web programming. It is fast, agile and easy to learn. <angular/> provides the hobbyist a tool that they can use to create an online application that will suit their needs without complex installations, expensive hosting companies, RDBMS management etc. I can also see experienced programmers using it to address a quick fix or a very urgent requirement that demands RAD.

    I encourage you to visit getangular.com} and give <angular/> a try. I am sure you will not be disappointed.

  • 2009-12-01 13:00:00

    The world with Angular - Part II

    Continued from Part I

    The Wildlife Rescue League application

    Design

    For those that do not know, the Wildlife Rescue League

    is a non-profit organization providing care for sick, injured and orphaned wildlife in order to return them to the wild. Our licensed rehabilitators, located throughout Virginia and suburban Maryland, work with animal shelters, humane societies, wildlife groups, nature centers and veterinary hospitals to provide care to creatures in need. WRL operates a wildlife hotline in the Northern Virginia and surrounding areas to assist the public in obtaining information and assistance in locating a wildlife rehabilitator. WRL is also committed to educating the public about the natural history of native wildlife, coexisting with it and preventing the need for wildlife rehabilitation. We can provide brochures, educational material and educational programs to suit your needs.

    The WRL hotline records all phone calls that the volunteers answer and organizes that data in a manner that would help the organization in the future (anticipated call volume etc.) In the past the data collection method was a simple sheet of paper that was mailed to one volunteer, who then had to decode everything and create the relevant spreadsheet for data analysis. Later on this model evolved into a spreadsheet which was copied and distributed to the volunteers. Again the data had to be collected (via email now) and merged for a meaningful analysis to take place.

    I have therefore created a simple application using <angular/> to allow the volunteers to enter their data in a centralized repository. I am going to explain in detail how I utilized <angular/> to perform this task, needing only a few hours (mostly spent in cosmetic changes) until I had a working copy of what I wanted.

    This blog post will be missing the authentication mechanism and a couple of other bits and pieces. I am hoping to show you a different way or programming and encourage you to explore <angular/> and its power.

    Thinking about my application I will need to store the data. I will need the following fields:

    Date
    Shift Start
    Shift End
    Animal Code
    Situation Code
    Resolution Code
    City
    State
    Description of incident
    
    Creating the database

    The data needs to be stored in the database. So logging into my account in getangular.com (do so if you haven't done this already) I created my library and my new database (both called testwrl) and I am set. Everything else will be controlled in the HTML document.

    Initial HTML file

    My HTML file is very simple.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    <meta http-equiv="Content-Type"
          content="text/html; charset=utf-8" />
    <meta name="robots" content="index, follow" />
    <style type="text/css">
    body {
        font-family:Verdana,Arial,Helvetica;
        font-size:10pt;
    }
    th,td {
        text-alignment:center;
    }
    th, .inputBox {
        background:#000066;
        color:#00FF00;
        font-weight:bold;
    }
    .incident {
        border:1px solid #000000;
    }
    .incidentheader {
        padding:5px;
        border:1px solid #000000;
        font-weight:bold;
        background:#000099;
        color:#00EE00;
    }
    .centercell {
        text-align:center;
    }
    img {
        border:none;
    }
    </style>
    <script type="text/javascript"
            src="http://testwrl.getangular.com/angular-1.0a.js#database=testwrl"></script>
    </head>
    <body>
    </body>
    </html>
    

    Note the JavaScript line at the bottom part of the snippet. It references a subdomain of getangular.com (testwrl.getangular.com) as well as the database I am using to store data (database=testwrl).

    Creating the HTML input elements

    I need to create a form to store the data. The programming is done with HTML <input> elements. Once I have everything mapped nicely on screen I need to bind them in the database. First of all I need to describe what I want to work with. I will use the ng-entity attribute in my body element. The ng-entity uses the expression [instance=]Entity[:template]. Effectively Entity is the name of the entity that will be stored in my database under that name.

    Therefore in my HTML file I need to change the body element:

    <body ng-entity="incident=Incident" ng-init="incidents=Incident.all()">
    

    So I am storing the Incident in the database. incident is the document of this entity (Incident) that is stored under the name of that instance.

    The ng-init declaration in the body element assigns all the records of the entity Incident (Incident.all()) to a variable (incidents). The name of the variable is arbitrary - you can choose whatever you like.

    Since incident is the document, I need to reference all my elements (the input ones) towards that. The way this is done is via the name attribute of each of the HTML elements. So for instance for the Date that I want to store, my HTML input declaration changes to:

    <input name="incident.shiftdate" />
    

    I repeat the same methodology and I name my elements incident.shiftstart, incident.shiftend, incident.animalcode etc.

    Notable is the fact that I haven't used the <form> element at all. I am going to add a Save button at the end of this HTML block which is nothing more than a submit element:

    <input type="submit" value="Save" />
    

    <angular/> takes care of all the data posting from the browser to the server so I do not need any <form> elements and POST control.

    The HTML script as is right now is below:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    <meta http-equiv="Content-Type"
             content="text/html; charset=utf-8" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Expires" content="-1" />
    <meta http-equiv="Cache-Control" content="no-cache" />
    <meta name="description"
             content="Wildlife Rescue League Hotline" />
    <meta name="keywords"
             content="WRL, wildlife, hotline, volunteer work" />
    <meta name="robots" content="index, follow" />
    <style type="text/css">
    body {
      font-family:Verdana,Arial,Helvetica;
      font-size:10pt;
    }
    th,td {
      text-alignment:center;
    }
    th, .inputBox {
      background:#000066;
      color:#00FF00;
      font-weight:bold;
    }
    .incident {
      border:1px solid #000000;
    }
    .incidentheader {
      padding:5px;
      border:1px solid #000000;
      font-weight:bold;
      background:#000099;
      color:#00EE00;
    }
    .centercell {
      text-align:center;
    }
    img {
      border:none;
    }
    </style>
    <script type="text/javascript"
      src="http://testwrl.getangular.com/angular-1.0a.js#database=testwrl"></script>
    </head>
    <body ng-entity="incident=Incident" ng-init="incidents=Incident.all()">
      <span style='float:right;font-size:10px;'>
        Powered by <a href='http://www.getangular.com'>`<angular/>`</a>
      </span>
      <br />
      <div class="incident">
        <div class="incidentheader">WRL Hotline Incidents</div>
        [ <a href="#">New Incident</a> ]
        <br />
        <table style='width:100%'>
        <tr>
          <td style='text-align:right;'>
            <label>Date</label>
          </td>
          <td>
            <input name="incident.shiftdate" />
          </td>
          <td style='text-align:right;'>
            <label>Shift Start/End</label>
          </td>
          <td>
            <select name="incident.shiftstart">
              <option value=""></option>
              <option value="08:00 AM">08:00 AM</option>
              <option value="08:30 AM">08:30 AM</option>
              <option value="09:00 AM">09:00 AM</option>
              <option value="09:30 AM">09:30 AM</option>
              <option value="10:00 AM">10:00 AM</option>
              <option value="10:30 AM">10:30 AM</option>
              <option value="11:00 AM">11:00 AM</option>
              <option value="11:30 AM">11:30 AM</option>
              <option value="12:00 PM">12:00 PM</option>
              <option value="12:30 PM">12:30 PM</option>
              <option value="13:00 PM">01:00 PM</option>
              <option value="13:30 PM">01:30 PM</option>
              <option value="14:00 PM">02:00 PM</option>
              <option value="14:30 PM">02:30 PM</option>
              <option value="15:00 PM">03:00 PM</option>
              <option value="15:30 PM">03:30 PM</option>
              <option value="16:00 PM">04:00 PM</option>
              <option value="16:30 PM">04:30 PM</option>
              <option value="17:00 PM">05:00 PM</option>
              <option value="17:30 PM">05:30 PM</option>
              <option value="18:00 PM">06:00 PM</option>
              <option value="18:30 PM">06:30 PM</option>
              <option value="19:00 PM">07:00 PM</option>
              <option value="19:30 PM">07:30 PM</option>
              <option value="20:00 PM">08:00 PM</option>
              <option value="20:30 PM">08:30 PM</option>
            </select>
             /
            <select name="incident.shiftend">
              <option value=""></option>
              <option value="08:00 AM">08:00 AM</option>
              <option value="08:30 AM">08:30 AM</option>
              <option value="09:00 AM">09:00 AM</option>
              <option value="09:30 AM">09:30 AM</option>
              <option value="10:00 AM">10:00 AM</option>
              <option value="10:30 AM">10:30 AM</option>
              <option value="11:00 AM">11:00 AM</option>
              <option value="11:30 AM">11:30 AM</option>
              <option value="12:00 PM">12:00 PM</option>
              <option value="12:30 PM">12:30 PM</option>
              <option value="13:00 PM">01:00 PM</option>
              <option value="13:30 PM">01:30 PM</option>
              <option value="14:00 PM">02:00 PM</option>
              <option value="14:30 PM">02:30 PM</option>
              <option value="15:00 PM">03:00 PM</option>
              <option value="15:30 PM">03:30 PM</option>
              <option value="16:00 PM">04:00 PM</option>
              <option value="16:30 PM">04:30 PM</option>
              <option value="17:00 PM">05:00 PM</option>
              <option value="17:30 PM">05:30 PM</option>
              <option value="18:00 PM">06:00 PM</option>
              <option value="18:30 PM">06:30 PM</option>
              <option value="19:00 PM">07:00 PM</option>
              <option value="19:30 PM">07:30 PM</option>
              <option value="20:00 PM">08:00 PM</option>
              <option value="20:30 PM">08:30 PM</option>
            </select>
          </td>
        </tr>
    
        <tr>
          <td style='width:20%;text-align:right;'>
            <label>Animal Code</label>
          </td>
          <td>
            <select name="incident.animalcode">
              <option value=""></option>
              <option value="B">Songbird</option>
              <option value="C">Corvine</option>
              <option value="M">Mammal</option>
              <option value="R">Raptor</option>
              <option value="RE">Reptile</option>
              <option value="U">Unknown</option>
              <option value="W">Waterfowl</option>
    
              <option value="OTH">Other</option>
            </select>
          </td>
          <td style='text-align:right;'>
            <label>Situation Code</label>
          </td>
          <td>
            <select name="incident.situationcode">
              <option value=""></option>
              <option value="A">Attacked (details for attacker)</option>
              <option value="I">Injured</option>
              <option value="K">Killed</option>
              <option value="N">Nuisance (explain in details)</option>
              <option value="O">Orphaned</option>
              <option value="OTH">Other (explain in details)</option>
              <option value="U">Unknown</option>
            </select>
    
            <label>Resolution Code</label>
    
            <select name="incident.resolutioncode">
              <option value=""></option>
              <option value="D">Died</option>
              <option value="GA">Gave advice only</option>
              <option value="LM">Left Message</option>
              <option value="OTH">Other</option>
              <option value="RR">Referred to Rehabber</option>
              <option value="RS">Referred to Shelter</option>
              <option value="RV">Referred to Vet</option>
              <option value="WCB">Watch and Call Back</option>
            </select>
          </td>
        </tr>
        <tr>
    
          <td style='width:20%;text-align:right;'>
            <label>City</label>
          </td>
          <td>
            <input name="incident.city" type="text" />
          </td>
          <td style='text-align:right;'>
            <label>State</label>
          </td>
          <td>
            <select name="incident.state">
              <option value=""></option>
              <option value="MD">Maryland</option>
              <option value="VA">Virginia</option>
              <option value="DC">Washington DC</option>
            </select>
          </td>
        </tr>
        <tr>
          <td style='width:20%;text-align:right;'>
            <label>Description</label>
          </td>
          <td colspan="3">
            <textarea name="incident.details" rows="5" cols="80"></textarea>
          </td>
        </tr>
        </table>
        <input type="submit" value="Save" class="inputBox" />
      </div>
    
    Adding data

    The entry screen is complete and if you type some data and click the Save button, you will store that data in the database. You will notice that this is the case since your URL will change to something like

    .../#incident=abcdefg7896456464532132135498a
    

    That is effectively the id of that record. If you delete that #incident..... and reload the page, you will be presented with an empty form where you can add more data. Clicking the Save button will save that record and you will notice that the new id is different than the previous one.

    I really don't want to have to delete the #incident.... from my address bar every time I want to add a new record. I am sure that the users of the WRL will not like it either. For that, I have added a link at the top of the screen which is already in the script that I have a few lines up. The line:

    [ <a href="#">New Incident</a> ]
    

    is the one that will reload the page allowing me to add a new record whenever I click that link.

    Continued in Part III

  • 2009-12-01 12:00:00

    The world with Angular - Part I

    If you haven't heard about <angular/>, this article is intended to give you a brief overview of the features and functionality that it exposes.

    <angular/> is a declarative programming language that provides the programmer with a wealth of tools using a simplistic model. <angular/> lives in the HTML file and references all the necessary libraries and tools using a single JavaScript file. This approach removes the need of complex scripts, installations of development/production environments (like AMP, Microsoft equivalent or other) and makes upgrading a breeze since the developer doesn't have to deal with it - it's all managed in the cloud. Development IDEs are rendered obsolete and all the developer needs is Notepad/Textmate/gEdit or a similar text editor.

    Backed by the latest cloud technologies, <angular/> is built for scalability. It can handle virtually any task or load right off the box but should the developer need more resources, they can easily contact Brat Tech LLC. and additional arrangements can be made. Ruby on Rails and Amazon EC2 along with CouchDB are the core components that utilizes, making it highly scalable, reliable and extremely fast!

    According to their website (http://www.getangular.com/) <angular/> provides:

    • A managed database - manages data for you
    • HTML & CSS - Full control of the look and feel
    • Security - Authentication and permissions
    • Embeddable - In third-party sites such ad blogs and wikis
    • Declarative - No need to learn a new language
    • Rich Widgets - Date-picker, Barcodes, Charts, etc.

    All of the above (and much more available through the documentation make <angular/> a really good and wise choice for the starter in web programming, the hobbyist who wants some variety in his/her website, the knowledgeable web developer or the expert in web programming.

    So why am I excited about this? For starters it is a really easy language to learn. It is by no means intimidating to any user and people that always wanted to enhance their website with some 'scripting' magic, can do so now with with no installations of any software on their sites.

    To start you need to go and create an account on the website (http://www.getangular.com/). In there you can select your subscription level. There is a free subscription (the default) and two paid ones at 14.95 USD and 45.95 USD per month respectively. The different subscription levels provide more functionality (i.e. SSL support, versioning, more documents etc.)

    Continued in Part II

  • 2009-11-03 12:00:00

    Flexible storage in MySQL

    We all need data to function. Whether this is information regarding what our body craves at the moment - hence go to the local take-away and get it or cook it - or whether this is electronic data to make our tasks easier, makes no difference.

    Storing data in an electronic format is always a challenge. When faced with a new project you always try to out think the project's needs and ensure that you covered all the possible angles of it. Some projects though are plain vanilla since say you only need to enter the customer's name, surname, address and phone. But what happens when you need to enter data that you don't know their type?

    This is where flexible storage comes into play. You can develop a database system that will store efficiently data (well within reason) without knowing what the data will be.

    Say we need to build an application that will be given to the customer to store data about his contacts, without knowing what the fields the customer needs. Fair enough storing the name, surname, address, phone etc. of the customer are pretty much easy and expected to be features. However what about a customer that needs to store in his/her contacts the operating system the contact uses on their computer? How about storing the contact's favorite food recipe, their car mileage, etc. Information is so diverse that you can predict up to a point what is needed but after that you just face chaos. Of course if the application we are building is intended for one customer then everything is simpler. How about more than one customers are our target audience? For sure we cannot fill the database with fields that will definitely be empty for certain customers.

    A simple format to store information can be achieved by storing a type and a value. The first field (data_type) will be a numeric one to hold the ID of the field while the second field (data_value) will be of TEXT type for the "value". The reason for the TEXT is because we don't know the size of the data that will be stored there. Indexes on both fields can help with speeding up the searches. If you use MySQL 4+ you can for sure opt for the FULLTEXT indexing method than the one used in previous MySQL versions.

    We also need a second table to hold the list of our data types (data_type field). This table will have 2 columns and will have of course an ID (AUTOINCREMENT INT) and a VARCHAR column to hold the description of the field.

    CREATE TABLE data_types (
        type_id MEDIUMINT( 8 ) UNSIGNED NOT NULL AUTO_INCREMENT,
        type_name VARCHAR( 50 ) NOT NULL,
        PRIMARY KEY ( type_id )
    );
    

    The table to store the data in will be as follows:

    CREATE TABLE data_store (
        cust_id MEDIUMINT( 8 ) UNSIGNED NOT NULL ,
        type_id MEDIUMINT( 8 ) UNSIGNED NOT NULL ,
        field_data TEXT NOT NULL,
        PRIMARY_KEY ( cust_id, type_id )
    );
    

    And also creating another index:

    ALTER TABLE data_store ADD FULLTEXT (field_data);
    

    (Note that the FULLTEXT support is a feature of MySQL version 4+)

    So what does this table do for us. We need to store the information of Mr. John Doe, 123 Somestreet Drive, VA, USA, +1 (000) 12345678 who likes cats and has a Ford Mustang.

    We first add the necessary fields we need to store in our data_types table. These fields for our example are as follows:

    1 - Title

    2 - Country

    3 - Favorite animal

    4 - Car

    The numbers in front are the IDs that I got when entering the data in the table.

    Assuming that the customer has a unique id of 1, we are off to store the data in our table. In essence we will be adding 4 records into the data_store table for every contact we have. The cust_id field holds the unique ID for each customer so that we can match the information to a single contact as a block.

    INSERT INTO data_store
        (cust_id, type_id, field_data)
        VALUES
        ('1', '1', 'Mr.'),
        ('1', '2', 'USA'),
        ('1', '3', 'Cat'),
        ('1', '4', 'Ford Mustang');
    

    That's it. Now Mr. John Doe is in our database.

    Adding a new field will be as easy as adding a new record in our data_types table. Now with a bit of clever PHP you can read the data_types table and display the data from the data store field.

    We can use the above example to store customer data either as a whole or as a supplement. So for instance in our example we can start by storing the customer ID, first name, surname etc. as fields also in the data_store table using a specific data type. On a different angle we can just keep the core data in a separate table (storing the first name, surname, address etc.) and linking that table with the data_store one.

    This approach although very flexible it has its disadvantages. The first one is that each record has a TEXT field to store data in. This will be a huge overkill for data types that are meant to store boolean values or integers. Another big disadvantage is the search through the table. It is TEXT but also it is vertically structured in blocks. So if you need to search for everyone living in the USA you will need to first find the data_type representing the Country field and then match it to the field_data field of the data_store table.

    There is no one right way of doing something in programming. It all depends on the circumstances and of course to the demands of the application we are developing.

    This is just another way of storing data.