Separation of logic, design and data

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Frank van Wensveen

    Separation of logic, design and data

    Friend, coders, fellow wage slaves, lend my your ears.

    I believe that in a perfect world the design of a website (or feature
    on a website) should be totally separated from its design and the data
    it serves up. I'd like some suggestions on good ways to do this,
    because in the real world it can be quite difficult.

    For example, if I'm rummaging around in a MySQL database, the table
    structure and the code that generates the SQL requests are often
    interrelated. Restructure your table(s) and you have to update your
    code accordingly.

    Another, more serious issue is the separation of design from code. For
    example, if I'm using tables to divide my pages into separate 'blocks'
    (e.g. for a top bar, menu, content section, side bar, banner space,
    etc.) then the structure of these tables and table cells are
    interrelated with the program's flow: you set up a table or table
    cell, do something that outputs data into that cell, close the cell
    and/or table, and move on to the next cell to do something else there.
    Removing or adding a cell will mean that the function(s) that output
    data into that cell should or should not be called. Or the order in
    which code is executed could be affected: if I want a page-wide top
    bar cell followed by a menu column and a content window underneath, I
    need to render the top bar table row first, spanning two columns, then
    start a new table row in which I'd put the menu and content cell. But
    if I want a menu bar all the way to the top of the screen and a top
    bar cell followed by a content cell both to the right hand side of the
    menu column, I need to render the menu cell first, spanning two rows,
    and then progress to rendering the top bar and content cells.

    One could of course take abstraction and modularization to extreme
    levels (e.g. put every line of table-related code into a separate
    template file and include that depending on program flow) but this
    quickly increased both complexity and overhead to beyond what is
    acceptable. Not to mention the fact that ideally one should not issue
    function calls from within a content template file.

    So how do real developers do this?



    Regards,
    Frank
  • Toby Inkster

    #2
    Re: Separation of logic, design and data

    Frank van Wensveen wrote:
    I believe that in a perfect world the design of a website (or feature
    on a website) should be totally separated from its design and the data
    it serves up. I'd like some suggestions on good ways to do this,
    because in the real world it can be quite difficult.
    Keeping styling separate from the rest is smiple (sic): just do all your
    layout, colour schemes, etc with CSS.

    After that you've still got the problem of the fact that your code has to
    do things in the correct order to output the page -- say, output HTML
    header stuff first, then body stuff, then sidebar stuff, and finish with
    some legalese and footer stuff. This can be solved using a template
    engine. There are several available, though I can't say I like any of
    them, I generally write my own template engine using the interface pasted
    below. (Infact, I've only recently coded it as a proper PHP Interface,
    earlier I used a standard class, which I would extend one or two methods
    of.

    This interface allows you to use (note the seemingly random order):

    $t = new StdTemplate('Fo o Bar');
    $t->add_section('F oo', '<p>Foo</p>', 'foo',
    StdTemplate::DI VISION_MAIN, 2);
    $t->add_section('B ar', '<p>Bar</p>', 'bar',
    StdTemplate::DI VISION_EXTRA, 3);
    $t->add_section('F oo Bar', '<p>The life of Foo Bar</p>', 'foobar',
    StdTemplate::DI VISION_HEAD, 1);
    $t->add_script('/js/prototype.js');
    $t->add_meta('Auth or', 'Me', FALSE, array());
    $t->add_filter(n ew SpellCheckFilte r(),
    StdTemplate::DI VISION_MAIN | StdTemplate::DI VISION_EXTRA);
    $t->add_section('B az', '<p>Baz</p>', 'baz',
    StdTemplate::DI VISION_EXTRA, 3);
    $t->output();

    which might output this:

    <html>
    <head>
    <title>Foo Bar</title>
    <meta name="Author" content="Me">
    <script type="text/javascript" src="/js/prototype.js"></script>
    </head>
    <body>
    <div id="head">
    <div class="section" id="foobar">
    <h1>Foo Bar</h1>
    <p>The life of Foo Bar</p>
    </div>
    </div>
    <div id="main">
    <div class="section" id="foo">
    <h2>Foo</h2>
    <p><span class="spelling " title="Fool?">F oo</span></p>
    </div>
    </div>
    <div id="extra">
    <div class="section" id="bar">
    <h3>Bar</h3>
    <p>Bar</p>
    </div>
    <div class="section" id="baz">
    <h3>Baz</h3>
    <p><span class="spelling " title="Bat?">Ba z</span></p>
    </div>
    </div>
    <div id="foot">
    </div>
    </body>
    </html>

    Anyway, interface follows. Implement this interface and you'll be
    happy. :-)

    <?php

    /**
    * @author Toby Inkster <demiblog@tobyi nkster.co.uk>
    * @copyright Copyright &copy; 2007, Toby Inkster
    * @license http://www.gnu.org/copyleft/gpl.html GNU General Public Licence
    * @version 1.0
    */

    /**
    * The Template interface is a standard interface that you must implement
    * if you would like to create a new template for Demiblog. In addition,
    * your template class must define the following constants. (PHP does not
    * allow constants to be defined within a template.)
    *
    * DIVISION_HEAD = 1
    * DIVISION_MAIN = 2
    * DIVISION_EXTRA = 4
    * DIVISION_FOOT = 8
    * (You may define up to four custom divisions with values 16, 32, 64
    * and 128.)
    * FULL_HTML = -1
    *
    * The StdTemplate class supplied with DemiBlog outputs a page with roughly
    * the following structure (it may vary, depending on HTML flavour):
    *
    * <!DOCTYPE ...>
    * <html>
    * <head>
    * <title>...</title>
    * <meta ... /><!-- etc -->
    * <link ... /><!-- etc -->
    * <script src="..."></script><!-- etc -->
    * </head>
    * <body>
    * <div id="page">
    * <div id="head">##</div>
    * <div id="body"><div id="main">##</div><div id="extra">##</div></div>
    * <div id="foot">##</div>
    * </div>
    * </body>
    * </html>
    *
    * where locations marked with a double-hash (##) can be filled with zero or
    * more content panels. This structure should be adequate for expressing most
    * site layouts and should provide enough id and class hooks to hang most CSS
    * designs onto.
    *
    * In the case where it does not prove sufficient, you have two options:
    *
    * 1. Keep the existing StdTemplate, but write a filter to modify its
    * output (using, for example, regular expressions). The filter
    * can be attached to the existing template using its add_filter()
    * method.
    *
    * 2. Write a new template class, implementing the Template interface.
    * Use the existing StdTemplate as a guide -- simply extending the
    * existing template is probably sufficient. You will probably want
    * to modify the output() method.
    */
    interface Template
    {
    /**
    * Add a section to the template with a particular ID and Title. Add
    * it to a particular division or divisions.
    * @param string $title Title of section.
    * @param string $body Body of section. This should be in the correct
    * flavour of HTML. The template will not attempt to rewrite it.
    * @param string $id HTML ID of section. The template will protect
    * against multiple sections with the same ID.
    * @param int $to_division Division(s) to add to.
    * @return bool Success.
    */
    public function add_section ($title, $body, $id, $to_division, $heading_level) ;

    /**
    * Filter for sections. An object with interface TemplateFilter must
    * be supplied. Filters are not applied until $this->output() is called.
    * @param Object $object Filter object.
    * @return bool Success.
    */
    public function add_filter (TemplateFilter $object);

    /**
    * Adds a META element to the template's document HEAD.
    * @param string $name META name.
    * @param string $content META content.
    * @param bool $is_http_equiv Replace "name" attribute with "http-equiv".
    * @param Array $more_attribute s Extra attributes for META element.
    * @return bool Success.
    */
    public function add_meta ($name, $content, $is_http_equiv, $more_attribute s);

    /**
    * Adds a LINK element to the template's document HEAD.
    * @param string $rel LINK relationship.
    * @param string $href LINK destination.
    * @param string $type LINK MIME Type.
    * @param Array $more_attribute s Extra attributes for META element.
    * @return bool Success.
    */
    public function add_link ($rel, $href, $type, $more_attribute s);

    /**
    * Adds a SCRIPT element to the template's document HEAD.
    * @param string $src Script file.
    * @return bool Success.
    */
    public function add_script ($src);

    /**
    * @return bool HTML Flavour.
    */
    public function get_flavour ();

    /**
    * @return string Finished page.
    */
    public function output ();
    }

    /**
    * The TemplateFilter interface is an interface for defining filters that
    * act on templates and may modify their output. Filters can apply to the
    * whole finished page, or just to specific sections within it. Examples of
    * uses for filters:
    *
    * - Gzip finished pages.
    * - Highlight search terms.
    * - Expand abbreviations.
    * - Remove/replace deprecated markup.
    *
    * The list is endless. (Well, obviously not the list above, as that has only
    * four items, and certainly ends. But possible applications for output filters
    * are infinite.)
    */
    interface TemplateFilter
    {
    /**
    * Determines suitability of this filter to a section, based on
    * section position and ID.
    * @param int $to_division Section position.
    * @param string $to_division Section position.
    */
    public function should_apply ($to_division, $id);

    /**
    * @param string $title Title to be filtered.
    * @param string $body Body to be filtered.
    * @return Array array(filtered title, filtered body)
    */
    public function apply ($title, $body);
    }

    ?>


    --
    Toby A Inkster BSc (Hons) ARCS
    Contact Me ~ http://tobyinkster.co.uk/contact

    Comment

    • Erwin Moller

      #3
      Re: Separation of logic, design and data

      Frank van Wensveen wrote:
      Friend, coders, fellow wage slaves, lend my your ears.
      >
      I believe that in a perfect world the design of a website (or feature
      on a website) should be totally separated from its design and the data
      it serves up. I'd like some suggestions on good ways to do this,
      because in the real world it can be quite difficult.
      >
      For example, if I'm rummaging around in a MySQL database, the table
      structure and the code that generates the SQL requests are often
      interrelated. Restructure your table(s) and you have to update your
      code accordingly.
      >
      Another, more serious issue is the separation of design from code. For
      example, if I'm using tables to divide my pages into separate 'blocks'
      (e.g. for a top bar, menu, content section, side bar, banner space,
      etc.) then the structure of these tables and table cells are
      interrelated with the program's flow: you set up a table or table
      cell, do something that outputs data into that cell, close the cell
      and/or table, and move on to the next cell to do something else there.
      Removing or adding a cell will mean that the function(s) that output
      data into that cell should or should not be called. Or the order in
      which code is executed could be affected: if I want a page-wide top
      bar cell followed by a menu column and a content window underneath, I
      need to render the top bar table row first, spanning two columns, then
      start a new table row in which I'd put the menu and content cell. But
      if I want a menu bar all the way to the top of the screen and a top
      bar cell followed by a content cell both to the right hand side of the
      menu column, I need to render the menu cell first, spanning two rows,
      and then progress to rendering the top bar and content cells.
      >
      One could of course take abstraction and modularization to extreme
      levels (e.g. put every line of table-related code into a separate
      template file and include that depending on program flow) but this
      quickly increased both complexity and overhead to beyond what is
      acceptable. Not to mention the fact that ideally one should not issue
      function calls from within a content template file.
      >
      So how do real developers do this?
      >
      Hi Frank,

      Toby gave a nice response + examplecode.
      I just want to add a fairly simple way to achieve the same: includefiles.

      If you combine css with seperate files, you gain large flexibility when it
      comes to changing layout, etc.
      For example: If you have a navigationbar with many links (for admin eg),
      just include a file that contains them.
      You can simply include it above every page that uses it.
      If you need to add/change anything, you have just one place to check.
      Same goes for footers, or other parts of html.

      It is easy to build, and easy to understand, and easy to implement, and easy
      to change. :-)

      Disclaimer: I am not claiming this approach is better than some
      template/parsing engine. It is just another way to approach the subject.

      Regards,
      Erwin Moller
      >
      >
      Regards,
      Frank

      Comment

      • Ian M Robertson

        #4
        Re: Separation of logic, design and data

        Erwin Moller wrote:
        Frank van Wensveen wrote:
        >
        >Friend, coders, fellow wage slaves, lend my your ears.
        >>
        >I believe that in a perfect world the design of a website (or feature
        >on a website) should be totally separated from its design and the data
        >it serves up. I'd like some suggestions on good ways to do this,
        >because in the real world it can be quite difficult.
        ---SNIP
        >
        Hi Frank,
        >
        Toby gave a nice response + examplecode.
        I just want to add a fairly simple way to achieve the same: includefiles.
        --- SNIP
        Disclaimer: I am not claiming this approach is better than some
        template/parsing engine. It is just another way to approach the subject.
        One template engine worth a look is smarty ( http://smarty.php.net ) gives
        good separation of source php and markup html

        IanR

        --
        homepage http://narian.org.uk

        Comment

        • Kenneth Downs

          #5
          Re: Separation of logic, design and data

          Frank van Wensveen wrote:
          >
          For example, if I'm rummaging around in a MySQL database, the table
          structure and the code that generates the SQL requests are often
          interrelated. Restructure your table(s) and you have to update your
          code accordingly.
          Exactly. The database and the code are not only interrelated, they are
          married, or perhaps they are blood brothers, they can never be separated.
          The code has to know about the structure of the tables.

          There are two solutions to making this manageable. The historical solution
          was the use of library code and data dictionaries. When OO mania came
          along we got involved in the Viet Nam of software engineering: ORM.

          I have tried both and found the classical solution to be far more practical.
          The real difference in approach is that the classic solution requires a
          little abstract thinking, while the ORM approach leads to a lot of ad-hoc
          table-by-table coding.


          --
          Kenneth Downs
          Secure Data Software, Inc.
          (Ken)nneth@(Sec )ure(Dat)a(.com )

          Comment

          • Toby Inkster

            #6
            Re: Separation of logic, design and data

            Erwin Moller wrote:
            For example: If you have a navigationbar with many links (for admin eg),
            just include a file that contains them.
            You can simply include it above every page that uses it.
            If you need to add/change anything, you have just one place to check.
            Same goes for footers, or other parts of html.
            But, in your example, if you have include("nav-links.html") scattered
            about on many pages, but you want to move your navigation links from,
            say, the top of the page to the bottom, then you need to change each file
            that includes it. With mine, you only change one file.

            The method you describe above is how I started using PHP, but as you start
            building progressively more complicated sites, it eventually begins to
            show its weaknesses. I started there, and now I'm here at my Template
            interface solution, and I went through several different techniques on the
            way. I'm sure at some point in the future I'll see the weaknesses in my
            current technique and move on to something even better, though I'm not
            sure what that might be.

            Ian mentioned Smarty. I've investigated that too, but found it lacked what
            I needed out of a template engine. Smarty looks handy for when there are
            large invariable chunks of HTML that need to be used on many pages, and a
            handful of variables that just need to be slotted into them. It's not for
            me though.

            --
            Toby A Inkster BSc (Hons) ARCS
            Contact Me ~ http://tobyinkster.co.uk/contact

            Comment

            • Toby Inkster

              #7
              Re: Separation of logic, design and data

              Kenneth Downs wrote:
              Exactly. The database and the code are not only interrelated, they are
              married, or perhaps they are blood brothers, they can never be separated.
              The code has to know about the structure of the tables.
              Well, "the dream" is to build as little database information into the code
              as possible, and have it infer as much as it can by querying the database
              itself. But there's a limit to how much can be done in this area.

              --
              Toby A Inkster BSc (Hons) ARCS
              Contact Me ~ http://tobyinkster.co.uk/contact

              Comment

              • pittendrigh

                #8
                Re: Separation of logic, design and data

                Someone wrote:
                The database and the code are not only interrelated, they are
                married, or perhaps they are blood brothers, they can never be separated.
                The code has to know about the structure of the tables.
                This is true in the general relational tables case, but not in all
                cases.
                Html is inherently hierarchical. It can be modelled and stored in
                hierarchical structures, where each
                node in the hierarchy represents a widget or div or paragraph in the
                page,
                and each such node can be adorned with a node_type attribute that
                permanently ties it to a particular display behavior.

                If you work with two *semi-mirror-image* hierarchies: one for defining
                page layouts
                and one for defining the data that gets pasted into its matching layout
                hierarchy,
                then it's possible to make a semi-automated system that works from a
                point
                and click editor, rather than the keyboard of a programmer.

                Each page-type display hierarchy may have many data sets that can be
                pasted
                in, to make an arbitrary number of page instantiations for that layout.

                To make each page the code loops through both hierarchies, pasting data
                into
                nodes in the layout, and then renders each node by default behavior.

                When a system works that way you do not have to change anything about
                the display code when the data changes. All you need is a point and
                click
                editor that creates hierarchical display definitions and the mirror
                image
                data sets to paste into the displays. Once you have the editor, you
                never need the programmer again.

                In other words you have a form that creates a form that defines a
                layout
                as a hierarchy. The rest can happen--forever--as drag and drop and
                click.

                Comment

                • Anthony Smith

                  #9
                  Re: Separation of logic, design and data

                  It is time for PHP to come up with something like Java's Hibernate &
                  Spring. They was a PHP implementation of Java's Struts, but it has not
                  been modified in a year or so. I think we all may need to join in the
                  party to help out.

                  On Jan 24, 8:12 am, "pittendrig h" <Sandy.Pittendr ...@gmail.comwr ote:
                  Someone wrote:
                  The database and the code are not only interrelated, they are
                  married, or perhaps they are blood brothers, they can never be separated.
                  The code has to know about the structure of the tables.This is true in the general relational tables case, but not in all
                  cases.
                  Html is inherently hierarchical. It can be modelled and stored in
                  hierarchical structures, where each
                  node in the hierarchy represents a widget or div or paragraph in the
                  page,
                  and each such node can be adorned with a node_type attribute that
                  permanently ties it to a particular display behavior.
                  >
                  If you work with two *semi-mirror-image* hierarchies: one for defining
                  page layouts
                  and one for defining the data that gets pasted into its matching layout
                  hierarchy,
                  then it's possible to make a semi-automated system that works from a
                  point
                  and click editor, rather than the keyboard of a programmer.
                  >
                  Each page-type display hierarchy may have many data sets that can be
                  pasted
                  in, to make an arbitrary number of page instantiations for that layout.
                  >
                  To make each page the code loops through both hierarchies, pasting data
                  into
                  nodes in the layout, and then renders each node by default behavior.
                  >
                  When a system works that way you do not have to change anything about
                  the display code when the data changes. All you need is a point and
                  click
                  editor that creates hierarchical display definitions and the mirror
                  image
                  data sets to paste into the displays. Once you have the editor, you
                  never need the programmer again.
                  >
                  In other words you have a form that creates a form that defines a
                  layout
                  as a hierarchy. The rest can happen--forever--as drag and drop and
                  click.

                  Comment

                  • Erwin Moller

                    #10
                    Re: Separation of logic, design and data

                    Toby Inkster wrote:
                    Erwin Moller wrote:
                    >
                    >For example: If you have a navigationbar with many links (for admin eg),
                    >just include a file that contains them.
                    >You can simply include it above every page that uses it.
                    >If you need to add/change anything, you have just one place to check.
                    >Same goes for footers, or other parts of html.
                    >
                    But, in your example, if you have include("nav-links.html") scattered
                    about on many pages, but you want to move your navigation links from,
                    say, the top of the page to the bottom, then you need to change each file
                    that includes it. With mine, you only change one file.
                    True.
                    That is the weakness of using includes for HTML pieces.
                    It can be overcome by using an include in the include, like this:
                    in header of page:
                    <?php include 'headerstuff.ph p'; ?>

                    and at bottom:
                    <?php include 'footerstuff.ph p'; ?>

                    And then put in the headerstuff.php another include:
                    [headerstuff.php :]
                    <?php include 'contactinforma tion.php'; ?>

                    If set up like that you can easily move/modify from header to footer by
                    editting/moving contactinformat ion.php from headerstuff.php to
                    footerstuff.php .

                    But I must admit that approach tends to get a little messy. :-)
                    And also you must decide beforehand WHERE you want your possible includes.

                    Personally I prefer the simplicity of includes over the use of a
                    templatesystem.

                    I think your template approach is much better if you have to maintain a
                    website that changes a lot. Then the original extra overhead pays back in
                    10-fold I expect. :-)

                    just my 2 cent..

                    Regards,
                    Erwin Moller
                    >
                    The method you describe above is how I started using PHP, but as you start
                    building progressively more complicated sites, it eventually begins to
                    show its weaknesses. I started there, and now I'm here at my Template
                    interface solution, and I went through several different techniques on the
                    way. I'm sure at some point in the future I'll see the weaknesses in my
                    current technique and move on to something even better, though I'm not
                    sure what that might be.
                    >
                    Ian mentioned Smarty. I've investigated that too, but found it lacked what
                    I needed out of a template engine. Smarty looks handy for when there are
                    large invariable chunks of HTML that need to be used on many pages, and a
                    handful of variables that just need to be slotted into them. It's not for
                    me though.
                    >

                    Comment

                    • Kenneth Downs

                      #11
                      Re: Separation of logic, design and data

                      Toby Inkster wrote:
                      Kenneth Downs wrote:
                      >
                      >Exactly. The database and the code are not only interrelated, they are
                      >married, or perhaps they are blood brothers, they can never be separated.
                      >The code has to know about the structure of the tables.
                      >
                      Well, "the dream" is to build as little database information into the code
                      as possible, and have it infer as much as it can by querying the database
                      itself. But there's a limit to how much can be done in this area.
                      >
                      The completion of "the dream" is to have the library know nothing about any
                      specific app which is easy if you have a complete dictionary. This is what
                      we have done, our libraries have zero knowledge of any specific database.
                      Here is how it works.

                      We use a tool to build/upgrade databases out of a dictionary. When the build
                      is complete, it takes the dictionary and generates a bunch of include files
                      for PHP that contain associative arrays describing each table. Any
                      function that needs to access a database loads the relevant arrays and
                      determines whatever it needs to know about the table(s).

                      In terms of the UI, the gen-spec equation falls usually in favor of
                      specialization, meaning it pays in the business sense to write specific
                      files for specific apps that "know" about tables and columns, because that
                      is what makes that app valuable to a paying customer.

                      --
                      Kenneth Downs
                      Secure Data Software, Inc.
                      (Ken)nneth@(Sec )ure(Dat)a(.com )

                      Comment

                      Working...