A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Jump to

Quick reference

Showing posts with label logic. Show all posts
Showing posts with label logic. Show all posts

When to use "or" and when to use || (double pipe) in Perl

Use || for assigning to a variable:

$a = $b || $c

Use "or" to control program flow:

$a = $b or die 'error: $b is unexpectedly false'

Mnemonic: || is a symbol like variables and numbers are, while "or" and "die" are both english words.

(source, source)

Why shouldn't you put logic in the template?

The overall reason for keeping business logic separate from presentation is well known, see MVC.

Here are the practical reasons why putting business logic in the template is a really bad idea:
  • You can't re-use it
  • You can't unit test it
  • You can't log
  • You can't validate parameters to subroutines
  • You often can't create subroutines at all (and you shouldn't)
  • You can't use an IDE to look up method definitions
  • You can't "use strict"
  • You can't run a code tidier
  • You can't validate syntax
  • Error messages are different
  • Keyword behaviour can be subtly different, leading to the worst kind of bug - the one you don't notice until it's too late.
  • Now you have two languages to maintain instead of one
Logic which relates directly to the display of the page is borderline okay, although for the reasons stated above it's better to put as much of that as possible in a class/module, which could be called a View Model.

Corollary - don't pass the entire model to the template, only stash what is needed. Reasons for this:

  • Separation of concerns - the template should be editable by a front-end dev without any knowledge of syntax to specify models
  • Performance may be poor - for example if the model opens a new database connection each time it's called


This article was written with Perl and Template Toolkit in mind.

Test MySQL date calculations

This is a way to test certain SQL queries involving dates. Say a query is supposed to select "Last Saturday", regardless of the date on which it runs:
SELECT DATE_SUB(CURDATE(), INTERVAL WEEKDAY(DATE_SUB(CURDATE(), INTERVAL 5 DAY)) DAY) AS 'Last Saturday';

How do you know if it really works on all days? This command will iterate through all the days in the month, and run the query with each date to see what it gets:

for day in $(seq 1 30)
do
    echo Nov $day, $(mysql -u sdkain -h db21 lf_wh -e"SELECT DATE_SUB('2010-11-$day', INTERVAL WEEKDAY(DATE_SUB('2010-11-$day', INTERVAL 6 DAY)) DAY) AS 'Last Sunday'")
done

Remember to test for when the year changes, and on leap years.

Min/Max for XSLT

Obtaining the MIN:
<!-- Create a variable named $minEventDate containing the MIN date -->
<xsl:variable name="minEventDate">
<xsl:for-each select="event">
<xsl:sort select="@date" data-type="text" order="ascending" />
<xsl:if test="position() = 1">
<xsl:value-of select="@date" />
</xsl:if>
</xsl:for-each>
</xsl:variable>

Obtaining the MAX:
<!-- Create a variable named $maxEventDate containing the MAX date -->
<xsl:variable name="maxEventDate">
<xsl:for-each select="event">
<xsl:sort select="@date" data-type="text" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="@date" />
</xsl:if>
</xsl:for-each>
</xsl:variable>

(If, Then, Else) LOGIC in XSL

Syntax:
<xsl:if test="XXX">
<!-- do something -->
</xsl:if>

<xsl:choose>
<xsl:when test="XXX">
<!-- do one thing -->
</xsl:when>
<xsl:when test="YYY">
<!-- do another thing -->
</xsl:when>
<xsl:otherwise>
<!-- do default thing -->
</xsl:otherwise>
</xsl:choose>


Logic examples:
<xsl:when test="matches(sql:feedurl_id, '^(\d+)$')">
<xsl:if test="$canonical-urls/agg:canonical-url[text()=$canonical-link-href][1]/@module = $module-type">
<xsl:when test="$module-type = 'knowledge'">
<xsl:when test="$module-type='iplayer' or $module-type='schedule'">
<xsl:if test="$debug">
<xsl:when test="document('')//this:modules/this:module[@type=$module-type]/this:merge-feeds">
<xsl:if test="position()=1">
<xsl:if test="position()=3 and count(agg:module)=0">
<xsl:when test="starts-with($name,'profile') or starts-with($name,'weather')">
<xsl:when test="starts-with(@type,'profile')">
<xsl:when test="@type='weather'">
<xsl:when test="count($modules/agg:modules/agg:module[starts-with(@type,'profile')])>0">