++ed by:
1 non-PAUSE user
Author image Alexandr Evstigneev

NAME

Class::Accessor::Lazy - class accessors generation with lazy accessors and fast mode support.

VERSION

Version 1.003

SYNOPSIS

    package Foo;
    use base qw(Class::Accessor::Lazy);

    Foo->follow_best_practice->fast_accessors;

    Foo->mk_accessors(qw(name role salary))
        ->mk_lazy_accessors(qw(work_history));

    ...

    sub _lazy_init_work_history
    {
    ... resourseful history fething from database
    }
    
    # Meanwhile, in a nearby piece of code!
    # Class::Accessor::Lazy provides new().
    
    my $foo = Foo->new({ name => "Marty", role => "JAPH" });

    my $job = $foo->get_role;  # gets $foo->{role}
    $foo->set_salary(400000);  # sets $foo->{salary} = 400000 # I wish

    my $history = $foo->get_work_history;   # invokes _lazy_init_work_history
    
    .... some code
    
    some_function($foo->get_work_history);  # using data, read on first access
    

DESCRIPTION

This module allowes you to create accessors and mutators for your class, using one of the modules: Class::Accessor or Class::Accessor::Fast, but, in addition, it allowes you to create lazy accessors.

You may create mix accessors in your module, use Fast and regular ones like this:

    package Foo;
    use base qw(Class::Accessor::Lazy);

    Foo->follow_best_practice;

    Foo->mk_accessors(slow_accessor);

    Foo->fast_accessors;

    Foo->mk_accessors(fast_accessor);

    # or even
    
    Foo->follow_best_practice
        ->mk_accessors(slow_accessor)
        ->fast_accessors
        ->mk_accessors(fast_accessor);
  

Main documentation may be found on Class::Accessor and Class::Accessor::Fast pages.

The main extension of this module is possibility to make lazy properties, which will be inited on first get operation (if there was no write before).

Such methods are useful for database representation classes, where related data may not be read at all and there is no need to fetch it from database.

For example, there are Shop class and Employee class. Each Shop has property employees, which contains a reference to Employee objects list. But, you could fetch Shop object from database just to check income property and no don't need information about employees at all. In this case, reading employees list and creating list of Employee objects makes absolutely no sense.

But, if you want to get access to them, they should be read from database. And here are lazy properties comes:

    package Shop;
    use base 'Class::Accessor::Lazy';
    
    Shop->follow_best_practice              # use set/get for accessors/mutators
        ->fast_accessors                    # use Class::Acessor::Fast algorithm
        ->mk_accessors('income')            # regular property
        ->mk_lazy_accessors('employees');   # lazy property
        
    ...
        
    sub _lazy_init_employees
    {
        # here we are reading employees from database and saving them in 
        # property directly or using mutator set_employees
    }

On first get_employees invocation, method Shop::_lazy_init_employees will be invoked automatically, to allow your class to read related data from database, for example, and store it in object.

IMPORTANT: every lazy property of the class MUST have related init method. The name of such method is _lazy_init_{property name}.

NEW METHODS

There are couple of new methods in addition to Class::Accessors ones. Also, class methods now returns $self and you may use chain calls.

fast_acessors

Enables using Class::Accessor::Fast accessors generators.

original_acessors

Enables using Class::Accessor accessors generators.

mk_lazy_accessors

Same as mk_accessors, but creating lazy ones.

mk_lazy_ro_accessors

Same as mk_ro_accessors, but creating lazy ones.

BENCHMARKING

 Accessors benchmark:
 Benchmark: timing 20000000 iterations of Acessor, AcessorF, Direct, Lazy, LazyF...
   Acessor: 12 wallclock secs (11.34 usr +  0.00 sys = 11.34 CPU) @ 1763512.92/s (n=20000000)
  AcessorF:  6 wallclock secs ( 5.71 usr +  0.00 sys =  5.71 CPU) @ 3502626.97/s (n=20000000)
    Direct:  1 wallclock secs ( 0.78 usr +  0.00 sys =  0.78 CPU) @ 25641025.64/s (n=20000000)
      Lazy: 14 wallclock secs (13.85 usr +  0.00 sys = 13.85 CPU) @ 1443730.60/s (n=20000000)
     LazyF:  9 wallclock secs ( 8.71 usr +  0.00 sys =  8.71 CPU) @ 2297530.16/s (n=20000000)
     
 Mutators benchmark: 
 Benchmark: timing 20000000 iterations of Acessor, AcessorF, Direct, Lazy, LazyF...
   Acessor: 16 wallclock secs (15.26 usr +  0.00 sys = 15.26 CPU) @ 1310959.62/s (n=20000000)
  AcessorF:  8 wallclock secs ( 7.91 usr +  0.00 sys =  7.91 CPU) @ 2528764.70/s (n=20000000)
    Direct:  2 wallclock secs ( 1.50 usr +  0.00 sys =  1.50 CPU) @ 13351134.85/s (n=20000000)
      Lazy: 19 wallclock secs (18.83 usr +  0.00 sys = 18.83 CPU) @ 1062191.30/s (n=20000000)
     LazyF:  9 wallclock secs (10.53 usr +  0.00 sys = 10.53 CPU) @ 1899335.23/s (n=20000000)
     

Direct means direct access to the object property, and F suffix means using fast_accessors.

BUGS AND IMPROVEMENTS

If you found any bug and/or want to make some improvement, feel free to participate in the project on GitHub: https://github.com/hurricup/Class-Accessor-Lazy

LICENSE

This module is published under the terms of the MIT license, which basically means "Do with it whatever you want". For more information, see the LICENSE file that should be enclosed with this distributions. A copy of the license is (at the time of writing) also available at http://www.opensource.org/licenses/mit-license.php.

SEE ALSO

AUTHOR

Copyright (C) 2014 by Alexandr Evstigneev (hurricup@evstigneev.com)