File Coverage

blib/lib/Bread/Board.pm
Criterion Covered Total %
statement 125 125 100.0
branch 60 62 96.7
condition 11 12 91.6
subroutine 27 27 100.0
pod 11 11 100.0
total 234 237 98.7


line stmt bran cond sub pod time code
1             package Bread::Board;
2             our $AUTHORITY = 'cpan:STEVAN';
3             $Bread::Board::VERSION = '0.36';
4 53     53   7183426 use strict;
  53         690  
  53         2114  
5 53     53   377 use warnings;
  53         133  
  53         2051  
6 53     53   391 use Carp qw(confess);
  53         126  
  53         3694  
7 53     53   430 use Scalar::Util qw(blessed);
  53         122  
  53         3161  
8             # ABSTRACT: A solderless way to wire up your application components
9              
10 53     53   19611 use Bread::Board::Types;
  53         236  
  53         2704  
11 53     53   24285 use Bread::Board::ConstructorInjection;
  53         286  
  53         2647  
12 53     53   24757 use Bread::Board::SetterInjection;
  53         262  
  53         2507  
13 53     53   24666 use Bread::Board::BlockInjection;
  53         3974  
  53         2442  
14 53     53   24383 use Bread::Board::Literal;
  53         268  
  53         2590  
15 53     53   26378 use Bread::Board::Container;
  53         288  
  53         2603  
16 53     53   27020 use Bread::Board::Container::Parameterized;
  53         288  
  53         2545  
17 53     53   552 use Bread::Board::Dependency;
  53         147  
  53         1488  
18 53     53   23967 use Bread::Board::LifeCycle::Singleton;
  53         239  
  53         2597  
19 53     53   23639 use Bread::Board::Service::Inferred;
  53         279  
  53         2514  
20 53     53   25022 use Bread::Board::Service::Alias;
  53         321  
  53         3019  
21              
22 53     53   557 use Moose::Exporter 2.1200;
  53         1623  
  53         483  
23             Moose::Exporter->setup_import_methods(
24             as_is => [qw[
25             as
26             container
27             depends_on
28             service
29             alias
30             wire_names
31             include
32             typemap
33             infer
34             literal
35             ]],
36             );
37              
38 116     116 1 447868 sub as (&) { $_[0] }
39              
40             our $CC;
41             our $in_container;
42              
43             sub set_root_container {
44 5 100   5 1 2056 confess "Can't set the root container when we're already in a container"
45             if $in_container;
46 4         14 $CC = shift;
47             }
48              
49             sub container ($;$$) {
50 124     124 1 11292 my $name = shift;
51              
52 124         308 my $c;
53 124 100       619 if (blessed $name) {
54 15 100 100     291 confess 'an object used as a container must inherit from Bread::Board::Container or Bread::Board::Container::Parameterized'
55             unless $name->isa('Bread::Board::Container') || $name->isa('Bread::Board::Container::Parameterized');
56              
57 14 100       169 confess 'container($object, ...) is not supported for parameterized containers'
58             if scalar @_ > 1;
59              
60             # this is basically:
61             # container( A::Bread::Board::Container->new, ... )
62             # or someone using &container as a constructor
63 13         38 $c = $name;
64              
65             # if we're in the context of another container
66             # then we're a subcontainer of it
67 13 50       54 $CC->add_sub_container($c) if defined $CC;
68             }
69             else {
70 109         461 my $is_inheriting = $name =~ s/^\+//;
71 109 100 100     801 confess "Inheriting containers isn't possible outside of the context of a container"
72             if $is_inheriting && !defined $CC;
73              
74             # if we have more than 1 argument, then we are a parameterized
75             # container, so we need to act accordingly
76 108 100       434 if (scalar @_ > 1) {
77 11 100       215 confess 'Declaring container parameters when inheriting is not supported'
78             if $is_inheriting;
79              
80 10         23 my $param_names = shift;
81 10         424 $c = Bread::Board::Container::Parameterized->new({
82             name => $name,
83             allowed_parameter_names => $param_names,
84             });
85             }
86             else {
87 97 100       4201 $c = $is_inheriting
88             ? $CC->fetch($name)
89             : Bread::Board::Container->new({ name => $name });
90             }
91              
92             # if we're in the context of another container
93             # then we're a subcontainer of it, unless we're inheriting,
94             # in which case we already got a parent
95 106 100 100     843 $CC->add_sub_container($c) if !$is_inheriting && defined $CC;
96             }
97              
98 119         336 my $body = shift;
99             # if we have more arguments
100             # then they are likely a body
101             # and so we should execute it
102 119 100       458 if (defined $body) {
103 113         292 local $_ = $c;
104 113         281 local $CC = $c;
105 113         326 local $in_container = 1;
106 113         523 $body->($c);
107             }
108              
109 107         2776 return $c;
110             }
111              
112             sub include ($) {
113 6     6 1 9592 my $file = shift;
114 6 100       1439 if (my $ret = do $file) {
115 3         21 return $ret;
116             }
117             else {
118 3 100       378 confess "Couldn't compile $file: $@" if $@;
119 2 100       239 confess "Couldn't open $file for reading: $!" if $!;
120 1         250 confess "Unknown error when compiling $file "
121             . "(or $file doesn't return a true value)";
122             }
123             }
124              
125             sub service ($@) {
126 167     167 1 6928 my $name = shift;
127 167         350 my $s;
128              
129 167         514 my $is_inheriting = ($name =~ s/^\+//);
130              
131 167 100       856 if (scalar @_ == 1) {
    100          
132 56 100       472 confess "Service inheritance doesn't make sense for literal services"
133             if $is_inheriting;
134              
135 55         2126 $s = Bread::Board::Literal->new(name => $name, value => $_[0]);
136             }
137             elsif (scalar(@_) % 2 == 0) {
138 110         544 my %params = @_;
139              
140 110         346 my $class = $params{service_class};
141             $class ||= defined $params{service_type} ? "Bread::Board::$params{service_type}Injection"
142 110 100 66     1029 : exists $params{block} ? 'Bread::Board::BlockInjection'
    100          
143             : 'Bread::Board::ConstructorInjection';
144              
145 110 100       929 $class->does('Bread::Board::Service')
146             or confess "The service class must do the Bread::Board::Service role";
147              
148 109 100       63850 if ($is_inheriting) {
149 9 50       42 confess "Inheriting services isn't possible outside of the context of a container"
150             unless defined $CC;
151              
152 9 100       127 my $container = ($CC->isa('Bread::Board::Container::Parameterized') ? $CC->container : $CC);
153 9         53 my $prototype_service = $container->fetch($name);
154              
155 9 100       50 confess sprintf(
156             "Trying to inherit from service '%s', but found a %s",
157             $name, blessed $prototype_service,
158             ) unless $prototype_service->does('Bread::Board::Service');
159              
160 8         550 $s = $prototype_service->clone_and_inherit_params(
161             service_class => $class,
162             %params,
163             );
164             }
165             else {
166 100         4482 $s = $class->new(name => $name, %params);
167             }
168             }
169             else {
170 1         108 confess "A service is defined by a name and either a single value or hash of parameters; you have supplied neither";
171             }
172 158 100       5659 return $s unless defined $CC;
173 155         855 $CC->add_service($s);
174             }
175              
176             sub alias ($$@) {
177 24     24 1 576 my $name = shift;
178 24         50 my $path = shift;
179 24         57 my %params = @_;
180              
181 24         853 my $s = Bread::Board::Service::Alias->new(
182             name => $name,
183             aliased_from_path => $path,
184             %params,
185             );
186 24 100       72 return $s unless defined $CC;
187 23         82 $CC->add_service($s);
188             }
189              
190             sub typemap ($@) {
191 33     33 1 1794 my $type = shift;
192              
193 33 100       274 (scalar @_ == 1)
194             || confess "typemap takes a single argument";
195              
196 32         78 my $service;
197 32 100       171 if (blessed $_[0]) {
198 26 100       184 if ($_[0]->does('Bread::Board::Service')) {
    100          
199 1         72 $service = $_[0];
200             }
201             elsif ($_[0]->isa('Bread::Board::Service::Inferred')) {
202 24         4616 $service = $_[0]->infer_service( $type );
203             }
204             else {
205 1         296 confess $_[0] . " isn't a service";
206             }
207             }
208             else {
209 6         45 $service = $CC->fetch( $_[0] );
210             }
211              
212 29         181 $CC->add_type_mapping_for( $type, $service );
213             }
214              
215             sub infer {
216 24 100   24 1 1950 if (@_ == 1) {
217 1         28 return Bread::Board::Service::Inferred->new(
218             current_container => $CC,
219             service => $_[0],
220             infer_params => 1,
221             );
222             }
223             else {
224 23         86 my %params = @_;
225 23         1103 return Bread::Board::Service::Inferred->new(
226             current_container => $CC,
227             service_args => \%params,
228             infer_params => 1,
229             );
230             }
231             }
232              
233 2     2 1 21 sub wire_names { +{ map { $_ => depends_on($_) } @_ }; }
  4         12  
234              
235             sub depends_on ($) {
236 65     65 1 5767 my $path = shift;
237 65         2499 Bread::Board::Dependency->new(service_path => $path);
238             }
239              
240             my $LITERAL_ANON = 0;
241             sub literal($) {
242 2     2 1 8 my $value = shift;
243 2         58 Bread::Board::Literal->new(
244             name => 'LITERAL_ANON_' . $LITERAL_ANON++,
245             value => $value,
246             );
247             }
248              
249             1;
250              
251             __END__
252              
253             =pod
254              
255             =encoding UTF-8
256              
257             =head1 NAME
258              
259             Bread::Board - A solderless way to wire up your application components
260              
261             =head1 VERSION
262              
263             version 0.36
264              
265             =head1 SYNOPSIS
266              
267             use Bread::Board;
268              
269             my $c = container 'MyApp' => as {
270              
271             service 'log_file_name' => "logfile.log";
272              
273             service 'logger' => (
274             class => 'FileLogger',
275             lifecycle => 'Singleton',
276             dependencies => [ 'log_file_name' ],
277             ]
278             );
279              
280             container 'Database' => as {
281             service 'dsn' => "dbi:SQLite:dbname=my-app.db";
282             service 'username' => "user234";
283             service 'password' => "****";
284              
285             service 'dbh' => (
286             block => sub {
287             my $s = shift;
288             require DBI;
289             DBI->connect(
290             $s->param('dsn'),
291             $s->param('username'),
292             $s->param('password'),
293             ) || die "Could not connect";
294             },
295             dependencies => [ 'dsn', 'username', 'password' ]
296             );
297             };
298              
299             service 'application' => (
300             class => 'MyApplication',
301             dependencies => {
302             logger => 'logger',
303             dbh => 'Database/dbh',
304             }
305             );
306              
307             };
308              
309             no Bread::Board; # removes keywords
310              
311             # get an instance of MyApplication
312             # from the container
313             my $app = $c->resolve( service => 'application' );
314              
315             # now user your MyApplication
316             # as you normally would ...
317             $app->run;
318              
319             =head1 DESCRIPTION
320              
321             Bread::Board is an inversion of control framework with a focus on
322             dependency injection and lifecycle management. It's goal is to
323             help you write more decoupled objects and components by removing
324             the need for you to manually wire those objects/components together.
325              
326             Want to know more? See the L<Bread::Board::Manual>.
327              
328             +-----------------------------------------+
329             | A B C D E F G H I J |
330             |-----------------------------------------|
331             | o o | 1 o-o-o-o-o v o-o-o-o-o 1 | o o |
332             | o o | 2 o-o-o-o-o o-o-o-o-o 2 | o o |
333             | o o | 3 o-o-o-o-o o-o-o-o-o 3 | o o |
334             | o o | 4 o-o-o-o-o o-o-o-o-o 4 | o o |
335             | o o | 5 o-o-o-o-o o-o-o-o-o 5 | o o |
336             | | 6 o-o-o-o-o o-o-o-o-o 6 | |
337             | o o | 7 o-o-o-o-o o-o-o-o-o 7 | o o |
338             | o o | 8 o-o-o-o-o o-o-o-o-o 8 | o o |
339             | o o | 9 o-o-o-o-o o-o-o-o-o 9 | o o |
340             | o o | 10 o-o-o-o-o o-o-o-o-o 10 | o o |
341             | o o | 11 o-o-o-o-o o-o-o-o-o 11 | o o |
342             | | 12 o-o-o-o-o o-o-o-o-o 12 | |
343             | o o | 13 o-o-o-o-o o-o-o-o-o 13 | o o |
344             | o o | 14 o-o-o-o-o o-o-o-o-o 14 | o o |
345             | o o | 15 o-o-o-o-o o-o-o-o-o 15 | o o |
346             | o o | 16 o-o-o-o-o o-o-o-o-o 16 | o o |
347             | o o | 17 o-o-o-o-o o-o-o-o-o 17 | o o |
348             | | 18 o-o-o-o-o o-o-o-o-o 18 | |
349             | o o | 19 o-o-o-o-o o-o-o-o-o 19 | o o |
350             | o o | 20 o-o-o-o-o o-o-o-o-o 20 | o o |
351             | o o | 21 o-o-o-o-o o-o-o-o-o 21 | o o |
352             | o o | 22 o-o-o-o-o o-o-o-o-o 22 | o o |
353             | o o | 22 o-o-o-o-o o-o-o-o-o 22 | o o |
354             | | 23 o-o-o-o-o o-o-o-o-o 23 | |
355             | o o | 24 o-o-o-o-o o-o-o-o-o 24 | o o |
356             | o o | 25 o-o-o-o-o o-o-o-o-o 25 | o o |
357             | o o | 26 o-o-o-o-o o-o-o-o-o 26 | o o |
358             | o o | 27 o-o-o-o-o o-o-o-o-o 27 | o o |
359             | o o | 28 o-o-o-o-o ^ o-o-o-o-o 28 | o o |
360             +-----------------------------------------+
361              
362             Loading this package will automatically load the rest of the packages needed by
363             your Bread::Board configuration.
364              
365             =head1 EXPORTED FUNCTIONS
366              
367             The functions of this package provide syntactic sugar to help you build your
368             Bread::Board configuration. You can build such a configuration by constructing
369             the objects manually instead, but your code may be more difficult to
370             understand.
371              
372             =head2 C<container>
373              
374             =head3 simple case
375              
376             container $name, \&body;
377              
378             This function constructs and returns an instance of L<Bread::Board::Container>.
379             The (optional) C<&body> block may be used to add services or sub-containers
380             within the newly constructed container. Usually, the block is not passed
381             directly, but passed using the C<as> function.
382              
383             For example,
384              
385             container 'MyWebApp' => as {
386             service my_dispatcher => (
387             class => 'MyWebApp::Dispatcher',
388             );
389             };
390              
391             If C<$name> starts with C<'+'>, and the container is being declared inside
392             another container, then this declaration will instead extend an existing
393             container with the name C<$name> (without the C<'+'>).
394              
395             =head3 from an instance
396              
397             container $container_instance, \&body
398              
399             In many cases, subclassing L<Bread::Board::Container> is the easiest route to
400             getting access to this framework. You can do this and still get all the
401             benefits of the syntactic sugar for configuring that class by passing an
402             instance of your container subclass to C<container>.
403              
404             You could, for example, configure your container inside the C<BUILD> method of
405             your class:
406              
407             package MyWebApp;
408             use Moose;
409              
410             extends 'Bread::Board::Container';
411              
412             sub BUILD {
413             my $self = shift;
414              
415             container $self => as {
416             service dbh => ( ... );
417             };
418             }
419              
420             =head3 with parameters
421              
422             container $name, \@parameters, \&body
423              
424             A third way of using the C<container> function is to build a parameterized
425             container. These are useful as a way of providing a placeholder for parts of
426             the configuration that may be provided later. You may not use an instance
427             object in place of the C<$name> in this case.
428              
429             For more detail on how you might use parameterized containers, see
430             L<Bread::Board::Manual::Concepts::Advanced/Parameterized Containers>.
431              
432             =head2 C<as>
433              
434             as { some_code() };
435              
436             This is just a replacement for the C<sub> keyword that is easier to read when
437             defining containers.
438              
439             =head2 C<service>
440              
441             service $name, $literal;
442             service $name, %service_description;
443              
444             Within the C<as> blocks for your containers, you may construct services using
445             the C<service> function. This can construct several different kinds of services
446             based upon how it is called.
447              
448             =head3 literal services
449              
450             To build a literal service (a L<Bread::Board::Literal> object), just specify a
451             scalar value or reference you want to use as the literal value:
452              
453             # In case you need to adjust the gravitational constant of the Universe
454             service gravitational_constant => 6.673E-11;
455              
456             =head3 using injections
457              
458             To build a service using one of the injection services, just fill in all the
459             details required to use that sort of injection:
460              
461             service search_service => (
462             class => 'MyApp::Search',
463             block => sub {
464             my $s = shift;
465             MyApp::Search->new($s->param('url'), $s->param('type'));
466             },
467             dependencies => {
468             url => 'search_url',
469             },
470             parameters => {
471             type => { isa => 'Str', default => 'text' },
472             },
473             );
474              
475             The type of injection performed depends on the parameters used. You may use
476             the C<service_class> parameter to pick a specific injector class. For
477             instance, this is useful if you need to use L<Bread::Board::SetterInjection>
478             or have defined a custom injection service. If you specify a C<block>, block
479             injection will be performed using L<Bread::Board::BlockInjection>. If neither
480             of these is present, constructor injection will be used with
481             L<Bread::Board::ConstructorInjection> (and you must provide the C<class>
482             option).
483              
484             =head3 service dependencies
485              
486             The C<dependencies> parameter takes a hashref of dependency names mapped to
487             L<Bread::Board::Dependency> objects, but there are several coercions and sugar
488             functions available to make specifying dependencies as easy as possible. The
489             simplest case is when the names of the services you're depending on are the
490             same as the names that the service you're defining will be accessing them with.
491             In this case, you can just specify an arrayref of service names:
492              
493             service foo => (
494             dependencies => [ 'bar', 'baz' ],
495             # ...
496             );
497              
498             If you need to use a different name, you can specify the dependencies as a
499             hashref instead:
500              
501             service foo => (
502             dependencies => {
503             dbh => 'foo_dbh',
504             },
505             # ...
506             );
507              
508             You can also specify parameters when depending on a parameterized service:
509              
510             service foo => (
511             dependencies => [
512             { bar => { bar_param => 1 } },
513             'baz',
514             ],
515             # ...
516             );
517              
518             Finally, services themselves can also be specified as dependencies, in which
519             case they will just be resolved directly:
520              
521             service foo => (
522             dependencies => {
523             dsn => Bread::Board::Literal->new(
524             name => 'dsn',
525             value => 'dbi:mysql:mydb',
526             ),
527             },
528             # ...
529             );
530              
531             As a special case, an arrayref of dependencies will be interpreted as a service
532             which returns an arrayref containing the resolved values of those dependencies:
533              
534             service foo => (
535             dependencies => {
536             # items will resolve to [ $bar_service->get, $baz_service->get ]
537             items => [
538             'bar',
539             Bread::Board::Literal->new(name => 'baz', value => 'BAZ'),
540             ],
541             },
542             # ...
543             );
544              
545             =head3 inheriting and extending services
546              
547             If the C<$name> starts with a C<'+'>, the service definition will instead
548             extend an existing service with the given C<$name> (without the C<'+'>). This
549             works similarly to the C<has '+foo'> syntax in Moose. It is most useful when
550             defining a container class where the container is built up in C<BUILD> methods,
551             as each class in the inheritance hierarchy can modify services defined in
552             superclasses. The C<dependencies> and C<parameters> options will be merged with
553             the existing values, rather than overridden. Note that literal services can't
554             be extended, because there's nothing to extend. You can still override them
555             entirely by declaring the service name without a leading C<'+'>.
556              
557             =head2 C<literal>
558              
559             literal($value);
560              
561             Creates an anonymous L<Bread::Board::Literal> object with the given value.
562              
563             service 'dbh' => (
564             block => sub {
565             my $s = shift;
566             require DBI;
567             DBI->connect(
568             $s->param('dsn'),
569             $s->param('username'),
570             $s->param('password'),
571             ) || die "Could not connect";
572             },
573             dependencies => {
574             dsn => literal 'dbi:SQLite:somedb',
575             username => literal 'foo',
576             password => literal 'password',
577              
578             },
579             );
580              
581             =head2 C<depends_on>
582              
583             depends_on($service_path);
584              
585             The C<depends_on> function creates a L<Bread::Board::Dependency> object for the
586             named C<$service_path> and returns it.
587              
588             =head2 C<wire_names>
589              
590             wire_names(@service_names);
591              
592             This function is just a shortcut for passing a hash reference of dependencies
593             into the service. It is not typically needed, since Bread::Board can usually
594             understand what you mean - these declarations are all equivalent:
595              
596             service foo => (
597             class => 'Pity::TheFoo',
598             dependencies => {
599             foo => depends_on('foo'),
600             bar => depends_on('bar'),
601             baz => depends_on('baz'),
602             },
603             );
604              
605             service foo => (
606             class => 'Pity::TheFoo',
607             dependencies => wire_names(qw( foo bar baz )),
608             );
609              
610             service foo => (
611             class => 'Pity::TheFoo',
612             dependencies => {
613             foo => 'foo',
614             bar => 'bar',
615             baz => 'baz',
616             },
617             );
618              
619             service foo => (
620             class => 'Pity::TheFoo',
621             dependencies => [ qw(foo bar baz ) ],
622             );
623              
624             =head2 C<typemap>
625              
626             typemap $type, $service;
627             typemap $type, $service_path;
628              
629             This creates a type mapping for the named type. Typically, it is paired with
630             the C<infer> call like so:
631              
632             typemap 'MyApp::Model::UserAccount' => infer;
633              
634             For more details on what type mapping is and how it works, see
635             L<Bread::Board::Manual::Concepts::Typemap>.
636              
637             =head2 C<infer>
638              
639             infer;
640             infer(%hints);
641              
642             This is used with C<typemap> to help create the typemap inference. It can be
643             used with no arguments to do everything automatically. However, in some cases,
644             you may want to pass a service instance as the argument or a hash of service
645             arguments to change how the type map works. For example, if your type needs to
646             be constructed using a setter injection, you can use an inference similar to
647             this:
648              
649             typemap 'MyApp::Model::UserPassword' => infer(
650             service_class => 'Bread::Board::SetterInjection',
651             );
652              
653             For more details on what type mapping is and how it works, see
654             L<Bread::Board::Manual::Concepts::Typemap>.
655              
656             =head2 C<include>
657              
658             include $file;
659              
660             This is a shortcut for loading a Bread::Board configuration from another file.
661              
662             include "filename.pl";
663              
664             The above is pretty much identical to running:
665              
666             do "filename.pl";
667              
668             However, you might find it more readable to use C<include>.
669              
670             =head2 C<alias>
671              
672             alias $service_name, $service_path, %service_description;
673              
674             This helper allows for the creation of L<service
675             aliases|Bread::Board::Service::Alias>, which allows you to define a
676             service in one place and then reuse that service with a different name
677             somewhere else. This is sort of like a symbolic link for
678             services. Aliases will be L<resolved
679             recursively|Bread::Board::Traversable/fetch>, so an alias can alias an
680             alias.
681              
682             For example,
683              
684             service file_logger => (
685             class => 'MyApp::Logger::File',
686             );
687              
688             alias my_logger => 'file_logger';
689              
690             =head1 OTHER FUNCTIONS
691              
692             These are not exported, but might be helpful to you.
693              
694             =head2 C<set_root_container>
695              
696             set_root_container $container;
697              
698             You may use this to set a top-level root container for all container
699             definitions.
700              
701             For example,
702              
703             my $app = container MyApp => as { ... };
704              
705             Bread::Board::set_root_container($app);
706              
707             my $config = container Config => as { ... };
708              
709             Here the C<$config> container would be created as a sub-container of C<$app>.
710              
711             =head1 ACKNOWLEDGEMENTS
712              
713             Thanks to Daisuke Maki for his contributions and for really
714             pushing the development of this module along.
715              
716             Chuck "sprongie" Adams, for testing/using early (pre-release)
717             versions of this module, and some good suggestions for naming
718             it.
719              
720             Matt "mst" Trout, for finally coming up with the best name
721             for this module.
722              
723             Gianni "dakkar" Ceccarelli for writing lots of documentation, and
724             Net-a-Porter.com for paying his salary while he was doing it.
725              
726             =head1 ARTICLES
727              
728             L<Bread::Board is the right tool for this job|http://domm.plix.at/perl/2013_04_bread_board_is_the_right_rool_for_this_job.html>
729             Thomas Klausner showing a use-case for Bread::Board.
730              
731             =head1 SEE ALSO
732              
733             =over 4
734              
735             =item L<Bread::Board::Declare>
736              
737             This provides more powerful syntax for writing Bread::Board container classes.
738              
739             =item L<IOC>
740              
741             Bread::Board is basically my re-write of IOC.
742              
743             =item L<http://en.wikipedia.org/wiki/Breadboard>
744              
745             =back
746              
747             =head1 AUTHOR
748              
749             Stevan Little <stevan@iinteractive.com>
750              
751             =head1 BUGS
752              
753             Please report any bugs or feature requests on the bugtracker website
754             https://github.com/stevan/BreadBoard/issues
755              
756             When submitting a bug or request, please include a test-file or a
757             patch to an existing test-file that illustrates the bug or desired
758             feature.
759              
760             =head1 COPYRIGHT AND LICENSE
761              
762             This software is copyright (c) 2017, 2016, 2015, 2014, 2013, 2011, 2009 by Infinity Interactive.
763              
764             This is free software; you can redistribute it and/or modify it under
765             the same terms as the Perl 5 programming language system itself.
766              
767             =cut