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 func‐
19       tionality.
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 real‐
24       ization may boost start-up: the realization of objects is triggered by
25       the use, so spread over time.
26

METHODS

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

DETAILS

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

SEE ALSO

396       This module is part of Object-Realize-Later distribution version 0.16,
397       built on March 25, 2007. Website: http://perl.overmeer.net/orl/
398

LICENSE

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