Wednesday, January 25, 2012

Notes on making a module distribution for CPAN

These notes are for creating a Perl CPAN module using Module::Build with some help from Module::Starter. I chose to use Module::Build because it is newer and was created to resolve various problems with the older ExtUtils::MakeMaker. The maintainer of ExtUtils::MakeMaker recommends using Module::Build.

Execute module-starter:

module-starter --mb --module=My::Module --author="Author Name" --email=author@email.com

Options used:

  • --mb - The build system to use. This is shorthand for --builder=Module::Build.
  • --module=My::Module - The name of the module that you want to build. A folder named My-Module will be created based on this.
  • --author="Author Name" - The name of the module author. The author, as well as the copyright and licensing, will be under this name in the README file and POD documentation.
  • --email=author@email.com - The author's email address

The following files are created:

  • Build.PL - Used to generate the Build script for this module. Under build_requires, you should add any other modules which this depends on. (This is a hash mapping from the module name to the required module version or 0 if no version is specified.)
  • Changes - A log of changes to this module. This is for the module maintainer to update with each version. You should modify the log entry for the initial version.
  • ignore.txt - An ignore file for your SCM.
  • lib/My/Module.pm - The module code, in the lib directory, with the folder structure following the module namespace structure. This should include the module version number and POD documentation (preferably after __END__.
  • MANIFEST - Lists the files contained in this distribution.
  • README - Provides an introduction to the module, as well as information about installation, documentation and licensing.
  • t/*.t - Various test files in which you will need to add your own unit tests.

Friday, January 20, 2012

Setting up a mini CPAN for private modules (Windows 2003 x64)

Set up CPAN::Mini

  1. Install the CPAN::Mini module.
  2. Create the file structure where the mini CPAN be.
  3. D:/www/MINICPAN
    D:/www/MINICPAN/authors
    D:/www/MINICPAN/authors/01mailrc.txt.gz (empty file)
    D:/www/MINICPAN/modules
    D:/www/MINICPAN/modules/02packages.details.txt.gz (empty file)
    
  4. Create the config file lib/CPAN/Mini/minicpan.conf (this is needed particularly for using CPAN::Mini::Webserver) with the following contents.
  5. local:  D:/www/MINICPAN/
    remote: http://mirror.optusnet.com.au/CPAN/ # or some other mirror from http://www.cpan.org/SITES.html
    exact_mirror: 1
    
  6. Set the CPAN_MINI_CONFIG environment variable to point to lib/CPAN/Mini/minicpan.conf. (Even though the conf file was created in a default location, this is not recognised in Windows.)

I didn't execute minicpan, because I only wanted my own private modules in here. But if I were to run it (which would have set up the mini CPAN for me):

minicpan -l D:/www/MINICPAN/ -r http://mirror.optusnet.com.au/CPAN/ # or some other mirror from http://www.cpan.org/SITES.html

Set up the webserver

  1. Install CPAN::Mini::Webserver module
  2. Execute minicpan_webserver

Set up CPAN::Mini::Inject

  1. Install the CPAN::Mini::Inject module.
  2. Create the config file D:/.mcpani/config with the following contents.
  3. local: D:/www/MINICPAN
    remote: ftp://ftp.cpan.org/pub/CPAN ftp://ftp.kernel.org/pub/CPAN
    repository: D:/MINICPAN
    passive: yes
    dirmode: 0755
    
  4. Set the MCPANI_CONFIG environment variable to D:\.mcpani\config.

Using the mini CPAN

  1. Upload modules to the mini CPAN.
  2. # add your modules to a repository
    mcpani --add --module My::Module --authorid STEVENL --modversion 0.001 --file My-Module-0.001.tar.gz
    # upload the repository modules into mini CPAN
    mcpani --inject
    
  3. Install modules from the mini CPAN (using cpanminus).
  4. cpanm --mirror file://D:/www/MINICPAN My::Module
    cpanm --mirror http://[SERVER:PORT] My::Module
    

Wednesday, January 11, 2012

Software Architectural Tactics

Availability Tactics

Fault Detection

  • Ping/echo
  • Heartbeat (dead man timer_
  • Exceptions

Fault Recovery

  • Voting
  • Active redundancy (hot restart)
  • Passive redundancy (warm restart, dual/triple redundancy
  • Spare
  • Shadow operation
  • State resynchronisation
  • Checkpoint/rollback

Fault Prevention

  • Removal from service
  • Transactions
  • Process monitor

Modifiability Tactics

Localise Modifications

  • Maintain semantic coherence
  • Anticipate expected changes
  • Generalise the module
  • Limit the possible options
  • Abstract common services

Prevent Ripple Effects

  • Hide information
  • Maintain existing interfaces
  • Restrict communication paths
  • Use an intermediary

Defer Binding Time

  • Runtime registration
  • Configuration files
  • Polymorphism
  • Component replacement
  • Adherence to defined protocols

Performance Tactics

Resource Demand

  • Increase computational efficiency
  • Reduce computational overhead
  • Manage event rate
  • Control frequency of sampling
  • Bound execution times
  • Bound queue size

Resource Management

  • Introduce concurrency
  • Maintain multiple copies of either data or computations
  • Increase available resources

Resource Arbitration

  • First-in/First-out (FIFO)
  • Fixed-priority scheduling
  • Dynamic priority scheduling
  • Static scheduling

Security Tactics

Resisting Attacks

  • Authenticate users
  • Authorize users (access control, user groups)
  • Maintain data confidentiality
  • Maintain integrity
  • Limit exposure
  • Limit access

Detecting Attacks

  • Intrusion detection

Recovering from Attacks

  • State restoration (see Availability tactics)
  • Maintain audit trail (identify attacker)

Testability Tactics

Manage Input/Output

  • Record/playback
  • Separate interface from implementaiton
  • Specialize access routes/interfaces

Internal Monitoring

  • Built-in monitors

Usability Tactics

Runtime Tactics

  • Support user initiative (error correction, e.g. cancel, undo; user efficiency, e.g. aggregate, multiple views)
  • Support system initiative (maintain user/task/system models)
  • Design-Time Tactics

    • Separate the user interface (e.g. MVC)

    Reference

    Len Bass, Paul Clements, Rick Kazman, Software Architecture in Practice (2nd ed.). Addison-Wesley, 2003.

    Digital Photo Printing

    Recently I've been editing some of my digital photos with Photoshop and prepared them for printing. As it happened, a vibrant looking picture on the screen came out with dull colours. This led me to learn about photo Colour Profiles, particularly sRGB and Adobe RGB. Plenty has been written about (just google "sRGB vs Adobe RGB") but here is what I've had to do this time to tweak the picture quality.

    My point-and-click camera by default produces photos with a "sRGB" profile, which looked perfectly ok on my screen, but this was what came out looking dull after printing. Adobe RGB is meant to use a broader range of colours, which looks too deep on the screen, but printed much better.

    In Photoshop (CS4), to convert the picture to Adobe RGB:
    1. Edit » Convert to Profile...
    2. Select Adobe RGB under Destination Space).
    From an article I read, it says that sRGB is sufficient for everything. I suspect that is the case if I don't Photoshop anything. That's for another day to check.

    Thursday, December 22, 2011

    DBIx::Class

    I've recently been looking for a Perl ORM. The 2 current contenders are:

    1. DBIx::Class (DBIC)
    2. Rose::DB::Object (RDO)

    Initially, I preferred RDO because it looked easier to learn because it was better documented and its scope was smaller. More importantly, it was built for speed which is a high priority for me right now. The main problem was that it does not work with MS SQL. So that was the end of that.

    DBIx::Class was my second choice because it is built for flexibility rather than speed. But with Rose::DB::Object not available for me, this became the default choice. Still it's said to be faster than the older DBI::Class, and there are the documentation has tips for improving speed. And I'm not complaining about having the flexibility. Initially, it did take a little searching around documentation to get it to work, but once I got it working it didn't seem too difficult at all.

    Here's some code for a quick start. Begin with the schema class.

    package MySchema;
    use base 'DBIx::Class::Schema';
    __PACKAGE__->load_namespaces;
    

    Define the classes which correspond to tables in the database (assuming they already exist). These classes will be automatically detected when you create the schema object. There is a module that allows you to auto-load these without having to specify them, but the performance is slower.

    package MySchema::Result::MyTable;
    use base 'DBIx::Class::Core';
    __PACKAGE__->table('tablename');
    __PACKAGE__->add_columns(qw/ col1 col2 col3 /);
    __PACKAGE__->set_primary_key(qw/ col1 col2 /);
    

    Then it's ready to use.

    package main;
    my $schema = MySchema->connect($dsn, $dbuser, $dbpass, \%attr);
    
    # query the table: WHERE col1 = 1
    my $resultset = $schema->resultset('MyTable')->search({ col1 => 1 });
    
    # a cool feature of the result sets is that you can chain queries.
    
    # iterate the rows of the result set
    while (my $row = $resultset->next) {
        # use the row as an object with accessors for each column
        print $row->col1, "\n";
    }
    

    So far the results set class was autogenerated. But you can subclass your own and create your own custom searches. And a cool thing is that you can then chain these filters.

    package AM::Tariff::DB::ResultSet::CallTypes;
    use base 'DBIx::Class::ResultSet';
    
    sub filter1 {
        my ($self) = @_;
        return $self->search({ col1 => 5 });
    }
    sub filter2 {
        my ($self) = @_;
        return $self->search({ col2 => 3 });
    }
    
    ...
    
    my $rs = $schema->resultset('MyTable')
                    ->filter1
                    ->filter2;
    
    Pretty cool, huh?