1# PODNAME: Bread::Board::Manual::Concepts::Typemap
2# ABSTRACT: An overview of the typemapping feature
3
4__END__
5
6=pod
7
8=encoding UTF-8
9
10=head1 NAME
11
12Bread::Board::Manual::Concepts::Typemap - An overview of the typemapping feature
13
14=head1 VERSION
15
16version 0.37
17
18=head1 INTRODUCTION
19
20A new (read: experimental) feature of Bread::Board is typemapped services.
21These are services which are mapped to a particular type rather then just
22a name. This feature has the potential to make obsolete a large amount of the
23Bread::Board configuration by simply asking Bread::Board to figure things
24out on its own. Here is a small example of how this works.
25
26  # define the classes making sure
27  # to specify required items and
28  # their types
29
30  {
31      package Stapler;
32      use Moose;
33
34      package Desk;
35      use Moose;
36
37      package Chair;
38      use Moose;
39
40      package Cubicle;
41      use Moose;
42
43      has 'desk'  => ( is => 'ro', isa => 'Desk',  required => 1 );
44      has 'chair' => ( is => 'ro', isa => 'Chair', required => 1 );
45
46      package Employee;
47      use Moose;
48
49      has [ 'first_name', 'last_name' ] => (
50          is       => 'ro',
51          isa      => 'Str',
52          required => 1,
53      );
54
55      has 'stapler' => ( is => 'rw', isa => 'Stapler', predicate => 'has_stapler' );
56
57      has 'work_area' => ( is => 'ro', isa => 'Cubicle', required => 1 );
58  }
59
60  # now create the container, and
61  # map the Employee type and ask
62  # Bread::Board to infer all the
63  # other relationships
64
65  my $c = container 'Initech' => as {
66      typemap 'Employee' => infer;
67  };
68
69  # now you can create new Employee objects
70  # by calling ->resolve with the type and
71  # supplying the required parameters (see
72  # below for details).
73
74  my $micheal = $c->resolve(
75      type       => 'Employee',
76      parameters => {
77          first_name => 'Micheal',
78          last_name  => 'Bolton'
79      }
80  );
81
82  my $cube = $micheal->work_area; # this will be a Cubicle object
83  $cube->desk;  # this will be a Desk object
84  $cube->chair; # this will be a Chair object
85
86  $micheal->has_stapler; # this is false
87
88  # We can create another Employee object
89  # and this time we pass in the optional
90  # parameter for the non-required 'stapler'
91  # attribute
92
93  my $milton = $c->resolve(
94      type       => 'Employee',
95      parameters => {
96          first_name => 'Milton',
97          last_name  => 'Waddams',
98          stapler    => Stapler->new
99      }
100  );
101
102  $milton->has_stapler; # this is true
103
104In the above example, we created a number of Moose classes that had
105specific required relationships. When we called C<infer> for the
106B<Employee> object, Bread::Board figured out those relationships
107and set up dependencies and parameters accordingly.
108
109For the C<work_area> object, we saw the B<Cubicle> type and then
110basically called C<infer> on the B<Cubicle> object. We then saw
111the B<Desk> and B<Chair> objects and called C<infer> on those as well.
112The result of this recursive inference was that the B<Employee>,
113B<Cubicle>, B<Desk> and B<Chair> relationships were modeled in
114Bread::Board as dependent services.
115
116Bread::Board also took it one step further.
117
118We were able to resolve the B<Cubicle>, B<Desk> and B<Chair> types
119automatically because they were already defined by Moose as subtypes
120of the I<Object> type. We knew that it could introspect those classes
121and get more information. However, this was not the case with the
122I<first_name> and I<last_name> attributes of the B<Employee> object.
123In that case, we determined that we couldn't resolve those objects and
124(because it was a top-level inference) instead turned them into required
125parameters for the inferred B<Employee> service.
126
127And lastly, with a top-level inference (not one caused by recursion)
128Bread::Board will also look at all the remaining non-required attributes
129and turn them into optional parameters. In this case we have a C<stapler>
130attribute that is not required and so is listed as an optional parameter,
131meaning that it is not required, but still subject to type checking.
132
133=head1 CONCLUSION
134
135This example should give a good basic overview of this feature and more
136details can be found in the test suite (F<t/07*.t>). These show examples
137of how to typemap roles to concrete classes and how to supply hints to
138C<infer> to help Bread::Board figure out specific details.
139
140As I mentioned above, this feature should be considered experimental
141and we are still working out details and writing tests for it. Any
142contributions are welcome.
143
144=head1 AUTHOR
145
146Stevan Little <stevan@iinteractive.com>
147
148=head1 BUGS
149
150Please report any bugs or feature requests on the bugtracker website
151https://github.com/stevan/BreadBoard/issues
152
153When submitting a bug or request, please include a test-file or a
154patch to an existing test-file that illustrates the bug or desired
155feature.
156
157=head1 COPYRIGHT AND LICENSE
158
159This software is copyright (c) 2019, 2017, 2016, 2015, 2014, 2013, 2011, 2009 by Infinity Interactive.
160
161This is free software; you can redistribute it and/or modify it under
162the same terms as the Perl 5 programming language system itself.
163
164=cut
165