/[cvs]/nfo/perl/libs/DesignPattern/Bridge.pm
ViewVC logotype

Contents of /nfo/perl/libs/DesignPattern/Bridge.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (show annotations)
Tue May 13 08:39:22 2003 UTC (21 years ago) by joko
Branch: MAIN
Changes since 1.11: +186 -14 lines
autocalling constructor after instantiation
added pod documentation

1 ## --------------------------------------------------------------------------------
2 ## $Id: Bridge.pm,v 1.11 2003/02/21 08:38:21 joko Exp $
3 ## --------------------------------------------------------------------------------
4 ## $Log: Bridge.pm,v $
5 ## Revision 1.11 2003/02/21 08:38:21 joko
6 ## + additional checks
7 ## + raising exceptions
8 ##
9 ## Revision 1.10 2003/02/20 20:50:32 joko
10 ## + small exception handling: now inheriting from little Exception object
11 ##
12 ## Revision 1.9 2003/02/18 18:35:30 joko
13 ## + encapsulated/abstracted some more functionality: sub load_single
14 ##
15 ## Revision 1.8 2003/02/14 14:20:05 joko
16 ## + modified mixin behaviour
17 ##
18 ## Revision 1.7 2003/02/11 10:34:19 joko
19 ## + loaded module may now lack 'mixin::with' declaration
20 ## + this gets us the possibility to load modules from any perl namespace
21 ## + enabled this mechanism
22 ##
23 ## Revision 1.6 2003/02/09 16:22:51 joko
24 ## + pseudo constructor mechanism via options
25 ##
26 ## Revision 1.5 2003/01/31 01:19:50 root
27 ## + fixed: doesn't need Log::Dispatch any more, but uses it if available
28 ##
29 ## Revision 1.4 2003/01/20 16:55:15 joko
30 ## + sub mixinPackage
31 ## + sub include
32 ##
33 ## Revision 1.3 2002/12/16 19:57:12 joko
34 ## + sub unload
35 ##
36 ## Revision 1.2 2002/12/15 02:06:15 joko
37 ## + feature to be able to specify module in non-perl-style when loading plugins: e.g. $process->load('Setup/Storage')
38 ##
39 ## Revision 1.1 2002/12/13 21:46:29 joko
40 ## + initial check-in
41 ##
42 ## --------------------------------------------------------------------------------
43
44
45 package DesignPattern::Bridge;
46
47 use strict;
48 use warnings;
49
50 use base qw(
51 DesignPattern::Object
52 DesignPattern::Exception
53 );
54
55
56 use Data::Dumper;
57
58 =pod
59
60 =head1 NAME
61
62 DesignPattern::Bridge
63
64
65 =head1 DESCRIPTION
66
67 This acts as a generic backplane for plugins using "Mix-in inheritance".
68
69
70 =head2 BACKGROUND
71
72 Mix-in inheritance
73 Please visit [http://citeseer.nj.nec.com/bracha90mixinbased.html].
74
75 [...]
76 Abstract: The diverse inheritance mechanisms provided by Smalltalk, Beta,
77 and CLOS are interpreted as different uses of a single underlying construct.
78 Smalltalk and Beta differ primarily in the direction of class hierarchy growth.
79 These inheritance mechanisms are subsumed in a new inheritance model
80 based on composition of mixins, or abstract subclasses. This form of
81 inheritance can also encode a CLOS multiple-inheritance hierarchy, although
82 changes to the encoded hierarchy that would violate... (Update)
83 [...]
84
85 ...level, and can naturally span component boundaries. Jiazzi supports
86 the composition of class extending components; e.g. mixins [1]. Mixins
87 and cyclic component linking can be combined into an open class pattern,
88 which allows independent features that cross cut class...
89
90 =head3 History of "mixins"
91
92 =head4 G. Bracha, W. Cook. Mixin-based inheritance.
93
94 G. Bracha and W. Cook, "Mixin-Based Inheritance", ECOOP/OOPSLA 1990, 303-311.
95 G. Bracha, W. Cook. Mixin-based inheritance. In OOPSLA/ECOOP '90 Conference Proceedings. ACM SIGPLAN Notices 25, 10 (Oct. 1990).
96
97 @inproceedings{ bracha90mixinbased,
98 author = "Gilad Bracha and William Cook",
99 title = "Mixin-Based Inheritance",
100 booktitle = "Proceedings of the Conference on Object-Oriented Programming: Systems, Languages, and Applications / Proceedings of the European Conference on Object-Oriented Programming",
101 publisher = "ACM Press",
102 address = "Ottawa, Canada",
103 editor = "Norman Meyrowitz",
104 pages = "303--311",
105 year = "1990",
106 url = "citeseer.nj.nec.com/bracha90mixinbased.html" }
107
108 =head4 D. Duggan and C. Sourelis. Mixin modules.
109
110 http://users.hol.gr/~csourelis/thesis.html
111
112 @misc{ duggan96mixin,
113 author = "D. Duggan and C. Sourelis",
114 title = "Mixin modules",
115 text = "D. Duggan and C. Sourelis. Mixin modules. In Intl. Conf. on Functional
116 Programming, Philadelphia, May 1996. ACM Press.",
117 year = "1996",
118 url = "citeseer.nj.nec.com/sourelis95mixin.html" }
119
120 =head4 Google on your own:
121
122 http://www.google.com/search?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&q=mix-in+inheritance
123 http://www.google.com/search?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&q=Moo86+mixins
124
125
126 =head3 Discussion
127
128 http://citeseer.nj.nec.com/context/6117/0
129
130 =head2 References
131
132 The Jigsaw Framework:
133 http://citeseer.nj.nec.com/bracha92programming.html
134
135 http://citeseer.nj.nec.com/114070.html
136 http://citeseer.nj.nec.com/445396.html
137 http://citeseer.nj.nec.com/tichelaar97coordination.html
138 http://citeseer.nj.nec.com/meijler98beyond.html
139
140 http://citeseer.nj.nec.com/89291.html
141 http://citeseer.nj.nec.com/sousa91runtime.html
142 http://citeseer.nj.nec.com/banavar95application.html
143 http://citeseer.nj.nec.com/sourelis95mixin.html
144 http://citeseer.nj.nec.com/hirschowitz02mixin.html
145
146 Java: http://csis.pace.edu/~bergin/patterns/multipleinheritance.html
147 C++: http://www.oofile.com.au/oofdoc/samples/ooftst19.htm
148
149 =head3 Related
150
151 http://citeseer.nj.nec.com/nrelated/6117/23339
152
153
154 =head3 Traits - Composable Units of Behavior
155
156 via: http://citeseer.nj.nec.com/context/22076/0
157
158 Traits: Composable Units of Behavior - Nathanael Schrli Stphane (Correct)
159 ....is not expressive enough to factor out common features (i.e. instance
160 variables and methods) shared by classes in a complex hierarchy. As a
161 consequence, language designers have proposed various forms of multiple
162 inheritance [Mey88] Kee89] Str86] as well as other mechanisms, such as
163 mixins [Moo86] BC90] FKF98] that allow classes to be composed incrementally
164 from sets of features. Despite the passage of nearly twenty years, neither
165 multiple inheritance nor mixins have achieved wide acceptance [Tai96]
166 Summarizing Alan Snyder s contribution to the inheritance panel discussion
167 at OOPSLA ....
168
169 ....complete. But as a unit of reuse, a class should be small. These properties
170 often conflict. Furthermore, the role of classes as instance generators requires
171 that each class have a unique place in the class hierarchy, whereas units of
172 reuse should be applicable at arbitrary places. Moon s Flavors [Moo86] were
173 an early attempt to address this problem: Flavors are small, not necessarily
174 complete, and they can be mixed in at arbitrary places in the class hierarchy.
175 More sophisticated notions of mixins were subsequently developed by Bracha
176 and Cook [BC90] and Flatt, Krishnamurthi and Felleisen ....
177
178 David A. Moon. Object-oriented programming with flavors. In Proceedings
179 OOPSLA '86, ACM SIGPLAN Notices, pages 1--8, November 1986.
180 Published as Proceedings OOPSLA '86, ACM SIGPLAN Notices, volume 21, number 11.
181
182
183 from: http://citeseer.nj.nec.com/566972.html
184
185 Abstract: Inheritance is the fundamental reuse mechanism in object-oriented
186 programming languages; its most prominent variants are single inheritance,
187 multiple inheritance, and mixin inheritance. In the first part of this paper,
188 we identify and illustrate the conceptual and practical reusability problems
189 that arise with these forms of inheritance. We then present a simple
190 compositional model for structuring object-oriented programs, which we call traits.
191 Traits are essentially groups of methods... (Update)
192
193
194 =head3 Hybrid - A Language for Programming with Active Objects
195
196 http://citeseer.nj.nec.com/561934.html
197 http://citeseer.nj.nec.com/nierstrasz92tour.html
198 http://www.iam.unibe.ch/~scg/Archive/NFS/cao.html
199
200 =head3 Active Objects and Oberon
201
202
203 =head2 DETAILS
204
205 This attempts to be a runtime wrapper around mixin.pm, written by Michael G Schwern
206 and available on CPAN.
207 Please visit:
208 http://magnonel.guild.net/~schwern/talks/Design_Patterns/full_slides/slide036.html
209
210
211 =head2 NOTES
212
213 ## ======== object inheritance ========
214
215 2002-12:
216 TODO / REFACTORING PROPOSAL
217 leading from Data::Storage to code abstracted out into this module - DesignPattern::Bridge
218 - this is no inheritance and it doesn't have to be
219 - implement this module as a bridge to its sub-modules
220 - use the BridgePattern (http://c2.com/cgi/wiki?BridgePattern)
221 Using patterns was already successfully done with Data::Storage::Handler
222 by implementing the AdapterPattern (http://c2.com/cgi/wiki?AdapterPattern)
223 with Perl's AUTOLOAD-mechanism
224 - try to use Perl's "tie" command to implement this functionality here instead of using AUTOLOAD!
225 - sub getChildNodes
226 - sub run
227
228 2003-02-11, joko: Does this have anything in parallel with CPAN's Class::Inner? No!
229
230
231 =head1 TODO
232
233 o use Class::Loader
234 o rename to mixin::runtime?
235
236
237 =cut
238
239
240 # get logger instance
241 my $logger = eval { Log::Dispatch::Config->instance; };
242
243 my $meta;
244
245 ## ======== object constructor ========
246 sub new {
247 my $invocant = shift;
248 my $class = ref($invocant) || $invocant;
249 my @args = ();
250 @_ && (@args = @_);
251 $logger->debug( __PACKAGE__ . "->new(@args)" ) if $logger;
252 my $self = { @_ };
253
254 # trace
255 #print "class: $class", "\n";
256
257 # create instance
258 bless $self, $class;
259
260 # NEW: 2003-04-16
261 $self->constructor() if $self->can('constructor');
262
263 return $self;
264 }
265
266
267 ## ======== method overrider ========
268 sub AUTOLOAD2 {
269
270 my $self = shift;
271 our $AUTOLOAD;
272
273 ##print "AUTOLOAD\n";
274
275 my $method = $AUTOLOAD;
276 $method =~ s/^.*:://;
277
278 $logger->debug( __PACKAGE__ . "->" . $method . "(@_)" . " (AUTOLOAD called, not dispatched)" ) if $logger;
279
280 ## ->DESTROY would - if not declared - trigger an AUTOLOAD also
281 return if $method =~ m/::DESTROY$/;
282
283 ## if ($self->_filter_AUTOLOAD($method)) {
284 ## $self->_accessStorage();
285 ## $self->{STORAGEHANDLE}->$method(@_);
286 ## }
287
288 }
289
290 sub _getPluginPackage {
291 my $self = shift;
292 my $modulename_load = shift;
293
294 # substitute slashes through double double-colons to load modules perl-style
295 $modulename_load =~ s/\//::/g;
296
297 # build full package name
298 my $self_classname = ref $self;
299 # name
300 my $package = $modulename_load;
301
302 # if package is absolute, cut away prefix ('/' or '::')
303 if ($package !~ s/^:://) {
304 # else: prefix with base classname if above name is relative (lacks of '/' or '::')
305 $package = $self_classname . '::' . $package
306 }
307
308 return $package;
309 }
310
311 sub load {
312
313 my $self = shift;
314 my $modulename = shift;
315 my $options = shift;
316
317 if (ref $modulename eq 'ARRAY') {
318 foreach (@$modulename) {
319 $self->load_single($_, $options);
320 }
321 } else {
322 $self->load_single($modulename, $options);
323 }
324
325 }
326
327 sub load_single {
328
329 my $self = shift;
330 my $modulename_load = shift;
331
332 my $options = shift;
333
334 my $self_modulename = ref $self;
335 my $package = $self->_getPluginPackage($modulename_load);
336
337 if ($meta->{loaded}->{$package}) {
338 return 1;
339 }
340
341 #$logger->info( __PACKAGE__ . "->load: $package" ) if $logger;
342 #$logger->info( __PACKAGE__ . "->load: $self_modulename" ) if $logger;
343 $logger->debug( $self_modulename . "->load: $package\t[via " . __PACKAGE__ . "]" ) if $logger;
344
345 # this is the module testing phase - use mixin doesn't seem to propagate errors by default
346 eval("use $package;");
347 $self->checkExceptions();
348
349 =pod
350 if ($@) {
351 $meta->{loaded}->{$package} = 0;
352 # include caller information
353 my @caller = caller;
354 my $caller_msg = $caller[1] . ':' . $caller[2];
355 my $msg = __PACKAGE__ . "->load: $@ ($caller_msg)";
356 if ($logger) {
357 $logger->error($msg);
358 } else {
359 print $msg, "\n";
360 }
361 }
362 =cut
363
364 #print "ref-1: ", ref $self, "\n";
365 #print "ref-2: ", ref $self::SUPER, "\n";
366
367 # V1:
368 #bless $self, $package;
369
370 # V2:
371 $self->mixinPackage($package);
372
373 if (my $method = $options->{method}) {
374 $self->$method();
375 }
376
377 return 1;
378
379 }
380
381 sub mixinPackage {
382 my $self = shift;
383 my $package = shift;
384
385 # switch into foreign package and prepare for mixin
386 $self->mixin_prepare($package);
387
388 # switch into local package (scope which uses DesignPattern::Bridge) and mixin plugin-module
389 $self->mixin_do($package);
390
391 }
392
393 # TODO: maybe refactor to DesignPattern::Object? what about the '$logger'?
394 sub mixin_prepare {
395 my $self = shift;
396 my $package = shift;
397 my $self_classname = ref $self;
398 eval("package $package; use mixin::with '$self_classname';");
399
400 # FIXME: --- this is redundant ---
401 if ($@) {
402 $meta->{loaded}->{$package} = 0;
403 $logger->error( __PACKAGE__ . "->load: $@" ) if $logger;
404 } else {
405 $meta->{loaded}->{$package} = 1;
406 }
407 # FIXME: --- this is redundant ---
408
409 }
410
411 sub mixin_do {
412 my $self = shift;
413 my $package = shift;
414 # switch into foreign package and mixin plugin-module
415 my $self_classname = ref $self;
416 eval("package $self_classname; use mixin '$package';");
417 #eval("use mixin_all '$package';");
418
419 # FIXME: --- this is redundant ---
420 if ($@) {
421 $meta->{loaded}->{$package} = 0;
422 $logger->error( __PACKAGE__ . "->load: $@" ) if $logger;
423 } else {
424 $meta->{loaded}->{$package} = 1;
425 }
426 # FIXME: --- this is redundant ---
427
428 }
429
430 sub unload {
431
432 my $self = shift;
433 my $modulename_unload = shift;
434
435 my $package = $self->_getPluginPackage($modulename_unload);
436
437 if ($meta->{loaded}->{$package}) {
438 $meta->{loaded}->{$package} = 0;
439 my $where = __PACKAGE__ . ':' . __LINE__;
440 $logger->debug( __PACKAGE__ . "->unload: FIXME: DESTROY object is not implemented at '$where'." ) if $logger;
441 }
442
443 }
444
445
446 sub boot {
447 my $self = shift;
448 $self->_abstract_function('boot');
449 }
450
451 sub include {
452 my $self = shift;
453 my $includefile = shift;
454 my $package = shift;
455
456 # pre-flight checks
457 if (!$includefile) {
458 $self->raiseException('Filename for inclusion was empty.');
459 return;
460 }
461
462 # go for it ...
463 eval("require '$includefile';");
464 # ... and handle errors afterwards catching every message from perl itself ...
465 return if $self->checkExceptions();
466
467 # ... otherwise continue assuming everything is fine
468 $self->mixinPackage($package) if $package;
469
470 }
471
472 1;
473 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed