AXForum  
Вернуться   AXForum > Microsoft Dynamics NAV > NAV: Blogs
DAX
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 04.10.2016, 12:11   #1  
Blog bot is offline
Blog bot
Участник
 
25,459 / 846 (79) +++++++
Регистрация: 28.10.2006
Navigate Into Success: Gentlemen’s agreement pattern, or handling the “Handled” pattern
Источник: http://vjeko.com/gentlemens-agreemen...andled-pattern
==============

I’ve delved deep into design patterns story with my last two blog posts, but I am far from over. The patterns I discussed are the ones we could use up until NAV 2015 (we can still use them, of course!) but some more robust loose coupling (excuse the near-oxymoron) can be achieved with what NAV 2016 brought along: events.

It’s the “Handled” pattern. This pattern comes from Thomas Hejlsberg, a chief architect and CTO of Microsoft Dynamics NAV, and was first described by Mark Brummel on his blog. It’s a powerful loose-coupling pattern that successfully addresses the shortcomings of all design patterns I discussed earlier. I would prefer calling this pattern Event Façade rather than “Handled”, but it’s not my baby to christen.

Let’s take a look.


First, this is what the pattern looks if you don’t care about the code:





So far, there’s not much difference between this and the other loose coupling patterns we’ve seen. And, from the consumer end, there’s no difference at all. However, let’s take a closer look at what’s happening inside both the façade and each of the subscribers (I won’t call them dependencies here).

First, the façade:



Translated to C/AL, this is what it typically looks like:



As facades go, this one is as simple as it gets. This pattern you see here, find subscriber > call event > make sure it was handled is something you put in all façade methods.

Then, each subscriber does the following:



Or, in C/AL, a subscriber could look like this:



And that’s it. You have some setup in the background, similar to the façade setup in case of CODEUNIT.RUN, and then you simply call the events. Subscribers subscribe, mark the event as handled, and all is good.

Compared to the patterns I discussed earlier, this one has several advantages:

  • It does not require CODEUNIT.RUN. This means that the event signature can carry far more context than a single record variable. This successfully mitigates the issue that caused me to come up with the TempBlob façade pattern.
  • Being based on events, it requires absolutely no knowledge about dependencies on the part of the façade. Dependencies can come and go without changing any component of the application.
However, it has a few disadvantages that I’d like to address here.

First, it’s the intermingledness (for the lack of a better term) of the infrastructure and the business logic code. Observe the dependency codeunit once again. The LogEvent function in there is not concerned only with the business logic it needs to execute (logging the event), it also has to be concerned with the two things it should not be concerned with. It needs to test for two conditions which should not be checked by business logic code – was the call handled already by someone else, and is this codeunit the one that should handle this call in the first place. And then, in the end, it must mark the call as handled, so that other dependencies, that find themselves in exactly the same situation, can know if they need to jump in and do some work, or can continue idling.

Maybe I am overly meticulous here, but I am not happy with this situation. The infrastructure code (that is the code that handles the internals, the scaffolding, the piping, whatever you wanna call it, in short any code that has nothing to do with the business logic of the task at hand) should not be mixed with the business logic code. They should be separated.

The infrastructure itself then depends on something that is very fuzzy: identification of the dependencies. Each dependency needs to somehow know whether it is the one that’s to handle this specific event. If it is, it handles it; if it isn’t, it doesn’t handle it. Since this identification happens at two levels (the façade first needs to find the identifier of the dependency to call, and pass this identifier as a part of the event context; and then each dependency gets a chance to compare the received identifier with some identifier it is aware of) there is no way to guarantee that identification succeeds.

This mish-mash of infrastructure and business logic code, while admittedly very shallow, still allows for the following anomalous situations to occur:

  • A dependency may incorrectly identify itself. This will result in no dependency firing.
  • A dependency may intentionally wrongly identify itself. This may result in a “stolen” event, handled by a dependency that should have no business handling it.
  • A dependency may ignore the “handled” flag, executing even though it shouldn’t.
  • A dependency may forget (or intend not) to set the “handled” flag, thus causing more dependencies to execute, or the call to fail in an error because the framework has no way to verify if a dependency was called.
Yes, all of this can be handled by having a gentlemen’s agreement between the dependencies and the framework, that each dependency will duly check the handled flag, properly identify itself, and finally set the handled flag. However, there is no such thing as a “gentlemen’s agreement pattern”, and this leaves a big door open to subscribers that may cause damage to the application. Not necessarily of malice; ignorance scares me equally as much.

Furthermore, since all dependencies are in fact invoked every time an event fires.

Obviously, this event can only work when you control all the code. However, that’s not what loose coupling often is. In true, real-life loose coupled scenarios, applications that are written by people unaware of each other, can happily talk to each other without having to know who is caller, who is responding to the call, and should not worry about much infrastructure.

Let’s be clear – infrastructure is necessary, every pattern has it; however, no good pattern I have seen, especially not any of the 23 Gang Of Four patterns, have logic and infrastructure code mixed up. That’s just not a good practice, and this is not how good patterns should work.

The story does not end here. This pattern also does not address the state preservation problem. Okay, this is not a problem of this pattern in particular – all of loose coupling patterns in C/AL exhibit this, as long as they are truly loose. An event subscriber that statically binds to events will always execute, and every time within a new instance of the codeunit. If you turn it to a manual subscriber, you have a bigger problem to solve: suddenly the façade infrastructure needs to become explicitly aware of the dependency, and there we have only half-loose façade just like with the variant façade, or argument table façade that comes without CODEUNIT.RUN.

Finally, one more issue I have with this pattern is that it does far more work than necessary. Since every time an event is called, all of the subscribers are being invoked, this will result in quite some overhead on each call. Now, depending on what your dependencies do and how often they are called, this may not be a problem at all. If you only have a couple of different dependencies and they are called infrequently, then this is no issue. However, if you have hundreds of dependencies, that are called every couple of seconds, then you may start to be concerned.

And I have exactly that. I have applied this pattern to break down a huge CASE block with hundreds of options into a polymorphic set of equally as many codeunits, by applying principles of what could be described as a command pattern of a sort. And this whole set is being called every few seconds – they correspond to buttons a user can press in a comprehensive HTML5-based UI, each button resulting in an individual call to a dependency codeunit. I did the measurements, and I am not personally concerned about the performance penalty, but still the fact that on every tap on the screen, the back end browses through a collection of several hundred subscribers only to find a single correct one to call doesn’t make me particularly enthusiastic about this approach.

And then again, architecturally speaking, the “handled” pattern (or the event façade pattern, or the gentlemen’s agreement pattern, whatever you wanna call it) is – architecturally speaking – the cleanest one I have discussed so far. It provides complete stability for all existing components of the system in case of any kind of change of behavior or business logic of any existing or freshly added dependency codeunit, and it enables establishing the most comprehensive and flexible contracts between consumers and dependencies.

However, having worked with C# quite a bit, and having applied a number of patterns to tackle different needs, I must say that all of these loose coupling patterns in C/AL seem clumsy at best. A good, robust loose coupling pattern requires at least some kind of abstraction, while C/AL provides nearly none. The farthest abstraction goes in C/AL is the ability of RecordRef type to represent any record type, but from perspective of most behavioral patterns (and loose coupling patterns are all behavioral) this is just not enough.

Let’s take one more look at the “handled” pattern. It’s not really a loose-coupling pattern. It’s a broadcasting pattern. It sends a message to a crowd of listeners, letting each of them a chance to process or ignore whatever was sent their way.

If there would be a way to turn this broadcast into a directed call, we’d be one step closer to a possibility of having truly polymorphic, loose coupling patterns in C/AL.

And – such a possibility exists, but is unfortunately again not good enough. It’s the manually subscribed codeunits. For each codeunit you can specify how exactly it is subscribing to events. By default, all are subscribing statically, which means a new instance is spawned for every subscribed event that’s being raised.

For manually subscribed codeunits, no subscriber is invoked unless the instance of the codeunit is first subscribed to events. If this was as versatile as you could hope for, then it would solve all issues we’ve currently seen with the loose coupling design patterns in C/AL.

First of all, a manually subscribed codeunit would make the whole processing more efficient, by reducing the number of codeunits that respond to an event only to decide to not go further because it’s not their turn. On top of that, a manually subscribed codeunit instance can retain state between event invocations: after an instance is subscribed, it’s always that instance that responds to events. If you have two instances of the same codeunit, and both of them are subscribed, then both of them are also invoked. Exactly as you’d expect an event pattern to work in an object-oriented world.

Except for a minor detail: you can only bind a codeunit instance to events if you hold its reference in a variable. Since you can only hold codeunit references in variables of explicit subtype, this means that the façade sitting in between the consumers and dependencies has again to be aware of all possible dependencies it can handle. And we are. unfortunately, back to square one.

I’ll propose two things at this stage. First is the “module binder” pattern (for the lack of a better name) that I came up with while trying to solve this problem. This pattern works with manually subscribed codeunits, but mitigates the explicit variable binding problem by providing a pair of codeunits, one being infrastructure, and another being business logic. It handles most of the problems we’ve encountered so far, and gets as far as C/AL could get to polymorphism and loose coupling with the current state of affairs. I won’t blog about it just yet – I’ve recently presented it at Directions US in Phoenix, I will present it at Directions EMEA in Prague in a short while, and then again at NAV TechDays in Antwerp next month. Until then, I’ll leave you with the materials I already published, and with a sense of suspense

However, I will propose the second of the two things I said I’d propose. It’s not a pattern, it’s not something you can do by applying the C/AL language or NAV technology stack in their current state. It’s a new thing altogether, that I hope Microsoft considers for a future version of C/AL: codeunit references. That will be the topic of my next post, so – stay tuned for some more musing about polymorphism, loose coupling, and design nitpickery.

Read this post at its original location at http://vjeko.com/gentlemens-agreemen...andled-pattern, or visit the original blog at http://vjeko.com. 5e33c5f6cb90c441bd1f23d5b9eeca34The post Gentlemen’s agreement pattern, or handling the “Handled” pattern appeared first on Vjeko.com.




Источник: http://vjeko.com/gentlemens-agreemen...andled-pattern
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Navigate Into Success: TempBlob Façade: a pattern proposition Blog bot NAV: Blogs 0 03.10.2016 09:11
Navigate Into Success: Decoupling dependencies in C/AL Blog bot NAV: Blogs 0 30.09.2016 16:11
Navigate Into Success: Activity Log or Activity Lock pattern? Blog bot Dynamics CRM: Blogs 0 20.11.2015 15:49
Navigate Into Success: Better error handling in NAV 2015 Blog bot Dynamics CRM: Blogs 0 13.10.2014 08:00
Navigate Into Success: .NET Tips & Tricks: Mediator Pattern (on steroids) Blog bot Dynamics CRM: Blogs 0 27.01.2014 10:25
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 00:04.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.