You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It uses manually bound event subscribers at both the interface layer and the implementation layer to allow consumers of the interface to work with none of the drawbacks or boilerplate commonly seen in other NAV/BC design patterns that address loose coupling and polymorphism. Usually those drawbacks are one or more of the following:
4
+
- Parameter records that only supports simple types (or binary..).
5
+
- Single instance codeunits at parts of the pattern requiring either singleton design, no global state or manual destruction of global state instead of relying on normal variable scoping to clean up.
6
+
- Stateless implementation (this one usually comes with initializing a new object every time the implementation is invoked which impacts performance - See https://youtu.be/jGdkpTGmCgs?t=3995 for more info on that, that talk was also the whole inspiration for this pattern..).
7
+
8
+
9
+
This pattern has none of these drawbacks, but it's still not perfect. It'll probably make debugging harder if taken to extremes since the language doesn't help you with any of this and if you have a lot of instantiated objects at the same time via the same interface there will be overhead when invoking one of them since manually bound subscribers still listen to ALL instantiated objects containing their corresponding publisher..
10
+
11
+
Microsoft should add a proper solution to this design problem in the language/runtime but until they do, this is the best pattern I can imagine when you need to build a generic framework and your daily work revolves around NAV/BC.
12
+
All of this should work in NAV2016 and newer, including AppSource extensions, since it only relies on manually bound events and CODEUNIT.RUN
13
+
14
+
Check out CarInterfaceConsumer.al first if you want to understand why this pattern can be useful.
15
+
The TestPage.al has an action that will run the consumer so you can see it in action.
//The codeunit IDs could come from persistent setup, be decided runtime or be send to NAV as part of a request from an external system.
15
+
car1.Construct(Codeunit::Skoda);
16
+
car2.Construct(Codeunit::Tesla);
17
+
18
+
//The object reference chains will be clean & independent after the object is constructed:
19
+
//Car1 => ICar => ICarBinder => Skoda
20
+
//Car2 => ICar => ICarBinder => Tesla
21
+
22
+
//Notice that ICar has the consumer facing API, while ICarBinder has the implementation facing API.
23
+
//From the consumers point of view, there is no magic or boilerplate or things to consider/keep in mind.
24
+
25
+
//Since nothing in the pattern is single instance the objects can live side by side, and go out of scope independently of each other. That also means no manual destructor is necessary.
26
+
//Compared to a discovery event pattern, constructing & using an object through an interface will not grow slower as the number of different possible implementations (car models) grow,
27
+
//since we don't need to broadcast to all possible implementations to find the right one.
28
+
29
+
//The only remaining overhead is: since every manually bound subscriber listens to ALL instances of publisher objects rather than one specific instance, performance will
30
+
//be impacted by the number of living implementation object at any given time. Ie. if I instantiate 100 cars and invoke 1 of them, 99 will have to exit out.
31
+
//But since we assume that the 99 other objects will at least be useful, otherwise why were they constructed in the first place, this hopefully has minimal impact compared to
32
+
//other drawbacks.
33
+
34
+
//We can pass the constructed objects to other codeunits that are written for the interface rather than for hardcoded references:
35
+
carComparison.CompareTopSpeed(car1, car2);
36
+
37
+
//The horse power comparison is using a nested object Engine within Car, implemented via the same pattern for illustration purposes.
0 commit comments