Design Concepts in PHP Projects

published by yegor256 on Apr 27, 2010

Every design concept is implemented as a combination of a unit test and source code prototypes. Three different people take participation in the process: analyst, architect, and designer. In this article we will start from the end. We will review a completed design concept as a unit test (test/design-concepts/FormattingFlexibilityTest.php):

<?php
/**
 * Document formatting shall be flexible enough
 *
 * Concern: It is required in SRS that user shall have an ability to format documents
 * by means of simple web forms, without any special technical knowledge. Thus,
 * the question is how exactly we can provide such an ability to the user, keeping
 * in mind that in the future we might have more and more complex requirements for
 * formatting principles and mechanisms.
 *
 * Concept: I think that we should keep documents in plain text format together
 * with embedded wiki-like formatting meta-tags and meta-commands. I think that
 * a good solution would be to use an extendable library of document parsers,
 * each of which will be responsible for certain meta-symbols and
 * meta-commands. Once we start this library will be small, but in time it
 * will grow and will allow us to modify and extend formatting mechanism.
 */
class concept_DocumentFormattingFlexibilityTest
{
    
/**
     * Document formatter shall be able to accept new parsers as injections
     *
     * We will do this injection during bootstrap of the application, and every
     * new parser shall be responsible for its meta-symbol or meta-command.
     */
    
public function testParsersAreInjectable()
    {
        
// formatter shall be a singleton
        
$formatter = new Model_Document_Formatter::getInstance();

        
// we can add a parser either by name (class name suffix)
        
$formatter->addParser('headers');

        
// or we can add them as class instances
        
$formatter->addParser(new Model_Document_Parser_Images());
    }

    
/**
     * Meta-symbols and meta-commands are converted to HTML or other formats
     *
     * Formatter is the central component, which renders documents using
     * parsers and renderer. Parsers know how to convert meta-commands into
     * document entities, for example: "line that looks like =..= is a top-level"
     * header. This is what a parser knows. Renderer knows that a header shall
     * be rendered as "<h1>...</h1>". Formatter knows how to dispatch them.
     */
    
public function testFormatterSupportsManyOutputFormats()
    {
        
// we use formatting in some places of this small document
        
$doc = new Model_Document(
            
"
            = Lorem ipsum dolor sit amet, consectetur adipiscing elit =

            '''Sed gravida sollicitudin nibh''', at tincidunt nulla laoreet
            quis. Nam hendrerit nunc eu velit [http://fazend.com accumsan eget]
            lacus venenatis. Nulla semper nulla sed ipsum ultrices varius. In
            hac habitasse platea dictumst. ''Pellentesque'' mi libero, facilisis
            sed ultrices id, luctus in ipsum. Phasellus bibendum scelerisque
            nulla, vel tempus purus ornare quis.
            "
        
);

        
// we are able to configure which output format to use
        // and we want to render it as HTML
        
$formatter = new Model_Document_Formatter::getInstance();
        
$formatter->setRenderer(new Model_Document_Renderer_Html());

        
// add all parsers from library, all of them
        
$formatter->addAllParsers();

        
// convert document to HTML using parsers and renderer
        
$html $formatter->render($doc);

        
// assert that the result is a valid XML/HTML string
        
$this->assertTrue(simplexml_load_string($html));
    }
}

The file evolves in three steps:

FormattingFlexibilityTest.php revision 1, by Analyst:

The Analyst analyzes the SRS, the requirements, user expectations, etc. and raises a concern. The Analyst asks a question "how can you design/implement this?", as if he/she is a technical representative of the customer.

<?php
/**
 * Document formatting shall be flexible enough
 *
 * Concern: It is required in SRS that user shall have an ability to format documents
 * by means of simple web forms, without any special technical knowledge. Thus,
 * the question is how exactly we can provide such an ability to the user, keeping
 * in mind that in the future we might have more and more complex requirements for
 * formatting principles and mechanisms.
 */
class concept_DocumentFormattingFlexibilityTest
{
}

The class is small, but very important at this moment. An incorrect selection of design concerns will lead to wasted time, to say the least.

FormattingFlexibilityTest.php revision 2, by Architect:

The Architect analyzes the concern/question raised by the Analyst and answers it by means of design concept, adding methods to the unit test. The Architect works only with the unit test, not with any other classes of the project. Everything is designed in the unit test class. The test shall not break the project, that's why all tests shall be marked as incomplete, by means of markTestIncomplete().

<?php
/**
 * Document formatting shall be flexible enough
 *
 * Concern: It is required in SRS that user shall have an ability to format documents
 * by means of simple web forms, without any special technical knowledge. Thus,
 * the question is how exactly we can provide such an ability to the user, keeping
 * in mind that in the future we might have more and more complex requirements for
 * formatting principles and mechanisms.
 *
 * Concept: I think that we should keep documents in plain text format together
 * with embedded wiki-like formatting meta-tags and meta-commands. I think that
 * a good solution would be to use an extendable library of document parsers,
 * each of which will be responsible for certain meta-symbols and
 * meta-commands. Once we start this library will be small, but in time it
 * will grow and will allow us to modify and extend formatting mechanism.
 */
class concept_DocumentFormattingFlexibilityTest
{
    
/**
     * Document formatter shall be able to accept new parsers as injections
     *
     * We will do this injection during bootstrap of the application, and every
     * new parser shall be responsible for its meta-symbol or meta-command.
     */
    
public function testParsersAreInjectable()
    {
        
// the test is not complete yet, just a design scaffolding
        
$this->markTestIncomplete();

        
// the same code as in the example above, skipped...
    
}

    
/**
     * Meta-symbols and meta-commands are converted to HTML or other formats
     *
     * Formatter is the central component, which renders documents using
     * parsers and renderer. Parsers know how to convert meta-commands into
     * document entities, for example: "line that looks like =..= is a top-level"
     * header. This is what a parser knows. Renderer knows that a header shall
     * be rendered as "<h1>...</h1>". Formatter knows how to dispatch them.
     */
    
public function testFormatterSupportsManyOutputFormats()
    {
        
// the test is not complete yet, just a design scaffolding
        
$this->markTestIncomplete();

        
// the same code as in the example above, skipped...
    
}
}

FormattingFlexibilityTest.php revision 4, by Designer:

The designer implements the concept proposed by the Architect, and makes the test workable and complete.

Copyright Notice: The article is published by FaZend.com and is protected by US and International copyright laws. You may not republish, copy, reproduce or distribute this article or its paragraphs or elements. You may reference the article in your documentation with a mandatory notice about the authorship of the material. If you have any other privacy concerns about the materials published on FaZend.com website you shall email to privacy@fazend.com.


read all articles...