1Object::Realize::Later(U3s)er Contributed Perl DocumentatOibojnect::Realize::Later(3)
2
3
4

NAME

6       Object::Realize::Later - Delayed creation of objects
7

SYNOPSIS

9        package MyLazyObject;
10
11        use Object::Realize::Later
12           becomes => 'MyRealObject',
13           realize => 'load';
14

DESCRIPTION

16       The "Object::Realize::Later" class helps with implementing transparent
17       on demand realization of object data.  This is related to the tricks on
18       autoloading of data, the lesser known cousin of autoloading of
19       functionality.
20
21       On demand realization is all about performance gain.  Why should you
22       spent costly time on realizing an object, when the data on the object
23       is never (or not yet) used?  In interactive programs, postponed
24       realization may boost start-up: the realization of objects is triggered
25       by the use, so spread over time.
26

METHODS

28   Construction
29       use(Object::Realize::Later OPTIONS)
30
31           When you invoke ("use") the "Object::Realize::Later" package, it
32           will add a set of methods to your package (see section "Added to
33           YOUR class").
34
35            Option            --Default
36            becomes             <required>
37            believe_caller      <false>
38            realize             <required>
39            source_module       <becomes>
40            warn_realization    <false>
41            warn_realize_again  <false>
42
43           . becomes => CLASS
44
45               Which type will this object become after realization.
46
47           . believe_caller => BOOLEAN
48
49               When a method is called on the un-realized object, the AUTOLOAD
50               checks whether this resolves the need.  If not, the realization
51               is not done.  However, when realization may result in an object
52               that extends the functionality of the class specified with
53               "becomes", this check must be disabled.  In that case, specify
54               true for this option.
55
56           . realize => METHOD|CODE
57
58               How will transform.  If you specify a CODE reference, then this
59               will be called with the lazy-object as first argument, and the
60               requested method as second.
61
62               After realization, you may still have your hands on the lazy
63               object on various places.  Be sure that your realization method
64               is coping with that, for instance by using Memoize.  See
65               examples below.
66
67           . source_module => CLASS
68
69               if the class (a package) is included in a file (module) with a
70               different name, then use this argument to specify the file
71               name. The name is expected to be the same as in the "require"
72               call which would load it.
73
74           . warn_realization => BOOLEAN
75
76               Print a warning message when the realization starts.  This is
77               for debugging purposes.
78
79           . warn_realize_again => BOOLEAN
80
81               When an object is realized, the original object -which
82               functioned as a stub- is reconstructed to work as proxy to the
83               realized object.  This option will issue a warning when that
84               proxy is used, which means that somewhere in your program there
85               is a variable still holding a reference to the stub.  This
86               latter is not problematic at all, although it slows-down each
87               method call.
88
89   Added to YOUR class
90       $obj->AUTOLOAD
91
92           When a method is called which is not available for the lazy object,
93           the AUTOLOAD is called.
94
95       $obj->can(METHOD)
96
97       Object::Realize::Later->can(METHOD)
98
99           Is the specified METHOD available for the lazy or the realized
100           version of this object?  It will return the reference to the code.
101
102           Example:
103
104              MyLazyObject->can('lazyWork')      # true
105              MyLazyObject->can('realWork')      # true
106
107              my $lazy = MyLazyObject->new;
108              $lazy->can('lazyWork');            # true
109              $lazy->can('realWork');            # true
110
111       $obj->forceRealize
112
113           You can force the load by calling this method on your object.  It
114           returns the realized object.
115
116       Object::Realize::Later->isa(CLASS)
117
118           Is this object a (sub-)class of the specified CLASS or can it
119           become a (sub-)class of CLASS.
120
121           Example:
122
123            MyLazyObject->isa('MyRealObject')      # true
124            MyLazyObject->isa('SuperClassOfLazy'); # true
125            MyLazyObject->isa('SuperClassOfReal'); # true
126
127            my $lazy = MyLazyObject->new;
128            $lazy->isa('MyRealObject');            # true
129            $lazy->isa('SuperClassOfLazy');        # true
130            $lazy->isa('SuperClassOfReal');        # true
131
132       $obj->willRealize
133
134           Returns which class will be the realized to follow-up this class.
135
136   Object::Realize::Later internals
137       The next methods are not exported to the class where the `use' took
138       place.  These methods implement the actual realization.
139
140       Object::Realize::Later->import(OPTIONS)
141
142           The OPTIONS used for "import" are the values after the class name
143           with "use".  So this routine implements the actual option parsing.
144           It generates code dynamically, which is then evaluated in the
145           callers name-space.
146
147       Object::Realize::Later->realizationOf(OBJECT [,REALIZED])
148
149           Returns the REALIZED version of OBJECT, optionally after setting it
150           first.  When the method returns "undef", the realization has not
151           yet taken place or the realized object has already been removed
152           again.
153
154       Object::Realize::Later->realize(OPTIONS)
155
156           This method is called when a "$object-"forceRealize()> takes place.
157           It checks whether the realization has been done already (is which
158           case the realized object is returned)
159

DETAILS

161   About lazy loading
162       There are two ways to implement lazy behaviour: you may choose to check
163       whether you have realized the data in each method which accesses the
164       data, or use the autoloading of data trick.
165
166       An implementation of the first solution is:
167
168        sub realize {
169            my $self = shift;
170            return $self unless $self->{_is_realized};
171
172            # read the data from file, or whatever
173            $self->{data} = ....;
174
175            $self->{_is_realized} = 1;
176            $self;
177        }
178
179        sub getData() {
180            my $self = shift;
181            return $self->realize->{data};
182        }
183
184       The above implementation is error-prone, where you can easily forget to
185       call realize().  The tests cannot cover all ordenings of method-calls
186       to detect the mistakes.
187
188       The second approach uses autoloading, and is supported by this package.
189       First we create a stub-object, which will be transformable into a
190       realized object later.  This transformation is triggered by AUTOLOAD.
191
192       This stub-object may contain some methods from the realized object, to
193       reduce the need for realization.  The stub will also contain some
194       information which is required for the creation of the real object.
195
196       "Object::Realize::Later" solves the inheritance problems (especially
197       the isa() and can() methods) and supplies the AUTOLOAD method.  Class
198       methods which are not defined in the stub object are forwarded as class
199       methods without realization.
200
201   Traps
202       Be aware of dangerous traps in the current implementation.  These
203       problems appear by having multiple references to the same delayed
204       object.  Depending on how the realization is implemented, terrible
205       things can happen.
206
207       The two versions of realization:
208
209       ·   by reblessing
210
211           This is the safe version.  The realized object is the same object
212           as the delayed one, but reblessed in a different package.  When
213           multiple references to the delayed object exists, they will all be
214           updated at the same, because the bless information is stored within
215           the refered variable.
216
217       ·   by new instance
218
219           This is the nicest way of realization, but also quite more
220           dangerous.  Consider this:
221
222            package Delayed;
223            use Object::Realize::Later
224                 becomes => 'Realized',
225                 realize => 'load';
226
227            sub new($)      {my($class,$v)=@_; bless {label=>$v}, $class}
228            sub setLabel($) {my $self = shift; $self->{label} = shift}
229            sub load()      {$_[0] = Realized->new($_[0]->{label}) }
230
231            package Realized;  # file Realized.pm or use use(source_module)
232            sub new($)      {my($class,$v)=@_; bless {label=>$v}, $class}
233            sub setLabel($) {my $self = shift; $self->{label} = shift}
234            sub getLabel()  {my $self = shift; $self->{label}}
235
236            package main;
237            my $original = Delayed->new('original');
238            my $copy     = $original;
239            print $original->getLabel;     # prints 'original'
240            print ref $original;           # prints 'Realized'
241            print ref $copy;               # prints 'Delayed'
242            $original->setLabel('changed');
243            print $original->getLabel;     # prints 'changed'
244            print $copy->getLabel;         # prints 'original'
245
246   Examples
247       Example 1
248
249       In the first example, we delay-load a message.  On the moment the
250       message is defined, we only take the location.  When the data of the
251       message is taken (header or body), the data is autoloaded.
252
253        package Mail::Message::Delayed;
254
255        use Object::Realize::Later
256          ( becomes => 'Mail::Message::Real'
257          , realize => 'loadMessage'
258          );
259
260        sub new($) {
261            my ($class, $file) = @_;
262            bless { filename => $file }, $class;
263        }
264
265        sub loadMessage() {
266            my $self = shift;
267            Mail::Message::Real->new($self->{filename});
268        }
269
270       In the main program:
271
272        package main;
273        use Mail::Message::Delayed;
274
275        my $msg    = Mail::Message::Delayed->new('/home/user/mh/1');
276        $msg->body->print;     # this will trigger autoload.
277
278       Example 2
279
280       Your realization may also be done by reblessing.  In that case to
281       change the type of your object into a different type which stores the
282       same information.  Is that right?  Are you sure?  For simple cases,
283       this may be possible:
284
285        package Alive;
286        use Object::Realize::Later
287             becomes => 'Dead',
288             realize => 'kill';
289
290        sub new()         {my $class = shift; bless {@_}, $class}
291        sub jump()        {print "Jump!\n"}
292        sub showAntlers() {print "Fight!\n"}
293        sub kill()        {bless(shift, 'Dead')}
294
295        package Dead;
296        sub takeAntlers() {...}
297
298       In the main program:
299
300        my $deer   = Alive->new(Animal => 'deer');
301        my $trophy = $deer->takeAntlers();
302
303       In this situation, the object (reference) is not changed but is
304       reblessed.  There is no danger that the un-realized version of the
305       object is kept somewhere: all variable which know about this partical
306       deer see the change.
307
308       Example 3
309
310       This module is especially usefull for larger projects, which there is a
311       need for speed or memory reduction. In this case, you may have an extra
312       overview on which objects have been realized (transformed), and which
313       not.  This example is taken from the MailBox modules:
314
315       The Mail::Box module tries to boost the access-time to a folder.  If
316       you only need the messages of the last day, why shall all be read?  So,
317       MailBox only creates an invertory of messages at first.  It takes the
318       headers of all messages, but leaves the body (content) of the message
319       in the file.
320
321       In MailBox' case, the Mail::Message-object has the choice between a
322       number of Mail::Message::Body's, one of which has only be prepared to
323       read the body when needed.  A code snippet:
324
325        package Mail::Message;
326        sub new($$)
327        {   my ($class, $head, $body) = @_;
328            my $self = bless {head => $head, body => $body}, $class;
329            $body->message($self);          # tell body about the message
330        }
331        sub head()     { shift->{head} }
332        sub body()     { shift->{body} }
333
334        sub loadBody()
335        {   my $self = shift;
336            my $body = $self->body;
337
338            # Catch re-invocations of the loading.  If anywhere was still
339            # a reference to the old (unrealized) body of this message, we
340            # return the new-one directly.
341            return $body unless $body->can('forceRealize');
342
343            # Load the body (change it to anything which really is of
344            # the promised type, or a sub-class of it.
345            my ($lines, $size) = .......;    # get the data
346            $self->{body} = Mail::Message::Body::Lines
347                                 ->new($lines, $size, $self);
348
349            # Return the realized object.
350            return $self->{body};
351        }
352
353        package Mail::Message::Body::Lines;
354        use base 'Mail::Message::Body';
355
356        sub new($$$)
357        {   my ($class, $lines, $size, $message) = @_;
358            bless { lines => $lines, size => $size
359                  , message => $message }, $class;
360        }
361        sub size()    { shift->{size} }
362        sub lines()   { shift->{lines} }
363        sub message() { shift->{message);
364
365        package Mail::Message::Body::Delayed;
366        use Object::Realize::Later
367            becomes => 'Mail::Message::Body',
368            realize => sub {shift->message->loadBody};
369
370        sub new($)
371        {   my ($class, $size) = @_;
372            bless {size => $size}, $class;
373        }
374        sub size() { shift->{size} }
375        sub message(;$)
376        {   my $self = shift;
377            @_ ? ($self->{message} = shift) : $self->{messages};
378        }
379
380        package main;
381        use Mail::Message;
382        use Mail::Message::Body::Delayed;
383
384        my $body    = Mail::Message::Body::Delayed->new(42);
385        my $message = Mail::Message->new($head, $body);
386
387        print $message->size;         # will not trigger realization!
388        print $message->can('lines'); # true, but no realization yet.
389        print $message->lines;        # realizes automatically.
390

SEE ALSO

392       This module is part of Object-Realize-Later distribution version 0.18,
393       built on June 08, 2007. Website: http://perl.overmeer.net/orl/
394

LICENSE

396       Copyrights 2001-2004,2007 by Mark Overmeer <perl@overmeer.net>. For
397       other contributors see Changes.
398
399       This program is free software; you can redistribute it and/or modify it
400       under the same terms as Perl itself.  See
401       http://www.perl.com/perl/misc/Artistic.html
402
403
404
405perl v5.12.0                      2007-06-08         Object::Realize::Later(3)
Impressum