My four preferences in Perl Web practices

Post on 18-Nov-2014

1896 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

Transcript

My Four Preferences

My Four Preferences

in my Perl Web practice

Architecture and music

Danube

My Four Preferences

in my Perl Web practice

1. Parsing URLs with grammar

2. .ini configuration files

3. WWW::Page

4. XSLT

0. Perl 5.10

1. Parsing URLs with grammar

URL is . . .

URL is . . .

a string

URL is . . .

a string,

a set of parts

URL is . . .

a string,

a set of parts,

a container of parameters

Blog URL scheme

Blog URL scheme/

Blog URL scheme//message‐uri/

Blog URL scheme//message‐uri//tag/tag‐name/

Blog URL scheme//message‐uri//tag/tag‐name//post/

Blog URL scheme//message‐uri//tag/tag‐name//post//message‐uri/post/

Blog URL scheme//message‐uri//tag/tag‐name//post//message‐uri/post//message‐uri/comments/

How to parse?

How to parse?RewriteRules in .htaccess

How to parse?RewriteRules in .htaccess^$ /index.pl?page=home

How to parse?RewriteRules in .htaccess^$ /index.pl?page=home

^post/?$ /post.pl

How to parse?RewriteRules in .htaccess^$ /index.pl?page=home

^post/?$ /post.pl

^([^/]+)/? /index.pl?page=$1

How to parse?RewriteRules in .htaccess^$ /index.pl?page=home

^post/?$ /post.pl

^([^/]+)/? /index.pl?page=$1

etc.

How to parse?RewriteRules in .htaccess

Bad: involves programmingoutside Perl

How to parse?Regular expressions

How to parse?Regular expressionsgiven ($uri) {

   when (/^\/$/) {...}

}

How to parse?Regular expressionsgiven ($uri) {

   when (/^\/$/) {...}

   when (/^\/post\/?/) {...}

}

How to parse?Regular expressionsgiven ($uri) {

   when (/^\/$/) {...}

   when (/^\/post\/?/) {...}

   # (regexes as in .htaccess)

}

How to parse?Regular expressions

Bad: rules are not obvious

How to parse?split builtin

How to parse?split builtin

@parts = split m{/}, $uri;

given (scalar @parts) {

   when (1) {...}

   when (2) {...}

}

How to parse?split builtin

Bad: boring

How to parse?Grammars

How to parse?Grammars

Cool!

How to parse?Grammars

Cool!Easy to maintain

How to parse?Grammars

Cool!Easy to maintainBut might be slow

How to parse?Grammars

Cool!Easy to maintainBut might be slow . . .up to 100 times over regexes.

Gramars

Parse::RecDescent today

Perl 6 grammars tomorrow

Gramars

Parse::RecDescent today

Perl 6 grammars after Christmas

uri          : post EOL

             | view EOL

uri          : post EOL

             | view EOL

post         : post‐message

             | post‐comment

uri          : post EOL

             | view EOL

post         : post‐message

             | post‐comment

view         : view‐message

             | view‐tag

uri          : post EOL

             | view EOL

post         : post‐message

             | post‐comment

view         : view‐message

             | view‐tag

view‐message : ‘/’ word ‘/’

uri          : post EOL

             | view EOL

post         : post‐message

             | post‐comment

view         : view‐message

             | view‐tag

view‐message : ‘/’ word ‘/’

view‐tag     : ‘/tag/’ word ‘/’

uri          : post EOL

             | view EOL

post         : post‐message

             | post‐comment

view         : view‐message

             | view‐tag

view‐message : ‘/’ word ‘/’

view‐tag     : ‘/tag/’ word ‘/’

word         : /\w+/

uri          : post EOL

             | view EOL

post         : post‐message

             | post‐comment

view         : view‐message

             | view‐tag

view‐message : ‘/’ word ‘/’

view‐tag     : ‘/tag/’ word ‘/’

word         : /\w+/

post‐message : ‘/post/’

uri          : post EOL

             | view EOL

post         : post‐message

             | post‐comment

view         : view‐message

             | view‐tag

view‐message : ‘/’ word ‘/’

view‐tag     : ‘/tag/’ word ‘/’

word         : /\w+/

post‐message : ‘/post/’

post‐comment : view‐message ‘/post/’

Actions in grammars

uri : post EOL

    | view EOL

uri : post EOL {

         $action = ‘post’;

      }

    | view EOL

uri : post EOL {

         $action = ‘post’;

      }

    | view EOL {

         $action = ‘view’;

      }

view‐message : ‘/’ word ‘/’

view‐tag     : ‘/tag/’ word ‘/’

view‐message : ‘/’ word ‘/’ {

                  $msg_sid = $item{word};

               }

view‐tag     : ‘/tag/’ word ‘/’

view‐message : ‘/’ word ‘/’ {

                  $msg_sid = $item{word};

               }

view‐tag     : ‘/tag/’ word ‘/’ {

                  $action = ‘view‐tag’;

                  $tag = $item{word};

               }

http://example.com/twincity/

$action = ‘view’;

$msg_sid = ‘twincity’;

http://example.com/twincity/

$action = ‘view’;

$msg_sid = ‘twincity’;

http://example.com/tag/workshop/

$action = ‘view‐tag’;

$tag = ‘workshop’;

my %uri = (

    '/'              => {

                       'type' => 'index',

                     },

    '/alpha/'        => {

                       'type' => 'section',

                       'sectionUri' => 'alpha',

                       'sectionPage' => 1,

                     },

    '/beta‐2/34/14/' => {

                       'type' => 'message',

                       'sectionUri' => 'beta',

                       'sectionPage' => 2,

                       'threadID' => 34,

                       'threadPage' => 1,

                       'messageID' => 14,

                     },

    '/‐/'            => {

                       'type' => '404',

                     });

for $uri (keys %uri) {    

    $parser‐>parse($uri);

    cmp_deeply(

        $parser‐>{data},

        $uri{$uri},

        $uri

    );

}

Grammars are

logical

Grammars are

logical,

easy to extend

Grammars are

logical,

easy to extend,

cacheable

Grammars are

logical,

easy to extend,

cacheable,

easy to test

2. .ini configuration files

Application =

code + configuration

Example: blog

number of messages per page

#!/usr/bin/perl

my $MSG_PER_PAGE = 10;

#!/usr/bin/perl

my $MSG_PER_PAGE = 10;

Load configuration from external file

Load configuration from external non-Perl file

<config>

   <page_length>10</page_length>

</config>

Question: XML

or JSON

or YAML

?

Answer: Windows INI

[page]

length=10

[section]

page_length=10

[thread]

page_length=10

[obsene]

replacement=***

[preview]

last_posts=31

last_message_length=200

global.ini local.ini

global.ini local.ini

[page]

length=10

[db]

host=db.int

port=3333

[db]

host=localhost

port=3306

use Config::INI::Access;

config‐>load("conf/config.ini");

use Config::INI::Access;

config‐>load("conf/config.ini");

config‐>load("conf/local.ini");

use Config::INI::Access;

config‐>load("conf/config.ini");

config‐>load("conf/local.ini");

say config‐>db‐>host;

[db]

host=localhost

port=3306

say config‐>db‐>host;

3. WWW::Page

WWW::Page

is a kinda MVC

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    use WWW::Page;

    use encoding 'utf‐8';

    my $page = new WWW::Page ({

        'xslt‐root'       => "../data/xsl",

    });

    print $page‐>as_string();

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

            sub Import::Client::keywordList

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    package Import::Client;

    sub keywordList    {        my ($this, $page, $node, $args) = @_;            my $sth = $dbh‐>prepare(            "select keyword, uri from keywords");        $sth‐>execute();        while (my ($keyword, $uri) = $sth‐>fetchrow_array())        {            my $item =                 $page‐>{'xml'}‐>createElement ('item');            $item‐>appendText($keyword);            $item‐>setAttribute('uri', $uri);            $node‐>appendChild($item);        }            return $node;    }

    package Import::Client;

    sub keywordList    {        my ($this, $page, $node, $args) = @_;            my $sth = $dbh‐>prepare(            "select keyword, uri from keywords");        $sth‐>execute();        while (my ($keyword, $uri) = $sth‐>fetchrow_array())        {            my $item =                 $page‐>{'xml'}‐>createElement ('item');            $item‐>appendText($keyword);            $item‐>setAttribute('uri', $uri);            $node‐>appendChild($item);        }            return $node;    }

    package Import::Client;

    sub keywordList    {        my ($this, $page, $node, $args) = @_;            my $sth = $dbh‐>prepare(            "select keyword, uri from keywords");        $sth‐>execute();        while (my ($keyword, $uri) = $sth‐>fetchrow_array())        {            my $item =                 $page‐>{'xml'}‐>createElement ('item');            $item‐>appendText($keyword);            $item‐>setAttribute('uri', $uri);            $node‐>appendChild($item);        }            return $node;    }

    package Import::Client;

    sub keywordList    {        my ($this, $page, $node, $args) = @_;            my $sth = $dbh‐>prepare(            "select keyword, uri from keywords");        $sth‐>execute();        while (my ($keyword, $uri) = $sth‐>fetchrow_array())        {            my $item =                 $page‐>{'xml'}‐>createElement ('item');            $item‐>appendText($keyword);            $item‐>setAttribute('uri', $uri);            $node‐>appendChild($item);        }            return $node;    }

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

<keyword‐list>

    <item uri="http://perl.org/">Perl</item>

    <item uri="http://dev.perl.org/">Perl 6</item>

    <item uri="http://bbc.co.uk/">Perl on rails</item>

</keyword‐list>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <keyword‐list> . . . </keyword‐list>

        </manifest>

    

        <content>

            <month‐calendar> . . . </month‐calendar>

        </content>

    </page>

Possible improvements

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <page:keyword‐list remote="host2">

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <page:keyword‐list remote="host2">

        </manifest>

    

        <content>

            <page:month‐calendar cache="memcached"/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <page:keyword‐list remote="host2">

        </manifest>

    

        <content>

            <page:month‐calendar cache="xml"/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <page:keyword‐list remote="host2">

        </manifest>

    

        <content>

            <page:month‐calendar transform="other.xsl"/>

        </content>

    </page>

4. XSLT

Not .WHAT XSLT is

but .WHY I use it

4a. XSLT: divide and power

website = logic + layout

website = Perl-code + HTML

website = Perl-code + XML+XSLT

website = Perl-code + XML+XSLT

Perl programmer XSLT coder

XML+XSLT

Perl programmer XSLT coder

website = Perl-code +

4b. XSLT: multiple languages

en.xml 

<strings>

    <months>

       <item>January</item>

       <item>February</item>

          . . .

       <item>December</item>

    </months>

</strings>

de.xml 

<strings>

    <months>

       <item>Januar</item>

       <item>Februar</item>

          . . .

       <item>Dezember</item>

    </months>

</strings>

at.xml 

<strings>

    <months>

       <item>Jänner</item>

       <item>Februar</item>

          . . .

       <item>Dezember</item>

    </months>

</strings>

<xsl:variable name="str">

    <xsl:copy‐of select="

       document(

          concat($lang, ‘.xml’)

       )"/>

</xsl:variable>

<xsl:variable name="str">

    <xsl:copy‐of select="

       document(

          concat($lang, ‘.xml’)

       )/strings"/>

</xsl:variable>

<date day="7" month="11" year="2008"/>

<date day="7" month="11" year="2008"/>

<xsl:value‐of select="@day"/>

<date day="7" month="11" year="2008"/>

<xsl:value‐of select="@year"/>

<date day="7" month="11" year="2008"/>

<xsl:value‐of 

    select="$str/months/item[@month]"/>

4b. XSLT: multiple layouts

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="pda/view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="iphone/view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

    <?xml version="1.0" encoding="UTF‐8"?>

    <page

        import="Import::Client"

        transform="rss/view.xsl"

        xmlns:page="urn:www‐page">

    

        <manifest>

            <title>WWW::Page Web‐Site</title>

            <locale>en‐gb</locale>

            <page:keyword‐list/>

        </manifest>

    

        <content>

            <page:month‐calendar/>

        </content>

    </page>

XML+XSLT

Perl programmer XSLT coder

website = Perl-code +

XML+XSLT

Perl programmer XSLT coder

website = Perl-code +

XSLT coder

XSLT coder

XSLT coder

__END__

Andrew Shitov

http://andy.sh | mail@andy.sh

top related