Commit | Line | Data |
ff05b07e |
1 | TODO, or the plan for making this stuff work right. |
2 | |
3 | The goals: |
4 | |
5 | 1/ I want to be able to specify a Controller base class, like |
6 | Catalyst::Controller::MessageDriven. That's where my |
7 | message-handling actually lives, so I want to build controllers |
8 | based on that, or whichever other class. |
9 | |
10 | 2/ We need a calling convention for the model implementations - in the |
11 | absence of defined interfaces this should be simple unblessed data, |
12 | but if we do have an interface, we should be able to put proper |
13 | constraints on it. |
14 | |
15 | 3/ Given generated controllers where I expose a bunch of methods from |
16 | the actual model classes, there needs to be some way to control |
56f4c9af |
17 | which methods are dispatchable - "very public", if you like. |
ff05b07e |
18 | |
19 | 4/ I'd like to be able to write down an "interface", consisting of a |
20 | set of messages my app is willing to handle, and have the framework |
21 | (or the controller base class, probably) reject messages that |
22 | aren't in that set. |
23 | |
24 | 5/ I'd also like to be able to say in that interface definition what |
56f4c9af |
25 | types of object those methods expect as a payload. |
ff05b07e |
26 | |
27 | 6/ It'd be nice if exceptions from model methods were caught by the |
56f4c9af |
28 | framework and converted into messages representing the error - |
ff05b07e |
29 | i.e. to set an error status, and return the text of the exception. |
30 | |
31 | All these things should be based on configuration. So, we've got |
32 | something to say what classes expose methods, which of those methods |
33 | are dispatchable, and which types are expected. |
34 | |
35 | Possible Implementation |
36 | |
56f4c9af |
37 | We can provide a number of controller base roles, for a number of |
ff05b07e |
38 | different message styles: YAML with type-tags, JSON bare hashes, |
8518a75b |
39 | etc. # FIXME - how does this work with role merging when you want to override the default? |
40 | # maybe base class knows how to serialize generically, and loads a serialization engine... |
41 | # or should we have serialization model.. Hmm, more thought needed. |
56f4c9af |
42 | |
8518a75b |
43 | We then provide strategy classes for a number of |
44 | policies for what models, and which methods on those models |
45 | get reflected / are dispatchable etc.. |
46 | |
47 | FIXME - Models, or just the methods, I'm thinking the strategy |
48 | just works out which methods. |
56f4c9af |
49 | |
50 | These should be selectable by configuration, the default |
ff05b07e |
51 | controller class plus overrides for specific controllers. |
52 | |
8518a75b |
53 | This makes the model to controller reflector config look like this: |
54 | |
55 | __PACKAGE__->config( |
56 | 'CatalystX::DynamicComponent::ModelToControllerReflector' => { |
57 | strategy => { |
58 | name => 'InterfaceRole', |
59 | roles => [qw/ My::Model::Interface::Role /], |
60 | }, |
61 | include => '(Datacash|Cybersource|Paypal)^', # Reflect these models. |
62 | controller_superclasses => [qw/ Catalyst::Controller /], # Default, you can omit this line |
63 | controller_roles => [qw/ My::ControllerRole /], |
64 | }, |
65 | 'Controller::Paypal' => { |
66 | superclasses => [qw/ My::Other::SuperClass /], # _replaces_ classes set above |
67 | roles => [qw/ My::Other::ControllerRole /], # merged with role set above |
68 | }, |
69 | ); |
70 | |
ff05b07e |
71 | The calling convention to model methods should be the "payload". That |
72 | might be a bare hashref for simple messages, or a blessed object of |
73 | some app-specific type if the message format contains first-class |
74 | objects, like tagged YAML. |
75 | |
76 | The "interfaces" should be Roles, which don't provide any methods but |
77 | which "need" methods to be implemented. We then use the "needed" |
78 | methods as the set of dispatchable methods, given if we compile OK, we |
56f4c9af |
79 | know that the model class has all the required methods. |
80 | *** Do we require that the model class in question has already composed |
81 | the appropriate role, and just check that by introspection or do we just |
82 | add it ourselves? Adding it ourselves involves making an anon subclass |
83 | to avoid action at a distance, so the former if possibly preferable? |
ff05b07e |
84 | |
85 | Types are implemented as type signatures on role methods, and we copy |
56f4c9af |
86 | them onto the actual methods on the model class at compile time. |
87 | **** I'm thinking this happens at role composition time.. |
ff05b07e |
88 | |
89 | Exception handling probably needs to be behaviour from the controller |
90 | base class, so that it can be specific to the type of message |
91 | serialization being used. |
56f4c9af |
92 | |