MetaL logo

Metastorage example application implemented with Use Case mapping


Page version


Metastorage example application implemented with Use Case mapping

  • Abstract
  • This document is an introduction on how to develop Web applications that use the code generated by Metastorage. It is meant to guide the Web developers through the necessary steps to build Web applications, using Metastorage as a means to reduce the project development cycle times.

    A methodology named use case mapping is also presented in this document. It is a methodology for developing consistent PHP Web applications, whether they use Metastorage generated code or not.

  • Introduction
  • Metastorage is a tool that generates several types of software components that can be incorporated Web applications. However, in the current version, Metastorage does not generate complete Web applications that can be executed right away.

    It is still necessary to develop more components that act as glue to implement complete Web applications. Such glue components can be Web page scripts, application logic components, and other types of components which provide functionality that is outside of the scope of Metastorage.

  • Use case mapping
    • The methodology
    • A complete Web application can be built using many different methodologies. This document presents one methodology named "Use case mapping".

      It does not mean that this is necessarily the best Web development methodology, nor that you could not use another methodology that you may prefer.

      It is a methodology that I have been using for developing PHP Web applications with very satisfactory productivity results. I have been using it since 1999, when Object Oriented Programming support was added to PHP 3. Over time, it has been refined to address better the real world needs of sites of growing complexity.

      This methodology has been used extensively to develop busy sites like the PHPClasses repository. Therefore, it has proven to be suitable to develop enterprise grade Web applications. It does not impose excessively complex development procedures. So, it is also suitable for developing small Web applications.

    • What are use cases?
    • Use cases are basically the different types of situations that an application must handle to interact with the application actors.

      Use cases are often referred to as "screens" or "pages", like for instance: the login page, the search page, the articles pages, etc...

      Actors are usually the application users or external systems with which the application must interact.

      Use cases are not only about situations that generate output that an user can view when it occurs. An use case may need to handle a situation that only requires to interact with non-human external systems. For instance, sending an automated newsletter to subscribers listed in a database, or fetching weather forecast information from a remote system.

    • Iterative software development processes
    • Usually, a well structured software process requires some planning. Even when you are developing a small project for your own use, it is always good to give some thought before start implementing it.

      Many developers do not like planning, either because it is boring, or because they do not know enough about good methodologies to make proper software planning.

      The Rational Unified Process is a well-known software development process that recommends a plan-driven development of projects that are divided in iterations.

      Agile is another well-known software development process that also recommends iterative development, but in shorter cycles. The idea is to be able to develop software than can be released earlier and often. That would allow making eventual adjustments to the project requirements and subsequent planning, based on information realized later during the implementation process.

      Developers that do not like planning much, often prefer Agile software development process because it lets them start writing code sooner and see the results more often.

    • Describing use cases
    • Regardless of the software development process you prefer, by the time you start implementing your project, you must have already a good idea of which use cases you are going to implement in each project iteration. You also need to have a good idea of what each use case must do.

      It is always good to document your project use cases. This is is specially true when you are developing a project for a client. Even when the client does not understand enough about software development, if you show him a use case diagram and use case descriptions, he will most likely understand and trust that you are doing what he expects.

      When the client trusts you have the competence to do what he wants, he is more open to pay you more for your work, and will prefer ordering more work from you instead of your competitors. Therefore, the additional work that it takes to create proper project documentation may compensate financially.

      An use case diagram is an artifact of the UML language that can help you modeling use cases. UML is a visual language that can be used to create visual representations of different perspectives of a software system.

      Metanews use case diagram

      An UML use case diagram can help representing the use cases that you want to implement. Use case diagrams are presented in an way that is easy to understand, even by people that is not familiar with software development processes, like clients and sponsors. However, use case diagrams are not sufficient to describe the relevant details of each use case.

      It is not absolutely necessary to describe use cases in detail before start writing the code that implements them. A small application written by a single developer may not need to be formally documented because the developer is capable to keep all the relevant details in mind.

      Regardless if a project is formally documented or not, there are several details about an use case that are very important. Understanding these details very well, helps you to write the necessary code to implement the use cases correctly. These are the most important use case details:

      • Name

        Example: Submit article

      • Description of the situation

        Summary of what the use case is about.

        Example: The user submits new article for publication.

      • Pre-conditions

        Any conditions that must be true when the use case is initiated.

        Example: The user must be authenticated to publish an article.

      • Activation events

        Events that trigger the start of an use case.

        Example: The user accesses the submit article page.

      • Normal flow of events

        Expected sequence of events that should happen when the use case is executed in most common situation. This is also known as the primary scenario.

        Example:
        1. The article submission form is presented with fields for the title, lead text and body text.
        2. The user submits the form.
        3. A message is displayed to let the user know the article was submitted successfully.

      • Alternative flows of events

        Other sequences of events that may happen but are not the most expected. These are also known as secondary scenarios or exceptions situations.

        Example:
        Secondary scenario: Submission canceled
        2a. The user submits the article form using the cancel button.
        3a. A message is displayed to let the user know that the article submission was canceled and nothing happened.

        Exception: empty fields
        2b. The user submits the form with empty fields.
        3b. A message is displayed telling that the form fields must not be empty.
        4b. Go to 1.

        Exception: non-unique article title
        2c. The user submits the form with a title of an article that was previously submitted.
        3c. A message is displayed telling that there is already an article with the same title.
        4c. Go to 1.

      • Post-conditions

        Conditions that must be true after the use case ends.

        Example: The new article record is inserted in the database.

    • Implementing Web application use cases
    • There are many ways to implement Web applications use cases. This document focus in the use case mapping methodology.

      This methodology consists in implementing all the logic of an use case in two parts: a Web script and a business rules component.

      The purpose of the Web script is to receive the HTTP request and return a response. The role of the business rules component is to handle all the situations planned in the use case specification.

      • Use case Web script
      • A use case Web script is usually very simple. It performs the same tasks for each use case:

        • Load the application components that the use case needs.
        • Invoke the use case business rules component.
        • Process runtime errors not anticipated in the use case specifications, like errors accessing the database or other external systems.

        Here is an example of an use case Web script:

        Load the application components

        
         define('APPLICATION_PATH', '..');
         define('METABASE_PATH', APPLICATION_PATH.'/../../../metabase');
         define('FORMS_PATH', APPLICATION_PATH.'/../../../forms');
        
         require(METABASE_PATH.'/metabase_database.php');
         require(METABASE_PATH.'/metabase_interface.php');
         require(FORMS_PATH.'/forms.php');
         require(APPLICATION_PATH.'/configuration/options.php');
         require(APPLICATION_PATH.'/templates/page.php');
         require(APPLICATION_PATH.'/templates/window.php');
         require(APPLICATION_PATH.'/components/metanews/metanews.php');
         require(APPLICATION_PATH.'/components/metanews/article.php');
         require(APPLICATION_PATH.'/components/metanews/submitarticleform.php');
         require(APPLICATION_PATH.'/usecases/metanews/submit_article.php');
        
        

        Invoke the business rules component

        
         $options = new configuration_options_class;
         $options->application_path = APPLICATION_PATH;
         $options->initialize();
        
         $case = new use_case_submit_article_class;
         $case->options = &$options;
        
         $success = ($case->initialize() && $case->process());
         if($success)
           $case->output();
        
        

        Process runtime errors

        
         if(!$success)
         {
           require(APPLICATION_PATH.'/usecases/error.php');
        
           $error_case = new use_case_error_class;
           $error_case->options = &$options;
           $error_case->error = $case->error;
           $error_case->debug = $case->debug;
           if($error_case->initialize()
           && $error_case->process())
             $error_case->output();
         }
        
        

      • Use case business rules component
      • The business rules component implements most of the logic to handle each use case:

        • Verifies the pre-conditions
        • Implements both the normal and the alternative flows of events.
        • Assures that the post-conditions are met when the use case ends.
        • Handles the exceptional situations anticipated in the use case description.

        In the use case mapping methodology, each business rules component is implemented in practice using a single class. It should implement a common interface that has the following structure:

        • May have public variables that are used by the Web script to pass configuration details to the use case class.
        • Should have one or more public variables to return error messages when unexpected exceptional situations occur.
        • May have additional public variables to return information about the use case current status.
        • May use auxiliary private variables, functions and additional classes.
        • Must have three public variables that implement a compact form of of the MVC (Model-View-Controller) design pattern: initialize(), process() and output().

      • Use case class interface
      • The three public functions initialize(), process() and output() constitute the use case class interface.

        Use case class interface

        Each of these three public functions of the use case class interface implement an important part of the use case logic:

        initialize()

        • It is called before the actual use case action happens.
        • Implements the first part of the Controller functionality of the compact MVC design pattern.
        • Initializes auxiliary variables and external objects.
        • May access model class objects if necessary.
        • Verifies whether the use case pre-conditions are met.
        • It is a function of type boolean. It returns false when an unexpected runtime error happens.

        process()

        • It is called right after the initialize() function, only if it has returned true.
        • Implements the second part of the Controller functionality of the compact MVC design pattern.
        • Implements the actions associated with the normal and alternative flows of events.
        • Does not do anything if the use case pre-conditions are not met.
        • Handles expected exceptional situations.
        • Assures that the use case post-conditions are met.
        • May access model class objects if necessary.
        • Prepares any results to be presented, but it does not output any information, except when that is part of the use case processing, like for instance serving files for download or other kind of streamed output.
        • It should use the class private variables to pass information to present by the output() function.
        • It is a function of type boolean. It returns false when an unexpected runtime error happens.

        output()

        • It is called right after the process() function, only if it has returned true.
        • Implements the View functionality of the compact MVC design pattern.
        • Generates the Web script output as result of the actions executed by the process() function.
        • It may use result information passed by the process() function using the class private variables.
        • It never fails. It is a void type function. Anything expected or unexpected that could have failed, must happen either in the initialize() or process() functions.

      • Use case class skeleton
      • In practice the use case classes have a skeleton like this:

        
         class use_case_skeleton_class
         {
           /* Public variables */
           var $error = '';
        
           /* Private variables */
           var $verified_pre_conditions = false;
           var $prepared_output = '';
        
           /* Private functions may go here  */
        
           /* Public functions */
           Function initialize()
           {
             /* ... */
        
             $this->verified_pre_conditions = $pre_conditions_are_met;
        
             /* ... */
        
             if($an_error_occurred)
             {
               $this->error = 'some explanatory error message';
               return false;
             }
        
             return true;
           }
        
           Function process()
           {
             if($this->verified_pre_conditions == false)
               return true;
        
             /* Execute use case processing tasks */
        
             $this->prepared_output = $data_to_output;
        
             if($an_error_occurred)
             {
               $this->error = 'some explanatory error message';
               return false;
             }
        
             return true;
           }
        
           Function output()
           {
             echo $this->prepared_output;
           }
        
         };
        
        

      • Use case class example
      • Here is a real example of an use case class:

        
         class use_case_submit_article_class
         {
        
        

        Public variables to pass application options to the class, and to return error and debug messages

        
           var $options;
           var $error = '';
           var $debug = '';
        
        

        Auxiliary private variables

        
           var $user;
           var $page;
           var $factory;
           var $form;
           var $window;
        
        

        initialize function

        
           Function initialize()
           {
        
        

        Verify whether the use case pre-conditions are met

        
             /*
              * Verify whether the user is authenticated
              */
             $this->user = new user_authenticate_class;
             $this->user->options = &$this->options;
             $success = ($this->user->initialize() && $this->user->process());
             $this->debug.=$this->user->debug;
             if(!$success)
             {
               $this->error = $this->user->error;
               return(0);
             }
        
        

        Initialize auxiliary variables and external objects

        
             if($this->user->authenticated)
             {
        
               /*
                * Initialize the factory class
                */
               $this->factory = &new metanewsclass;
               $this->factory->debug = $this->options->debug;
               $this->factory->connection = $this->options->database_connection;
               $this->factory->includepath = METABASE_PATH;
               if(!$this->factory->initialize())
               {
                 $this->error = $this->factory->error;
                 return(0);
               }
        
               /*
                * Initialize the submit article form class
                */
               $this->form = &new submitarticleformclass;
               $this->form->images = 'graphics/';
               $this->form->text['title'] = HtmlSpecialChars('Submit a new article'.
                 ' - '.$this->options->application_name);
               $this->form->text['warningtitle'] = HtmlSpecialChars('Warning!'.
                 ' - '.$this->options->application_name);
               if(!$this->form->initialize($this->factory))
               {
                 $this->error = $this->form->error;
                 return(0);
               }
             }
        
             /*
              * Initialize the page template class
              */
             $this->page = &new template_page_class;
             $this->page->title_prefix = $this->options->application_name;
             $this->page->title = 'Submit a new article';
             return(1);
           }
        
        

        process function

        
           Function process()
           {
        
        

        Do nothing if the use case pre-conditions are not met

        
             if(!$this->user->authenticated)
               return(1);
        
        

        Implement the actions associated with the normal and alternative flows of events

        
             /*
              * Process the form
              */
             $success = $this->form->process();
        
        

        Returns false when an unexpected runtime error happens

        
             /*
              * If there was a problem, retrieve the error message
              */
             if(!$success)
               $this->error = $this->form->error;
        
             /*
              * Finalize pending operations, if any
              */
             $this->factory->finalize();
        
             /*
              * Retrieve debug output, if any
              */
             $this->debug.= $this->factory->debugoutput;
             return($success);
           }
        
        

        output function

        
           Function output()
           {
        
        

        Generates the Web script output

        
             $this->page->Header();
             if(!$this->user->authenticated)
             {
               /*
                * Let the user know that the article submission can only be made
                * by an authenticated system administrator
                */
         ?>
         <h2 class="importantmessage">Only the system administrator
         is allowed to submit new articles.</h2>
         <?php
                $this->user->output();
         ?>
         <p class="importantmessage"><a href="index.php">List articles</a></p>
         <?php
             }
        
        

        Use result information passed by the process() function using the class private variables

        
             elseif($this->form->processed)
             {
               /*
                * Let the user know that the article submission succeeded
                */
         ?>
         <h2 class="importantmessage">The article was submission successfully.</h2>
         <p class="importantmessage"><a href="index.php">List articles</a></p>
         <?php
             }
             elseif($this->form->canceled)
             {
               /*
                * Let the user know that the article submission was canceled
                */
         ?>
         <h2 class="importantmessage">The article submission was canceled.</h2>
         <p class="importantmessage"><a href="index.php">List articles</a></p>
         <?php
             }
             else
             {
               /*
                * If the article submission is not yet done, output the form
                */
               echo $this->form->output();
             }
             if(strlen($this->debug))
             {
               /*
                * Output the debug information in debug mode
                */
         ?><pre><?php echo HtmlSpecialChars($this->debug); ?></pre><?php
             }
             $this->page->Footer();
           }
         };
        
        

      • Handling unexpected runtime errors
      • An use case class may fail due to an unexpected runtime error. When that happens, either of the initialize() or the process() use case class functions return false.

        Following the use case mapping methodology, unexpected runtime errors should be handled by a special error handling use case class.

        That class implements the same interface and should be called the same way at the end of the Web script.

        Here follows a Web script excerpt that shows how the error handling use case class is invoked:

        
         $case = new use_case_submit_article_class;
         $case->options = &$options;
        
         $success = ($case->initialize() && $case->process());
         if($success)
           $case->output();
        
         if(!$success)
         {
           require(APPLICATION_PATH.'/usecases/error.php');
        
           $error_case = new use_case_error_class;
           $error_case->options = &$options;
           $error_case->error = $case->error;
           $error_case->debug = $case->debug;
           if($error_case->initialize()
           && $error_case->process())
             $error_case->output();
         }
        
        

        This special use case class is like an exception class, except that it can work with PHP 4 on which exception handling support is not available.

        It provides consistent error handling behavior. It works the same way regardless of the type of error that may have occurred.

        It may receive error context information via public variables, like for instance an error message, or debug log messages returned by the main use case class.

        The error handling class may perform several types actions. Such actions may be useful to help the system administrators or the developers to realize what happened and why, so they can act promptly and fix any problems as soon as possible.

        Common error handling actions may include recording the error message in a log file, notify the system administrators by e-mail, pager, instant messaging, etc..

        The output of the use case must be an user-friendly message that should not cause user panic. That message also must not include sensitive details that could be used by malicious users to compromise the system security.

        Here is an example of an error handling use case class:

        
         class use_case_error_class
         {
           var $options;
           var $error = '';
           var $debug = '';
        
           var $page;
           var $window;
        
           Function initialize()
           {
             /*
              * Initialize the page and window frame generation template classes
              * that will be used by the output function
              */
             $this->page = new template_page_class;
             $this->page->title_prefix = $this->options->application_name;
             $this->page->title = 'Application problem';
             $this->window = new template_window_class;
             $this->window->title = 'Application problem!';
             $this->window->center = 1;
             $this->window->background_color = $this->options->windows_background_color;
             return(1);
           }
        
           Function process()
           {
             /*
              * Here the class could execute important actions to help the
              * developers or system administrators to fix the problem promptly like:
              *
              * - Log the errors to a file
              * - Send an e-mail to the system administrator
              * - Etc.
              */
             return(1);
           }
        
           Function output()
           {
             $this->page->Header();
             $this->window->Header();
        
             /*
              * Display an user friendly error message
              * without disclosing any details about the actual error
              */
         ?>
         <p style="text-align: center"><b>Sorry, for the time being<br />
         <?php echo HtmlEntities($this->options->application_name); ?> is not available.</b></p>
         <?php
             $this->window->Footer();
        
             /*
              * In debug mode any details about the actual error
              */
             if($this->options->debug)
             {
         ?>
         <hr />
         <p><b>Error</b>: <?php echo HtmlEntities($this->error); ?></p>
         <?php
               if(strlen($this->debug))
               {
         ?><pre><?php echo HtmlSpecialChars($this->debug); ?></pre><?php
               }
             }
            $this->page->Footer();
           }
         };
        
        

    • Standard Web application directory structure
    • An application may be made of many files for many different purposes. Usually each file should be stored in a directory according to its purpose.

      Using a consistent application directory structure helps developers understanding better their applications. This way they can find faster the files they need to create and maintain.

      The following directory structure is a proposal that addresses the needs of most types of Web applications. It is not necessarily the only directory structure that may be right for Web applications. It is a recommendation that may be followed by anybody. Eventually, you may rename, add, remove or rearrange directories according to your needs.

      Under restricted hosting environments it may not be possible to put the base directory for Web pages accessible to the public as a sub-directory of the installation directory named web, as it is proposed.

      In that case it is acceptable to make the base Web page scripts directory the same as the installation directory, as long as sensitive information files do not become accessible via Web, like for instance the configuration files that contain database access user names and passwords.

      
       /path/to/application/ - installation directory
       |
       |-> usecases/ - use case implementation classes
       |
       |-> web/ - Web page scripts
       |   |
       |   |-> graphics/ - static image files used in the site
       |   |
       |    -> css/ - CSS files used in the site
       |
       |-> templates/ - files and classes that define presentation aspects
       |
       |-> components/ - general purpose classes
       |
       |-> configuration/ - configuration files and scripts
       |
       |-> locale/ - configuration and text files to support different idioms
       |
       |-> setup/ - installation files and scripts
       |
       |-> backend/ - maintenance files and scripts
       |
        -> logs/ - events and error log files
      
      

  • Metanews - an example Metastorage application
    • What is Metanews?
    • Metanews is the name of simple application written with the help of code generated by Metastorage. It is a simples news publication system that lets a news editor submit articles. The published articles are listed in their own Web pages.

      By all means, it is not anything near a complete article publication system. It is just meant to illustrate how common aspects of Web applications can be implemented by glueing custom handwritten code with Metastorage generated code.

    • Planing the Metanews project
    • Despite Metanews is a simple project for educational purposes, it required some planing. The planing consisted in looking at the project requirements and see which use cases would need to be implemented.

      An use case diagram was elaborated with the help of a UML modeling program named Umbrello. This is a free Linux program that is now part of the software development kit package of the KDE system. There are plenty of other free and commercial UML tools that you can use to design UML diagrams.

      These tools can save UML projects in the XMI. This is a XML based format meant for exchange project metadata between different tools.

      The Metanews use case diagram is available as part of UML project saved in XMI format. The Metanews XMI project file comes with the project source code distribution. It looks like this:

      Metanews use case diagram

    • Metanews system use cases
    • Three main use cases were considered to develop in a first iteration of the Metanews project: Submit article, Show latest articles, and Show article.

      There is an additional use case that was not included in the use case diagram. That use case is for installing the application database schema.

      Lets document these use cases, so we can have a good perspective of how they can be implemented:

      • Installation
        • Description

          Install the schema of the database that will serve as support to store the information of the application objects.

        • Pre-conditions

          1. The database schema is not yet installed or it is not upto date with the latest revision.
          2. The application options are configured.

        • Activation events

          The user accesses the page of the application start page.

        • Normal flow of events

          1. The database schema is installed.
          2. A message is displayed to tell the user that the database schema was installed successfully.

        • Alternative flows of events

          Secondary scenario: The database schema is already installed
          1a. If the database schema is not upto date, upgrade it to the latest version.
          2a. If the database schema was upgraded, tell the user that the database was updated successfully.

          Exception: Application is not configured
          1b. Tell the user which application options must be configured.
          2b. Stop

        • Post-conditions

          The database schema is installed and upto date.

      • Submit article
        • Description

          The user submits new article for publication.

        • Pre-conditions

          The user must be authenticated as an administrator to be allowed to publish an article.

        • Activation events

          The user accesses the submit article page.

        • Normal flow of events

          1. The article submission form is presented with fields for the title, lead text and body text.
          2. The user submits the form.
          3. A message is displayed to let the user know the article was submitted successfully.

        • Alternative flows of events

          Secondary scenario: Submission canceled
          2a. The user submits the article form using the cancel button.
          3a. A message is displayed to let the user know that the article submission was canceled and nothing happened.

          Exception: empty fields
          2b. The user submits the form with empty fields.
          3b. A message is displayed telling that the form fields must not be empty.
          4b. Go to 1.

          Exception: non-unique article title
          2c. The user submits the form with a title of an article that was previously submitted.
          3c. A message is displayed telling that there is already an article with the same title.
          4c. Go to 1.

        • Post-conditions

          The new article record is inserted in the database.

      • Show latest articles
        • Description

          Display a list of the latest articles that were published.

        • Pre-conditions

          None

        • Activation events

          The user accesses the page to show the latest articles.

        • Normal flow of events

          1. The page lists upto 10 of the latest articles that were published, showing each article title as a link to the page to show the article in detail, the article date and the article lead paragraph.

        • Alternative flows of events

          Secondary scenario: RSS feed
          1a. Generate a XML RSS 1.0 feed with the articles titles, article detail page URLs, article dates and article lead paragraphs.

          Exception: No articles were published yet
          1b. Display a message telling the user that no articles were published so far.

        • Post-conditions

          The latest articles are displayed.

      • Show article
        • Description

          Display an individual article in detail.

        • Pre-conditions

          A valid article identifier must be specified as a page request parameter.

        • Activation events

          The user accesses the page to show an individual article.

        • Normal flow of events

          1. The page shows the article title, the article date, the article lead paragraph, and the article body text.

        • Alternative flows of events

          Exception: Invalid or missing article identifier
          1a. Display a message telling the user that it was not specified a valid article identifier.

        • Post-conditions

          The specified article is displayed.

    • Metanews application structure
    • Below follows the structure of files and directories of the Metanews application.

      Some directories have a sub-directory named metanews that contains files that belong specifically to the Metanews project. Using sub-directories this way is recommended in case you plan to install several applications or modules that coexist in the same Web site.

      The source directory is listed for learning purposes. In a real Web site production environment that directory is not need and should not be installed.

      
       metal/metastorage/applications/metanews/
       |
       |-> components/
       |   |
       |   |-> metanews/
       |   |   |
       |   |   |-> article.php - Article persistent class
       |   |   |
       |   |   |-> articlesreport.php - Article reports class
       |   |   |
       |   |   |-> metanews.php - Metanews factory class
       |   |   |
       |   |    -> submitarticleform.php - Submit article form class
       |   |
       |    -> users/
       |       |
       |        -> authenticate.php - User authentication class
       |
       |-> configuration/
       |   |
       |    -> options.php - Application options class
       |
       |-> setup/
       |   |
       |    -> metanews/
       |       |
       |       |-> metanews.schema - Database schema definition
       |       |
       |        -> metanewsschema.php - Database installation class
       |
       |-> source/
       |   |
       |   |-> components/
       |   |   |
       |   |   |-> articles.report - Articles report class definition
       |   |   |
       |   |   |-> metanews.component - Metanews component definition
       |   |   |
       |   |    -> submitarticle.form - Submit article form class definition
       |   |
       |    -> uml/
       |       |
       |        -> metanews.xmi - UML Use cases and classes diagrams
       |
       |-> templates/
       |   |
       |   |-> page.php - Page header and footer generation class
       |   |
       |    -> window.php - Window frame generation class
       |
       |-> usecases/
       |   |
       |   |-> error.php - Error handling use case class
       |   |
       |    -> metanews/
       |       |
       |       |-> latest_articles.php - Show latest articles use case class
       |       |
       |       |-> show_article.php - Show article use case class
       |       |
       |       |-> start.php - Installation use case class
       |       |
       |        -> submit_article.php - Submit article use case class
       |
        -> web/
           |
           |-> css/
           |   |
           |    -- styles.css - CSS styles sheet
           |
           |-> graphics/
           |   |
           |   |-> close.gif - Window close button image
           |   |
           |    -> rss.gif - RSS icon image
           |
           |-> index.php - Show latest articles page
           |
           |-> show_article.php - Show article page
           |
           |-> start.php - Installation page
           |
            -> submit_article.php - Submit article page
      
      

    • Metanews use cases implementation
      • General considerations
      • Each use case uses its own set of scripts and class files. Some were generated by Metastorage, others were handwritten.

        There are several groups of files located in different directories that are shared by practically all use cases:

        • Configuration

          The application configuration files are located in the directory configuration. There is one options class file that defines all the application configuration default values. To override the default values, you need to create a PHP script named local_options.php. If it exists, this script is included by the options class. So, it must be made of statements that redefine the class variables like this:

          
           $this->debug = 0;
          
          
        • Presentation details

          The application uses special classes to generate common presentation output for page headers and footers and also window frames. These classes are located in the directory templates.

          The classes use HTML embedded in the actual class code. The template HTML is HTML 4.01 strict DTD compliant.

          The template classes could have used a template engine that would allow putting the template HTML in separate data files. That was not done only to simplify this example project and not add a dependency on an external template engine package.

          The presentation styles of several page items are defined in a CSS file located in the web/css directory. This file can be customized to adjust the presentation styles to your preferences.

      • Installation
      • The installation use case is implemented using files for the schema definition and the database installation class that are located in the directory setup/metanews.

        The database installation class is capable of installing the database schema generated automatically by Metastorage. The schema includes all the tables that are necessary to store the objects of the persistent classes specified in the project component definition.

        Metastorage generates a database installation class that can either install the schema for the first time, or upgrade to a newer revision, also generated by Metastorage, after eventual changes made to the project component definition.

        When the database schema is installed, the file metanews.schema is copied to metanews.schema.installed. The installation use case class uses this information to determine whether the database schema is being installed for the first time, or is being upgraded to a newer revision, or if nothing happened when the installed schema revision is already the most upto date.

        Metanews installation page

      • Submit article
      • The submit article use case is implemented using a form handling class located in the directory components/metanews. This class is also generated by Metastorage.

        The article submission form class takes care of most of the use case processing logic, including form validation, article object initialization, validation and storage. It also takes care of the situation when the user cancels the form submission.

        Since the use case has as pre-condition that the user must be authenticated, this verification is the first thing that is done in the initialize function of the submit article use case class.

        The authentication is done using a special use case class located in the components/users directory. This class performs basic HTTP user authentication. It verifies whether the user and password match those defined by the application options administrator and administrator_password.

        Metanews submit article page

      • Show latest articles
      • The show latest articles use case is implemented using a report data extraction class handling class located in the directory components/metanews. This class is also generated by Metastorage.

        The report class retrieves all the necessary data to present upto 10 of the latest articles into a class private array variable. The class iterates over this array to format the article information.

        The class also generates a link to a page that generate the same articles listing as an RSS 1.0 feed. This link points to same page but it takes an additional request parameters that tells the class to generate the RSS feed instead of the normal articles listing page.

        Metanews latest articles page

        Metanews RSS feed

      • Show article
      • The show article use case is implemented using the same report data extraction class handling class generated by Metastorage that is located in the directory components/metanews.

        The report class retrieves all the data to present an article with an identifier passed by a page request parameter. The article data is also stored in a class private array variable that is accessed by the class output function to present the article in detail.

        Metanews show article page

  • Conclusions
  • Metastorage is a powerful code generation tool, but obviously it does not generate all the parts of a Web application. That is not its main goal either. However, the Metanews application demonstrated how Metastorage can be used already to generate a significant amount of code of a complete Web application, that otherwise would take a lot more time to write, test and debug by hand.

    The use of a mature and consistent development methodology, as the use case mapping, also helps the developer to become more productive once he gets used to work systematically using the same development procedures.

    Therefore, the adoption of productive tools and methodologies like Metastorage and use case mapping can obviously contribute in a significative way to the moral and financial satisfaction of the Web developer.


For more information contact: info-at-meta-language.net