Friday, December 04, 2009

Evolution of inclusion

Once upon a time, there was the php include() construct. Reusing part of pages and other code was as simply as:
include 'table.php';
Include files gained the same scope of the parent script, with no need to look for global variables somewhere.
The problem came when there were parameters that influenced the final result, and the included html was a template expecting its variables to assume a value:
$user = new User();
$entries = array(...);
$showCaption = true; 
include 'table.php';
This programming style is also known as Accumulate and fire, and it exposes a not very good Api. There is no way to learn the variables needed to the template, nor to immediately signal errors in population: if I comment $user assignment or set it to an array, the script would not notice until the variable is used deep in table.php.

So the php programmers approach evolved in writing functions and classes that generate html as their only responsibility. These classes are called View Helpers.
Since the generation process involves calling a method, the method's signature takes care of exposing the list of parameters and to validate them.
Some dependencies can be one-time injected via the constructor of a view helper (or via setters), but not every piece of code is prone to being put in a view helper because not every line of code is actually reused. Often this low in logic php code is placed in View classes (usually view scripts in php). View scripts are very simple for designers to modify, although some people think that they should absolutely interpose a layer between the php code and the front-end designers.

View scripts can include an header.php or footer.php to avoid duplication of common code, but this solution does not remove duplication: it only reduces it. Try to change the filename of header.php and you will see.
Thanks to url rewriting, the single point of entry pattern became trivial to implement, and now every serious framework has only one or two top-level php files which are loaded in the browser with different parameters, and that determine which action to perform and which view script to show to the end-user (MVC paradigm in php applications).

Still, there was the problem of configuration: sometimes we need pages with the menu on the right and sometimes not (maybe a forum index is too large). In printable versions no navigation has to be shown; in other pages some submenu can be open or closed depending on the context.
And so the famous Two Step View pattern was implemented, and its process now minimizes code duplication:
  • the action chosen by url parameters is executed and its output consist of some variables, which populates the view. Still there is no Api to refer to, but if you keep view scripts small the problem does not arise often, and there is no mandatory scope mixing by direct include() usage.
  • the chosen first view is rendered and its generated content is saved in a variable, usually via output buffering. In Zend Framework, Zend_View is the object that manages the rendering of a script and which acts as a generic view class. Using view scripts instead of view classes eliminates the need for a templating language: imagine web designers modifying a php class.
  • then the chosen second view is rendered, passing the first result as a variable named by convention, for example $content. In Zend Framework, the second view is a script which is managed by Zend_Layout.
  • both view scripts, which we shall call the view and the layout from now on, have access to view helpers, object injected in the way and in the form you prefer, so that different kinds of tedious html generation can be kept in their cohesive classes and tested independently.
Sometimes a view script still include()s another... But if the code gets complex the latter view script can usually be refactored and transformed in a view helper.


Nikos said...

Good points Giorgio.

Accumulate and Fire is probably a reasonable way to start as a programmer but it won't get you far if you want to evolve as a programmer or if you want to produce high quality low maintenance code.

Your explanation of view scripts is simple and to the point and can easily act as a reference.


Giorgio said...

It was simple to ignore problems when starting out as a php developer, one must pass trough different stages before reaching MVC and other advanced paradigms.

myrtille said...

Hello Giorgio, i read your post and the links you have given.It helps me.Hope to hear from you in future.Thank you.

Anonymous said...

I apologise, but it does not approach me. Perhaps there are still variants?