Searching for Mrs X

So yesterday I muddled myself up quite well, so It took a little time to see if I could come up with a solution. Thinking that someone else might have had the same problem I did a troll of Map of CPAN looking for a MooseX that might help me out.

Now I was looking at briefly at one point of using a delegated object but the problems with that is I contaminated my parent object with unneeded code and I would also have to iterate all the way though my attributes, never a good practice.

I wrote a Perl book

(This article is cross posted here and on my own blog)

I wrote a Perl book accidentally during my vacation. I started typing and everything just fell out of my head over the next few days. Its still pretty rough but I think its a decent start.

The book is called Minimum Viable Perl..

mvp-book.jpg

Ok, its not a real published book. Maybe I’ll self publish it on Amazon some day. For now its just a website. I’m going to call it a book anyway.

What its about

This book is for developers who want to get up to speed with Perl quickly through concise tutorials (about 1 screenful in size).

Being concise is one of the primary goals. In the age of stackoverflow and blogs and info graphics everyone is in a hurry. People shouldn’t have to wade through unnecessary prose. I literally review each sentence in each article and try to remove unnecessary words.

Well that's not it!!

So lets see how I am going to move those annoying 'sub SQL' that I have in my DA::View and DA::Element packages out of them and into my LSDs.

So going blindly where I have gone before though the I might Role for the Element class in DA::LSD::SQL and see what I can come up with. So I duly added this

 package 
     DA::LSD::SQL_D::Element;
  use Moose::Role;
  sub retrieve {
        my $self = shift;
        if ( $self->alias() ) {
            return $self->name() . "  AS " . $self->alias();
        }
        else {
            return $self->name();
        }
    }
Now I renamed the SQL sub to retrieve just to keep it separate and then after playing about for a long while the best I could come up with was this in my DA retrieve sub

...
if ($conn eq 'DBH'){
      apply_all_roles( $lsd, "DA::LSD::SQL_D");
      foreach my $elememt (@{$self->elements()}) {
           apply_all_roles( $elememt, "DA::LSD::SQL_D::Element");
       }
   }
...
Then all I needed to do was change my _execute sub in LSD::SQL a little like this

--$sql .= $delimiter . $element->sql(); 
--$sql .= $delimiter . $element->retrieve();

And now for Tea

Now in my last post I left off with a bit of a code mess. Roles bleeding code into each other and my API in a dreadful state.

Well on thing I have seen before in non moose apps was use something called 'Class::Rebless' to rip the 'DA::LSDs' from my DA class but that is sort of an abuse of that code as it really is just for renaming name-space and I am not sure it will do what I want.

I had a look about the Moose::MOP class and found something called 'rebless_instance' which should take my original class, in this case DA with one or more LSD roles back to just a DA class.

Seems like a good idea but I think I would be opening myself up to a whole new slew of problems as I would only have a base object perhaps with it attributes in place and any other roles I may want removed.

So what to do??

Patreon and Perl

Once upon a time there was Gittip that became Gratipay that got shut down. Several Perl developers had account there and many got contributions through that platform.

A few days ago I've started to use Patreon that allows people to support each other on a monthly basis. (Or per creation.)

Searching for perl shows lots of unrelated entries. So it won't be easy to find other people contributing to Perl or writing about Perl.

This is my account: Gabor Szabo on Patreon.

Do you have a Patreon account? Post your link in the comment section so others can find you!

Never Role Twice!

Well did a little more playing about with my applied roles on my DA.pm and added in a bunch more testing to see if things where working for me.

First I wanted to see if using a role twice caused any ill effects so I added
 
ok(
    $address->retrieve( 'DBH', $result ) eq
      'SELECT  street, city, country FROM person  AS me',
    'SQL correct'
);

ok(
    $address->retrieve('MONGO') eq
      'db.person.find({},{ street: 1, city: 1, country: 1}',
    "Mongo Query correct"
);
to the end of my test and they both passed.

ok 9 - SQL correct
ok 10 - Mongo Query correct
ok 11 - SQL correct
ok 12 - Mongo Query correct

which is good I can flip between LSDs without much problem. Then I though that there could be some code bleed between the roles so in DA::LSD::Mongo I commented out the with statement
 
– with qw(DA::Roles::API)

++ #with qw(DA::Roles::API);
and re-ran my tests and unfortunately there was some code bleed as all my test passed!

(Update) Inline::F2003 - An ILSM for modern FORTRAN

An updated version, 1.01, of “matopmul” has been released on SourceForge. This version contains several fixes for the Inline::F2003 module. In particular, when a new FORTRAN compiler is specified through the FOR => “compiler” configuration option, Inline::F2003 recognises the change and recompiles the FORTRAN source with the new compiler.

Another change is that both Inline::F2003 and Inline::C can now load and execute at Perl’s compile-time. This further implies that the FORTRAN and C sources may both appear under the “__DATA__” section of the program.

use Inline F2003 => "DATA",
           ( FOR        => "gfortran",
             MAKEFILE   => "matopmul.mk",
             MAKEDIR    => File::Spec->curdir(),
             SRCLIST    => [ qw( ModMatrixOps.f03 ) ],
             PRINT_INFO => BOOL_T );

# Load and execute Inline::C just before end of compile-time
INIT {
   my @C_Config = ( MYEXTLIB    => $main::F2003Lib{PATHFN},
                    FORCE_BUILD => $main::F2003Lib{ISNEW},
                    CCFLAGSEX   => "-std=c99",
                    PRINT_INFO  => BOOL_T );

   Inline->import( C => "DATA", @C_Config );
   Inline->init();
}

In this source fragment, Inline::F2003 and Inline::C both receive the relevant source code from the “__DATA__” section of the program. Notice that Inline::C loads and executes inside an INIT block. This is necessary to ensure that the package variable %F2003Lib is exported before Inline::C is loaded. The detailed description is found in the “README.txt” file under the section “USING THE MODULE”.

The updated release is available at https://sourceforge.net/projects/inline-f2003/

Many Sides of Moose!!

In my last post I did managed to make a little code progress but I still had one major goal to accomplish and that is to make my Data Accessor smart enough that is would know what Driver to use form the connection passed in.

Well I am glad to say I am now able to do that with this test 02_base.t

ok 1 - use DA;
ok 2 - use DA::View;
ok 3 - use DA::Element;
ok 4 - Person is a View
ok 5 - Street is an Element
ok 6 - County is an Element
ok 7 - City is an Element
ok 8 - Address is a DA
ok 9 - SQL correct
ok 10 - Mongo Query correct

Moose is anything but inflexible and with it I was able to come up with a working prototype very quickly just by moving a few things about and reversing my roles.

So before I had DA.pm as a role. I change that to a class
 
– use Moose::Role;
++ use Moose;

–- requires '_execute';

Perl 5 Porters Mailing List Summary: December 6th-10th

Hey everyone,

Following is the p5p (Perl 5 Porters) mailing list summary for the past week.

Enjoy!

Just a Quick one!

So spent a little time working on my rough code from my last post and made up a working copy that you can have a look at here.

It was easy enough to get the SQL part working, after all I have been using such code my Data Accessor for many years now. It also took only a few minutes create a new DA::Mongo class with and an '_execute' function to come up with the query for Mongo.

With my limited test I get the correct query in SQL
 
SELECT street, city, country FROM person  AS me 
and Mongo as well
 
db.person.find({},{ street: 1, city: 1, country: 1}
So I have accomplished one of my goals; To have the same set of params to my API come up with the correct query in either SQL or Mongo.

Now this is all great and good but my code has started to diverge even with this very simple use case.

Code comes and Code goes but the App goes on!

Well how about some coding today?

Lets look at the first little bits from my last post the 'View' and 'Element' and I am going to focus in on using it with SQL in this post. So we have this;
 
{
    view => 'person',
    elements => [
        { name => 'name' },
        {
          name => 'street',
          view => 'address'
        },
        {
          name => 'country'
          view => 'address'
        }
        {
          name => 'city',
          view => 'address'
        }
    ],
}
Now the question, 'How am I going to express the above in the code of my Data Accessor?' Do I just have one attribute that stores the above in a hash-ref? Do I break them down into two attributes a string and an array-ref of hashes Like this;
 
has view => (
    is     => 'rw',
    isa    => 'Str',
);

has elements => (
    is      => 'rw',
    isa     => 'ArrayRef',
);

And the Plot Thickens

Yesterday I looked at maybe abstracting my API to make it common across a number of Data Accessor Derivers such as SQL and MongoDB and that got me thinking of how I am going to put all the pieces together?

Now what I would like is the end user to be able to something like this
 
my $address_da = SomeDa::Address()->new();
my $address_hash = {};
my $dbh = DBI->connect(“DBD::aything”,$uid,$ps);
 $address_da->retrieve($dbh,$address_hash,$options);
print $address->{steet}...

The present way I do things with Data Accessor, that 'SomeDA::Address' had to be an instance or extension of my DA::SQL class as shown here. Now do I have to do it this way? What if I made may Data Accessor smart enough that it could tell by the Connection you are passing what Driver to use so my SomeDA::Address could work with MongoDB as well. Like this

11-1.png

An interesting concept. Let me just model out the good old Person with Address first in RDBMS format

10-3.png

and now on mongo

10-2.png

Back in API again

Now onto another problem!

With present Perl version of my Data Accessor I had only a very small set of common methods, the CRUD ones and add_dynamic_criterion while the DA::SQL brought into the API many methods and attributes that are SQL specific.

  • Table
  • Fields
  • Group_by
  • Where
  • Having
  • ...

So if one of my evil plans is to make DA work across a number of differing DB platforms it would not be a good thing if for each of the accessor drivers would have its own API. Could also see the case where drivers for the same sort of DB say Mongo and Clusterpoint could have completely different APIs.

This would be no problem for the end user (remember her out on the pointy end writing up REST ful web services and desktop apps) as they would just have that nice little CRUD API to play with.

Why I wrote Keyword::DEVELOPMENT

I've had a few discussions with people about why I wrote Keyword::DEVELOPMENT, a useful, but simple module. In short, it lets you do this:

use Keyword::DEVELOPMENT;

# later ...

sub consume_item ( $self, $item_slug ) {
    DEVELOPMENT {
      # expensive and time-consuming debugging code here
    }
    my $inventory = $self->inventory;
    return $self->new_exchange(
        slug => 'consume',
        Steps(
            Inventory(  $inventory => contains => $item           ),
            Consumable( $self      => consume  => 'item_instance' ),
            Inventory(  $inventory => remove   => 'item_instance' ),
        ),
    )->attempt;
}

The expensive debug block? With Keyword::DEVELOPMENT, is simply fails to exist in production unless the PERL_KEYWORD_DEVELOPMENT environment variable has a true value. Thus, there is no performance overhead to instrumenting your code with complicated debugging logic (as I'm currently doing with Tau Station).

It's been pointed out to me by several people that I can accomplish the above in regular Perl with constant folding. I'll explain what that means and why I prefer the keyword route.

Nominate Perl heroes for the 2017 White Camel Awards

We're looking for nominations for the 2017 White Camel Awards that recognize significant non-technical achievement in Perl and its community. Each year we recognize work in the broad categories of community, advocacy, and user groups. These people keep the Perl community going and deserve to be recognized!

White baby camel

To nominate someone, you can send me a name and your reasoning through any means you like. Reply here, post on Twitter (note @briandfoy_perl or use the #whitecamelaward tag so I'll find it), send me email, hire landscapers to write out the names in tulips then take an aerial photo you post to instagram, or something more creative. Note, however, that the method of nomination does not factor into our decision!

And the word for Today is Abstract

Well lets play with some code today.

So I spent a little time having a look at MooseX::AbstractMethod and at first glance it look promising as is suppose to allow on to create an Abstract Class. So having a little time I created a little test code and of course a test file.

The code is simple parent Abstract class that has one sub and one required or abstract sub and then a child class that extends that parent but does not have the required sub so it should fail. This give me a simple four test plan;

  1. use the extended child class
  2. fail to instantiate the child class
  3. use the abstract class
  4. fail to instantiate the abstract class

So in my first run with MooseX::AbstractMethod I get

ok 1 - use DA_AM::Memory;
ok 2 - DA_AM::Memory dies requires _execute sub
ok 3 - use DA_AM;
ok 4 - Directly opened DA

Perl 5 Porters Mailing List Summary: November 21st - December 5th

Hey everyone,

Following is the p5p (Perl 5 Porters) mailing list summary for the past two weeks.

Enjoy!

Pretty Patterns All in a Row

Now that I have things mostly sorted out let's actually do some code or at least some pseudo-code on how I going to make it work.

I could go the pure Perl route and do the same sort of thing DBI does, an interface then drivers under it following this design pattern

pic1.png

I have cloned out and customized the DBI code and pattern in other applications and it really works well when you want the common glue on-top approach.

One thing I want to avoid is API deviation or sub bloat as I like to call it. It is an all to common occurrence with this design pattern. I am guilty of it myself when I added Scrollable Cursors into DBD::Oracle. Nothing in the DBI spec about these and I recall a little note from Tim asking to explain why I didn't create a generic DBI version before I added into DBD::Oracle.

Did I Forget Something??

My little API exercise in my last post I noticed that I may be missing an important part of the puzzle and that is some sort of generic connector function.

The present perl code DA.pm does have this:

 
sub _connect {
   my $self = shift;
   return $self->_dbh()
      if ($self->_dbh());
   my $dbh;
   if ($self->cache_connection()){
      $dbh = DBI->connect_cached($self->data_source,$self->username,$self->password,$self->connect_attr);
   }
   else {
      $dbh = DBI->connect($self->data_source,$self->username,$self->password,$self->connect_attr);
   }
   $self->_dbh($dbh);
   return $dbh;
}
Obviously it assumes that you would be using a DBI and returning a database handle. Not much use if you want to use Mongo as the data source. So putting my abstraction cap on I came up with this simple three param call
 
  $DA->connect({artibute1=>x,...},$user_name, $password) ;
which will cover off 99.765% of data sources.

London Perl Workshop 2017 - Talks Review

About a week ago, I published London Perl Workshop 2017 - Report. In the previous blog, I didn't mention anything about the talks I attended. So this blog would focus more on that. First sorry for late review, no excuse is good enough.

About blogs.perl.org

blogs.perl.org is a common blogging platform for the Perl community. Written in Perl and offering the modern features you’ve come to expect in blog platforms, the site is hosted by Dave Cross and Aaron Crane, with a design donated by Six Apart, Ltd.