Peter Stuifzand

Template 'table' filter

After these two changes I got into an object-oriented (with a splash of functional and generic programming) mindset. So I created a table filter in my template code. A filter is a function that transforms a data structure to an HTML string.

This filter transforms a template parameter value from an arrayref to an HTML table. Currently it only supports lists of items, but it could be expanded to single items. I’m not sure how useful that would be, however. The question is: “How can we produce a nice HTML table from an arrayref?” The answer lies in the use of objects.

A few months ago I created a few classes that allow me to easily transform arrayrefs to HTML. I wrote one Model class and one Render class. The Model class models the information in a list. It’s not always required, because the Render class also renders simple arrays, without a model.

The Model classes (there are three, at the moment), have at least three methods: update, length, item. The three classes all implement these methods.

The Render class renders these list Models. The important method on this class is the render method. It renders a HTML version of the table. The set_header method accompanies the render method. The set_header method sets the description of the table structure. This description is an arrayref with an item for each column in the table. Each item consists of, at least, a field and a title. It’s also possible to add a class or a link.

These two classes are combined in the template code in the template_table function.

sub template_table {
    my ($type, $value) = @_;
    my $table = Render::Table->new();
    $table->set_header(...);
    $table->set_model(Model::Table::List->new($value));
    return $table->render;
}

This function renders the table, but notice that the set_header function lacks an argument. What argument should we use?

In a explicitly typed language we would have known the type of the $value argument. In Perl we only know that it’s an arrayref. However, we can ignore the type of the value inside. The render function only needs a description of the table to be able to render the HTML. The best way to do this is, is by calling a method on the $value. In this case that’s a call to the first value: $value->[0]->column_descriptions.

This change adds two preconditions to the function. Ignoring these preconditions, introduces an error. This function only works for non-empty arrays, where the first value has a method, that returns a table description.

What should we do? Can we declare these preconditions? How do we cope with these?

The first precondition — handling empty arrays — can be removed when we add code that returns a table when an empty array is passed as an argument. To solve it we return an empty string. To return an empty table based on the structure of the first value element would be really hard.

The second precondition — the value should contain the method — is already handled by Perl itself; it will throw an exception when the method missing. It could be a problem that we have to test the code, to find this error.

It like how this chunk of code enables us to remove the simpler table generating pieces of template code. These guidelines enabled me to write simpler code.

  • Write code for arrays, ignorant of the type inside.
  • Use objects instead of primitive types. Call methods on those objects.
  • Allow the value to tell you what to do with it.
  • Look for preconditions in your code and know how these are handled.
  • Make your code more general by moving specific code to specific classes.
© 2023 Peter Stuifzand