Google
 
   
Login
Username:

Password:


Lost Password?

Register now!
Search
Main Menu
top books
Polls
What do you think about php-deluxe.net?
Excellent!
Cool
Hmm..not bad
What the hell is this?
encyclopedia
recommendation
compare webbrowser
Freenet DSL
Who's Online
9 user(s) are online (7 user(s) are browsing encyclopedia)

Members: 0
Guests: 9

more...
browser tip
Unix Befehle
manual of unix befehle
recommendation!
Sponsored
partner

Extensibility pattern

In computer programming, the extensibility pattern is a design pattern (computer science) that provides a framework for straightforward addition of functionality to a system at a later date.

Extensibility is often desired when an application must be able to support new features, such as networking protocols or file formats, that do not yet exist. This requires the Application software to supply a framework for the general problem without concern for the specifics of details.

=Frameworks=

A framework uses other Module (programming). Normal modules have a fixed set of dependencies, and are only extended through Subclass (computer science), as per Inheritance (computer science). A framework may consist of several parts that must be inherited to be used much like several cases of Class (computer science)#Abstract and Concrete classes. It may also be passed Reference (computer science) to other Object (computer science), as would a Class (computer science) that is sets up a Model-view-controller. It may read names of classes from a configuration file or from the user, as in BeanPattern. Instead of Code (computer programming) being used by other code, it will use other code on the fly. It is on top of the food chain instead of the bottom.

=Configuration Files as Extensions=

A ConfigFile may be enough to customize the module for reasonable needs. It may also specify modules by name to be created and employed in a framework.

# the config.pl file defines @listeners to contain a list of class names # that should receive notices from an EventListener broadcaster, # referenced by $broadcaster. require config.pl ; foreach my $listener (@listeners) { require $listener; my $list_inst = $listener->new(); $broadcaster->add_listener($list_inst); }

See for the plugin would need to ask the user where the //config.pl// is, and use the ConfigFile idiom to update it.

=Extending Through Scripting=

A major complaint against Graphical user interfaces is that they make it difficult to Scripting language repetitive tasks. Command line interfaces are difficult for most humans to work with. Neither give rich access to the application programming interface (API) of a program. A well-designed program is a few lines of Perl in the main program that use a number of modules — see Creating CPAN Modules. This makes it easier to reuse the program logic in other programs. Complex programs that build upon existing parts benefit from this, without question. How about the other case — a small script meant to automate some task This requires that the script have knowledge about the structure of the application — it must know how to assemble the modules, initialize them, and so on. It is forced to work with aspects of the API that it almost certainly is not concerned with. It must itself be the framework.

This is a kind of abstraction inversion — where something abstract is graphed onto something concrete, or something simple is grafted onto the top of something complex.

It would make more sense in this case for the application to implement a sort of visitor pattern, and allow itself to be passed whole, already assembled, to another spat of code that knows how to perform specific operations on it. This lends itself to the sequence nature of the script: the user-defined extention could be a series of simple calls: package UserExtention1; # we are expected to have a run_macro method sub run_macro { my $this = shift; my $app = shift; $app->place_cursor(0, 0); $app->set_color( white ); $app->draw_circle(radius=>1); $app->set_color( red ); $app->draw_circle(radius=>2); # and so on... make a little bull s eye return 1; }

The main application could prompt the user for a module to Load (computing), or load all of the modules in a plugins directory, then make them available as Menu (computing) items in an extentions menu. When one of the extentions are select from the menu, a reference to the application — or a facade pattern providing an Network interface to it — is passed to the run_macro() Method (computer science) of an Object (computer science) of that Software package.

Many applications will have users that want to do simple automation without being bothered to learn even a little Perl (horrible but true!). Some applications (like Mathematica, for instance) will provide functionality that does not cleanly map to Perl. In this case, you would want to be able to parse expressions and manipulate them. In these cases, a Domain-specific programming language may be just the thing.

A Little Language is a small programming language, created specifically for the task at hand. It can be similar to other languages. Having something clean and simple specifically targeted at the problem can be better solution than throwing an overpowered language at it. Just by neglecting unneeded features, user confusion is reduced.

place_cursor(0, 0) set_color(white) draw_circle(radius=1) set_color(red) draw_circle(radius=2)

A few options exist: we can compile this directly to Perl without performance loss), or we can munge this into Perl and ||eval|| it. Let us turn it into Perl.

# read in the users program my $input = join , ; # 0 if we re expecting a function name, 1 if we re expecting an argument, # 2 if we re expecting a comma to separate arguments my $state = 0; # perl code we re creating my $perl = package UserExtention1; sub run_macros { my $this = shift; my $app = shift; ; while(1) { # function call name if($state == 0 && $input =~ m{Gs*(w+)s*(}cgs) { $perl .= $app-> . $1 . ( ; $state = 1; # a=b style parameter } elsif($state == 1 && $input =~ m{Gs*(w+)s*=s*([w0-9]+)}cgs) { $perl .= qq{$1=> $2 }; $state = 2; # simple parameter } elsif($state == 1 && $input =~ m{Gs*([w0-9]+)}cgs) { $perl .= qq{ $1 }; $state = 2; # comma to separate parameters } elsif($state == 2 && $input =~ m{Gs*,}cgs) { $perl .= , ; $state = 1; # end of parameter list } elsif(($state == 1 || $state == 2) && $input =~ m{Gs*)}cgs) { $perl .= ); ; $state = 0; # syntax error or end of input } else { return 1 unless $input =~ m{G.}cgs; print operation name expected if $state == 0; print parameter expected if $state == 1; print comma or end of parameter list expected if $state == 2; return 0; } } $perl .= qq< return 1; } >; eval $perl; if($@) { # display diagnostic information to user }

We re using the G regex metacharacter that matches where the last Scope (programming) regex on that String (computer science) left off. That let us take off several small bites from the string rather than having to do it all in one big bite. The Flag (computing) on the end of the regex are:

  • g - global - needed for the G token to work
  • c - not sure, but it makes g work
  • s - substring - treat the entire string as one string. Newlines become regular characters and match whitespace.
  • Out of context, the string xyzzy could be either a name and an opening parenthesis, either a hash style parameter or a single, lone parameter, or else a close parenthesis would be valid. We are not even looking for the start of another function [though perhaps we should be. If changed, this in our code, it would allow us to nest function calls inside of each other. We would have to track our level of nesting if we wanted to report errors if there were too many or too few right-parenthesis. Exercise left for the reader.].

    After a parameter, we are looking for either the close parenthesis or another parameter.

    Every time we match something, we append a Perl-ized version of exactly the same thing onto $perl. All of this is wrapped in a package and method Declaration#Computer science. Finally, $perl is evaluated. The result of evaluating should be to make this new package available to our code, ready to be called.

    =Beans as Extentions=

    =Hacks as Extentions=

    When a base application, or shared code base, is Custom software in different directions for different clients, heavy use should be made of Template method patterns and Abstract factory pattern, localizing client-specific code into a module or tree of modules under a client-specific Namespace, rather than where it belongs .

    =References=

  • The article is originally from Perl Design Patterns Book.