deploy: d7a7d2459a
This commit is contained in:
parent
34af3362da
commit
2d866c6316
732 changed files with 136202 additions and 67025 deletions
150
categories/pattern/index.html
Normal file
150
categories/pattern/index.html
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
<!doctype html><html lang=en class=no-js>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
||||
<meta name=generator content="Hugo 0.92.2">
|
||||
<link rel=alternate type=application/rss+xml href=https://alguidelines.dev/categories/pattern/index.xml>
|
||||
<meta name=robots content="index, follow">
|
||||
<link rel="shortcut icon" href=/favicons/favicon.ico>
|
||||
<link rel=apple-touch-icon href=/favicons/apple-touch-icon-180x180.png sizes=180x180>
|
||||
<link rel=icon type=image/png href=/favicons/favicon-16x16.png sizes=16x16>
|
||||
<link rel=icon type=image/png href=/favicons/favicon-32x32.png sizes=32x32>
|
||||
<link rel=icon type=image/png href=/favicons/android-36x36.png sizes=36x36>
|
||||
<link rel=icon type=image/png href=/favicons/android-48x48.png sizes=48x48>
|
||||
<link rel=icon type=image/png href=/favicons/android-72x72.png sizes=72x72>
|
||||
<link rel=icon type=image/png href=/favicons/android-96x96.png sizes=96x96>
|
||||
<link rel=icon type=image/png href=/favicons/android-144x144.png sizes=144x144>
|
||||
<link rel=icon type=image/png href=/favicons/android-192x192.png sizes=192x192>
|
||||
<title>Pattern | alguidelines.dev - Business Central Design Patterns</title>
|
||||
<meta name=description content>
|
||||
<meta property="og:title" content="Pattern">
|
||||
<meta property="og:description" content="Guidelines for when Developing AL for Microsoft Dynamics 365 Business Central">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://alguidelines.dev/categories/pattern/"><meta property="og:image" content="https://alguidelines.dev/images/og-image-fission.png"><meta property="og:site_name" content="alguidelines.dev - Business Central Design Patterns">
|
||||
<meta itemprop=name content="Pattern">
|
||||
<meta itemprop=description content="Guidelines for when Developing AL for Microsoft Dynamics 365 Business Central"><meta name=twitter:card content="summary_large_image">
|
||||
<meta name=twitter:image content="https://alguidelines.dev/images/og-image-fission.png">
|
||||
<meta name=twitter:title content="Pattern">
|
||||
<meta name=twitter:description content="Guidelines for when Developing AL for Microsoft Dynamics 365 Business Central">
|
||||
<link rel=preload href=/scss/main.min.465d5fa0bd58415aee47bc5a1c5d8deee19fe158cff814bc698ee863ea6b68eb.css as=style>
|
||||
<link href=/scss/main.min.465d5fa0bd58415aee47bc5a1c5d8deee19fe158cff814bc698ee863ea6b68eb.css rel=stylesheet integrity>
|
||||
<script src=https://code.jquery.com/jquery-3.6.0.min.js integrity=sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK crossorigin=anonymous></script>
|
||||
</head>
|
||||
<body class=td-term>
|
||||
<header>
|
||||
<nav class="js-navbar-scroll navbar navbar-expand navbar-dark flex-column flex-md-row td-navbar">
|
||||
<a class=navbar-brand href=/>
|
||||
<img src=/images/alguidelines-bclogo-pattern-white.png height=32px>
|
||||
<span class=font-weight-bold>alguidelines.dev - Business Central Design Patterns</span>
|
||||
</a>
|
||||
<div class="td-navbar-nav-scroll ml-md-auto" id=main_navbar>
|
||||
<ul class="navbar-nav mt-2 mt-lg-0">
|
||||
<li class="nav-item mr-4 mb-2 mb-lg-0">
|
||||
<a class=nav-link href=/docs/><i class="fas fa-book"></i><span>Docs</span></a>
|
||||
</li>
|
||||
<li class="nav-item mr-4 mb-2 mb-lg-0">
|
||||
<a class=nav-link href=https://github.com/microsoft/alguidelines/discussions/ target=_blank><i class="fas fa-comments"></i><span>Discussions</span></a>
|
||||
</li>
|
||||
<li class="nav-item mr-4 mb-2 mb-lg-0">
|
||||
<a class=nav-link href=https://github.com/microsoft/alguidelines target=_blank><i class="fab fa-github"></i><span>GitHub</span></a>
|
||||
</li>
|
||||
<li class="nav-item mr-4 mb-2 mb-lg-0">
|
||||
<a class=nav-link href=https://discord.gg/4wbfNv3 target=_blank><i class="fab fa-discord"></i><span>Discord</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="navbar-nav d-none d-lg-block"></div>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="container-fluid td-default td-outer">
|
||||
<main role=main class=td-main>
|
||||
<div class=td-content>
|
||||
<main class=taxonomy-taxonomy-page>
|
||||
<h1>Category: <span>Pattern</span></h1>
|
||||
<div>
|
||||
</div>
|
||||
<div>
|
||||
<article class="article-teaser article-type-docs">
|
||||
<h3><a href=/docs/patterns/event-bridge-pattern/>Event Bridge</a></h3>
|
||||
<p></p>
|
||||
<header class=article-meta>
|
||||
<div class="taxonomy taxonomy-terms-article taxo-tags">
|
||||
<h5 class=taxonomy-title>Tags:</h5>
|
||||
<ul class=taxonomy-terms>
|
||||
<li><a class=taxonomy-term href=https://alguidelines.dev/tags/interface/ data-taxonomy-term=interface><span class=taxonomy-label>Interface</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="taxonomy taxonomy-terms-article taxo-categories">
|
||||
<h5 class=taxonomy-title>Categories:</h5>
|
||||
<ul class=taxonomy-terms>
|
||||
<li><a class=taxonomy-term href=https://alguidelines.dev/categories/pattern/ data-taxonomy-term=pattern><span class=taxonomy-label>Pattern</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</header>
|
||||
</article>
|
||||
<article class="article-teaser article-type-docs">
|
||||
<h3><a href=/docs/patterns/facade-pattern/>Façade</a></h3>
|
||||
<p></p>
|
||||
<header class=article-meta>
|
||||
<div class="taxonomy taxonomy-terms-article taxo-categories">
|
||||
<h5 class=taxonomy-title>Categories:</h5>
|
||||
<ul class=taxonomy-terms>
|
||||
<li><a class=taxonomy-term href=https://alguidelines.dev/categories/pattern/ data-taxonomy-term=pattern><span class=taxonomy-label>Pattern</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</header>
|
||||
</article>
|
||||
<article class="article-teaser article-type-docs">
|
||||
<h3><a href=/docs/patterns/generic-method-pattern/>Generic Method</a></h3>
|
||||
<p></p>
|
||||
<header class=article-meta>
|
||||
<div class="taxonomy taxonomy-terms-article taxo-categories">
|
||||
<h5 class=taxonomy-title>Categories:</h5>
|
||||
<ul class=taxonomy-terms>
|
||||
<li><a class=taxonomy-term href=https://alguidelines.dev/categories/pattern/ data-taxonomy-term=pattern><span class=taxonomy-label>Pattern</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</header>
|
||||
</article>
|
||||
</div>
|
||||
<a href=https://alguidelines.dev/categories/ class=all-taxonomy-terms>All Categories</a>
|
||||
</main>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="bg-dark py-5 row d-print-none">
|
||||
<div class="container-fluid mx-sm-5">
|
||||
<div class=row>
|
||||
<div class="col-6 col-sm-4 text-xs-center order-sm-2">
|
||||
<ul class="list-inline mb-0">
|
||||
<li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title=GitHub aria-label=GitHub>
|
||||
<a class=text-white target=_blank rel=noopener href=https://github.com/microsoft/alguidelines aria-label=GitHub>
|
||||
<i class="fab fa-github"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title=Twitter aria-label=Twitter>
|
||||
<a class=text-white target=_blank rel=noopener href="https://twitter.com/search?q=%23bcalhelp" aria-label=Twitter>
|
||||
<i class="fab fa-twitter"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title=Discord aria-label=Discord>
|
||||
<a class=text-white target=_blank rel=noopener href=https://discord.gg/4wbfNv3 aria-label=Discord>
|
||||
<i class="fab fa-discord"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-6 col-sm-4 text-right text-xs-center order-sm-3">
|
||||
</div>
|
||||
<div class="col-12 col-sm-4 text-center py-2 order-sm-2">
|
||||
<small class=text-white>© 2022 alguidelines.dev Project All Rights Reserved</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<script src=https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js integrity=sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN crossorigin=anonymous></script>
|
||||
<script src=https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.min.js integrity="sha512-UR25UO94eTnCVwjbXozyeVd6ZqpaAE9naiEUBK/A+QDbfSTQFhPGj5lOR6d8tsgbBk84Ggb5A3EkjsOgPRPcKA==" crossorigin=anonymous></script>
|
||||
<script src=/js/tabpane-persist.js></script>
|
||||
<script src=/js/main.min.46b25eb30e292e80e9e18facc285e194199cf26288c5a1735cda89fb827eba54.js integrity="sha256-RrJesw4pLoDp4Y+swoXhlBmc8mKIxaFzXNqJ+4J+ulQ=" crossorigin=anonymous></script>
|
||||
</body>
|
||||
</html>
|
||||
482
categories/pattern/index.xml
Normal file
482
categories/pattern/index.xml
Normal file
|
|
@ -0,0 +1,482 @@
|
|||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>alguidelines.dev - Business Central Design Patterns – Pattern</title><link>https://alguidelines.dev/categories/pattern/</link><description>Recent content in Pattern on alguidelines.dev - Business Central Design Patterns</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><atom:link href="https://alguidelines.dev/categories/pattern/index.xml" rel="self" type="application/rss+xml"/><item><title>Docs: Event Bridge</title><link>https://alguidelines.dev/docs/patterns/event-bridge-pattern/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/docs/patterns/event-bridge-pattern/</guid><description>
|
||||
<p><em>Created by waldo &amp; Arend-Jan Kauffmann, Described by waldo</em></p>
|
||||
<h2 id="abstract">Abstract</h2>
|
||||
<p>In the world of interfaces, it is important to preserve (certain) events over multiple implementation of the interface.</p>
|
||||
<h2 id="context">Context</h2>
|
||||
<p>An app can have interfaces.
|
||||
It makes it possible for other apps to extend/change the implementations of a certain part of the business logic.</p>
|
||||
<p>Like in this example, we have an interface, to implement different ways for getting weights from scales:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">interface</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;IScale&#34;<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>GetWeight<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Decimal</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Tare<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><h2 id="problem">Problem</h2>
|
||||
<p>Multiple apps can subscribe to certain events of the app.
|
||||
When a new implementation is created, we need to make sure that these events are raised at the right times. If those events were published on the implementation codeunit, it might very well be that those events will not be raised, hard to find, or whatever.</p>
|
||||
<p>So, if we would implement it like this, it isn&rsquo;t really extensible, as a different implemention would implement different events .. and it&rsquo;s not possible to subscribe to all of them (including future implementations)</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">50407</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;Scale Wrong&#34;<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">implements</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IScale<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>GetWeight<span style="color:#ce5c00;font-weight:bold">() </span>Result<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Decimal</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">//TODO: Implement Bar GetWeight
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterGetWeight<span style="color:#ce5c00;font-weight:bold">(</span>Result<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Tare<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">//TODO: Implement Bar Tare
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterTare<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>[IntegrationEvent<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>false<span style="color:#ce5c00;font-weight:bold">)</span>]<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterGetWeight<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Result<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Decimal</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>[IntegrationEvent<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>false<span style="color:#ce5c00;font-weight:bold">)</span>]<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterTare<span style="color:#ce5c00;font-weight:bold">()
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><h2 id="description">Description</h2>
|
||||
<p>To mitigate this problem, we can work with a new, dedicated and isolated codeunit, with publisher events to be able to raise them from different places.</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">50406</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;IScale Triggers&#34;<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>[IntegrationEvent<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>false<span style="color:#ce5c00;font-weight:bold">)</span>]<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterGetWeight<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Result<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Decimal</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>[IntegrationEvent<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>false<span style="color:#ce5c00;font-weight:bold">)</span>]<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterTare<span style="color:#ce5c00;font-weight:bold">()
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p>This way, it&rsquo;s possible to raise the events in all the implementations:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">50405</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;Scale Bar&#34;<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">implements</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IScale<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IScaleTriggers<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;IScale Triggers&#34;<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>GetWeight<span style="color:#ce5c00;font-weight:bold">() </span>Result<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Decimal</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">//TODO: Implement Bar GetWeight
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span>IScaleTriggers<span style="color:#ce5c00;font-weight:bold">.</span>OnAfterGetWeight<span style="color:#ce5c00;font-weight:bold">(</span>Result<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Tare<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">//TODO: Implement Bar Tare
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span>IScaleTriggers<span style="color:#ce5c00;font-weight:bold">.</span>OnAfterTare<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><h2 id="benefits">Benefits</h2>
|
||||
<p>This new codeunit, with public events, makes the events accessible from all places, including new apps that are dependent from this app, and wants to extend the</p>
|
||||
<p>The naming convention (both starting with &ldquo;IScale&rdquo;) also makes it very easy to find that corresponding events for the interface.</p>
|
||||
<h2 id="when-not-to-use">When not to use</h2>
|
||||
<p>Obviously, the events should be carefully considered: only the events that make sense to &ldquo;share&rdquo; over all implementations, need this approach.</p>
|
||||
<h2 id="discussions">Discussions</h2>
|
||||
<p>You can discuss this pattern <a href="https://github.com/microsoft/alguidelines/discussions/66">here</a></p></description></item><item><title>Docs: Façade</title><link>https://alguidelines.dev/docs/patterns/facade-pattern/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/docs/patterns/facade-pattern/</guid><description>
|
||||
<p><em>Created by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (Gang of Four), Described by Jesper Schulz-Wedde (Microsoft)</em></p>
|
||||
<h2 id="abstract">Abstract</h2>
|
||||
<p>The intent of this pattern is to provide a unified API to a single or a collection of potentially complex subsystems. If you apply this pattern as a general pattern, you will ensure improved:</p>
|
||||
<ul>
|
||||
<li>Decoupling</li>
|
||||
<li>Encapsulation</li>
|
||||
<li>Readability</li>
|
||||
<li>Testability</li>
|
||||
<li>Maintainability</li>
|
||||
</ul>
|
||||
<h2 id="context">Context</h2>
|
||||
<p>Whenever you want to write an isolated piece of business logic, from now on referred to as subsystem, this pattern should be applicable.</p>
|
||||
<h2 id="problem">Problem</h2>
|
||||
<p>The facade pattern addresses two main problems:</p>
|
||||
<ul>
|
||||
<li>Over time as systems grow, they tend to become complex and harder to comprehend. By adding a facade on top of the subsystem, that complexity is hidden, and a clear API is defined.</li>
|
||||
<li>Any object or method which is publicly accessible, may not receive breaking changes in future releases without announced deprecation. This complicates maintainability of the system. By adding a facade, you ensure that the subsystem is inaccessible to the outside systems, enabling you to change the implementation details of the subsystem at will.</li>
|
||||
</ul>
|
||||
<h2 id="description">Description</h2>
|
||||
<p>The facade pattern is one of the most commonly used and known patterns, first described the book <a href="https://archive.org/details/designpatternsel00gamm/page/185">Design Patterns: Elements of Reusable Object-Oriented Software</a>. It is classified as a structural pattern. While it originates from the object-oriented world, it for sure also applies to AL. The power of a facade is that it:</p>
|
||||
<ul>
|
||||
<li>Improves the readability of your subsystem&rsquo;s API, as it acts as an entry point to your subsystem. This also allows for easier documentation of your API, as you can focus it to a few public objects.</li>
|
||||
<li>Improves the maintainability of your subsystem, as the internal subsystem can be modified or even completely replaced freely, without risking to break the public API - as long as the facade remains intact.</li>
|
||||
<li>Ensures that your code remains loosely coupled and encapsulated, as no other subsystem can take dependencies on your internal implementation details. This also fosters the reusability of your code.</li>
|
||||
<li>Suggests what needs most attention in your tests, as you would want to make sure that your subsystem&rsquo;s public API behaves as designed.</li>
|
||||
</ul>
|
||||
<p>Whenever you develop a functional group or an independent system, which has a clear API, you should add a facade to achieve the above-mentioned benefits.</p>
|
||||
<h3 id="what-is-a-subsystem">What is a subsystem?</h3>
|
||||
<p>A subsystem is a group of objects, which together provide a set of capabilities. Libraries are excellent examples of such subsystems.
|
||||
In Business Central, all modules in the System Application are subsystems. Examples are hence every module you will find in the system application, such as:</p>
|
||||
<ul>
|
||||
<li>Azure Blob Services API</li>
|
||||
<li>Barcode</li>
|
||||
<li>Cryptography Management</li>
|
||||
<li>Encoding</li>
|
||||
<li>Image</li>
|
||||
<li>RegEx</li>
|
||||
<li>&hellip;</li>
|
||||
</ul>
|
||||
<p>If you can describe a set of capabilities out of context of the rest of the system, chances are you are looking at a subsystem.</p>
|
||||
<h3 id="the-pattern">The Pattern</h3>
|
||||
<p>This is arguably one of easiest patterns to understand and implement. Loosely speaking, you simply need to smack a wrapper on top of your implementation and hide away your implementation details from the outside world.</p>
|
||||
<p><img src="diagram.jpg" alt="image"></p>
|
||||
<p>To achieve this, we are using <a href="https://docs.microsoft.com/bs-cyrl-ba/dynamics365/business-central/dev-itpro/developer/devenv-using-access-modifiers">access modifiers</a>. Let&rsquo;s try to take a look at an example, taken from the system application: <a href="https://github.com/microsoft/ALAppExtensions/tree/main/Modules/System/Image">the Image module</a>. I&rsquo;m using this very simplified example for illustration purposes. Notice, that even the full subsystem at time of writing isn&rsquo;t complex - it merely has a single codeunit containing the implementation details. However, as it is expected that the complexity will increase over time or that the implementation details can change, the subsystem is already equipped with a facade from the beginning.</p>
|
||||
<p><em>The Facade</em></p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">3971</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Image<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Access<span style="color:#f8f8f8;text-decoration:underline"> </span>=<span style="color:#f8f8f8;text-decoration:underline"> </span>Public<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ImageImpl<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;Image Impl.&#34;<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">/// &lt;summary&gt;
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">/// Creates an image from the specified data stream.
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">/// &lt;/summary&gt;
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">/// &lt;param name=&#34;InStream&#34;&gt;A Stream that contains the image data.&lt;/param&gt;
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>FromStream<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ImageImpl<span style="color:#ce5c00;font-weight:bold">.</span>FromStream<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">/// &lt;summary&gt;
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">/// Gets the width in pixels.
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">/// &lt;/summary&gt;
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic">/// &lt;returns&gt;The width in pixels.&lt;/returns&gt;
|
||||
</span><span style="color:#8f5902;font-style:italic"></span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>GetWidth<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Integer</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#ce5c00;font-weight:bold">(</span>ImageImpl<span style="color:#ce5c00;font-weight:bold">.</span>GetWidth<span style="color:#ce5c00;font-weight:bold">())</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p>The facade codeunit above has some characteristics:</p>
|
||||
<ul>
|
||||
<li>Access is explicitly set to Public, to underline that this is a facade.</li>
|
||||
<li>All methods are public.</li>
|
||||
<li>All methods are documented.</li>
|
||||
<li>No methods contain any logic. They merely point to implementation details.</li>
|
||||
<li>The object naming suggests that it will get referenced from the outside.</li>
|
||||
</ul>
|
||||
<p>Anyone who wants to access the subsystem, will only have to take a dependency on the facade; the implementation details are not needed nor accessible.</p>
|
||||
<p>Anyone who wants to access the subsystem, will only have to relate to this one public facade; the documentation makes it easy-to-understand the subsystem&rsquo;s capabilities.</p>
|
||||
<p>Test of the subsystem can be limited to testing the facade - it is strictly speaking the only thing that needs verification, that it functions as designed. It is the contract of the subsystem.</p>
|
||||
<p><em>The Subsystem</em></p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">3970</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;Image Impl.&#34;<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Access<span style="color:#f8f8f8;text-decoration:underline"> </span>=<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Internal</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>TempBlob<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;Temp Blob&#34;<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>FromStream<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">OutStream</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">OutStream</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>TempBlob<span style="color:#ce5c00;font-weight:bold">.</span>CreateOutStream<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">OutStream</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>CopyStream<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">OutStream</span><span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>GetWidth<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Integer</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Image<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">DotNet</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Image<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>TempBlob<span style="color:#ce5c00;font-weight:bold">.</span>CreateInStream<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Image<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">:=</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Image<span style="color:#ce5c00;font-weight:bold">.</span>FromStream<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">InStream</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#ce5c00;font-weight:bold">(</span>Image<span style="color:#ce5c00;font-weight:bold">.</span>Width<span style="color:#ce5c00;font-weight:bold">())</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p>There are no rules for the subsystem, except that access needs to be <strong>internal</strong>. How you implement, how much you document, how you test, is entirely up to you and not the business of the outside caller. Of course, you should apply all of the best practices and patterns anyway, as you and possibly other developers will have to understand, extend and maintain the subsystem too. But from the view of this pattern, the complexity of the subsystem is irrelevant - just as long as it&rsquo;s not accessible.</p>
|
||||
<h2 id="usage">Usage</h2>
|
||||
<p>The facade pattern is one of the most prominent patterns in the <a href="https://github.com/microsoft/ALAppExtensions/tree/main/Modules/System">system application</a>. You will find plenty of examples here.</p>
|
||||
<h2 id="benefits">Benefits</h2>
|
||||
<p>The benefits of this rather simple pattern should be abundantly clear by now. But let&rsquo;s go over them once more, structured by the advantages this patterns brings:</p>
|
||||
<h3 id="decoupling">Decoupling</h3>
|
||||
<p>As the entire subsystem is inaccessible to outside systems, no dependencies can be taken. Hence this patterns strongly promotes the decoupling of objects.</p>
|
||||
<h3 id="encapsulation">Encapsulation</h3>
|
||||
<p>The entire purpose of this very pattern is to encapsulate complexity; you hide away the implementation details behind an easy to understand facade.</p>
|
||||
<h3 id="readability">Readability</h3>
|
||||
<p>If done right, the developer doesn&rsquo;t need to be able to understand the details of the subsystem. Everything relevant to using the subsystem is described in the facade.</p>
|
||||
<h3 id="testability">Testability</h3>
|
||||
<p>Ensuring the correct behaviour of the subsystem can be done by testing the facade. The facade defines the contract of your subsystem - what does it expose and how should it behave. That contract should be covered with adequate tests, which will ensure that it is upheld, even if you decide to change the implementation of the subsystem.</p>
|
||||
<h3 id="maintainability">Maintainability</h3>
|
||||
<p>The one thing you may not change freely, is the facade and the test of the facade. It can be extended, but you should not break any existing APIs. But that leaves the entire subsystem to be completely rewritten, if you desire to do so. As no external dependencies can exist, there is no risk of introducing any syntactical breaking changes to the outside world. And as the tests of the public facade remain, there is no risk of introducing semantical breaking changes either - the contract is upheld, as long as your tests pass.</p>
|
||||
<h2 id="when-not-to-use">When not to use</h2>
|
||||
<p>This is a very applicable pattern, which can be used in most cases. While it may appear to be overkill at the beginning of the design of your subsystem, chances are your subsystem will evolve in complexity over time. The pattern may complicate implementation of extensibility, as you hide away all implementation details and hence also take away the opportunity to extend those, but that does not mean that extensibility cannot be achieved - but it requires more careful designing for extensibility. Extensibility with facades could be a topic of its own, which for now isn&rsquo;t covered by this pattern description. As always, use your common sense when to use and when not to use this pattern.</p>
|
||||
<h2 id="snippets">Snippets</h2>
|
||||
<p>Given the simplicity of this pattern, there are no snippets available at the moment.</p>
|
||||
<h2 id="list-of-references">List of references</h2>
|
||||
<p>This is one of the most commonly used and discussed, initially described here:</p>
|
||||
<p><a href="https://archive.org/details/designpatternsel00gamm/page/185">Design Patterns: Elements of Reusable Object-Oriented Software</a>. Addison Wesley. pp. 185ff. ISBN 0-201-63361-2.</p>
|
||||
<p>It is also a key pattern in the design of our system application modules, which is described here:</p>
|
||||
<p><a href="https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-blueprint">Module Architecture</a></p>
|
||||
<h2 id="discussions">Discussions</h2>
|
||||
<p>You can discuss this pattern <a href="https://github.com/microsoft/alguidelines/discussions/42">here</a></p></description></item><item><title>Docs: Generic Method</title><link>https://alguidelines.dev/docs/patterns/generic-method-pattern/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://alguidelines.dev/docs/patterns/generic-method-pattern/</guid><description>
|
||||
<p><em>Created by Gary Winter (Cloud Ready Software), Described by waldo (iFacto Business Solutions | Dynex)</em></p>
|
||||
<h2 id="abstract">Abstract</h2>
|
||||
<p>The goal of this pattern is to facilitate a lot of things in one single awesome way of writing code. If you apply this pattern as a general pattern, you&rsquo;ll implement:</p>
|
||||
<ul>
|
||||
<li>Extensibility</li>
|
||||
<li>Decoupling</li>
|
||||
<li>Readability</li>
|
||||
<li>Testability</li>
|
||||
<li>Encapsulation</li>
|
||||
</ul>
|
||||
<h2 id="context">Context</h2>
|
||||
<p>Whenever you have to write an isolated piece of business logic, this pattern should be applicable.</p>
|
||||
<h2 id="problem">Problem</h2>
|
||||
<p>Usually, when you ask people where to place code, they all have their own opinion: on a table or page, or in some kind of codeunit library where lots of functions will be placed, or .. . In fact, does it matter? It sure does, because in many cases, the code simply isn&rsquo;t maintainable, let alone extendable or testable.</p>
|
||||
<h2 id="description">Description</h2>
|
||||
<p>What if we have some kind of &ldquo;standard way&rdquo; to always write our code. The <em>Generic Method Pattern</em> is kind of like what it says: a generic way to implement a method.</p>
|
||||
<h3 id="what-is-a-method">What is a method?</h3>
|
||||
<p>Well, a method is <em>a significant piece of business logic</em> - maybe best explained by some examples:</p>
|
||||
<ul>
|
||||
<li>Posting a document</li>
|
||||
<li>Any button on a page that executes business logic</li>
|
||||
<li>a batch run to send emails</li>
|
||||
<li>&hellip;</li>
|
||||
</ul>
|
||||
<p>In a way, except &ldquo;data validation&rdquo;, most of the things we write in our daily life, are methods.</p>
|
||||
<h3 id="the-pattern">The Pattern</h3>
|
||||
<p><strong>One method, one codeunit</strong>
|
||||
The idea is to put the code in one <em>encapsulated</em> codeunit with the purpose to have all the code in that one codeunit function for that one method. This way, the codeunit will stay relatively small and readable.</p>
|
||||
<p>Let me start by showing an example, so you can refer to this complete example during the rest of the article:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">53100</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;WLD BlockCustomer Meth&#34;<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">internal</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>BlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">not</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ConfirmBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#ce5c00;font-weight:bold">) </span><span style="color:#204a87;font-weight:bold">then</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnBeforeBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>Cust<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DoBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>Cust<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>Cust<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>AcknowledgeBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DoBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">then</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#ce5c00;font-weight:bold">.</span>Blocked<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">:=</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#ce5c00;font-weight:bold">.</span>Blocked<span style="color:#000;font-weight:bold">::</span>All<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#204a87;font-weight:bold">Modify</span><span style="color:#ce5c00;font-weight:bold">(</span>true<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ConfirmBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ConfirmManagement<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;Confirm Management&#34;<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ConfirmQst<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Label</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#39;Are you sure?&#39;</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DefaultAnswer<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DefaultAnswer<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">:=</span><span style="color:#f8f8f8;text-decoration:underline"> </span>true<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">then</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#ce5c00;font-weight:bold">(</span>DefaultAnswer<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#ce5c00;font-weight:bold">(</span>ConfirmManagement<span style="color:#ce5c00;font-weight:bold">.</span>GetResponseOrDefault<span style="color:#ce5c00;font-weight:bold">(</span>ConfirmQst<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DefaultAnswer<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>AcknowledgeBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>AcknowledgeMsg<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Label</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#39;You successfully executed &#34;BlockCustomer&#34;&#39;</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">not</span><span style="color:#f8f8f8;text-decoration:underline"> </span>GuiAllowed<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">or</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">then</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Message<span style="color:#ce5c00;font-weight:bold">(</span>AcknowledgeMsg<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>[IntegrationEvent<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>false<span style="color:#ce5c00;font-weight:bold">)</span>]<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnBeforeBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>[IntegrationEvent<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>false<span style="color:#ce5c00;font-weight:bold">)</span>]<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p>Within that codeunit, the pattern is always the same:</p>
|
||||
<ul>
|
||||
<li>One public (internal) procedure</li>
|
||||
<li>The rest is always local</li>
|
||||
</ul>
|
||||
<p>So, from outside the codeunit, there is only one clear entrypoint: that one (public) internal function with its parameters.</p>
|
||||
<p>The <strong>pattern</strong> within the codeunit exists of a few layers:</p>
|
||||
<ul>
|
||||
<li>The UI layer</li>
|
||||
<li>The Event layer</li>
|
||||
<li>The method layer</li>
|
||||
</ul>
|
||||
<p><em>The UI layer</em>
|
||||
The UI layer takes care of the UI, obviously. What is important in this case, is that you always make sure that there is a &ldquo;HideDialog&rdquo; parameter that the business logic can use to still decide whether to use the dialog or not.</p>
|
||||
<p>These are the UI Layer parts, where you see the public function gets the HideDialog, and passes it to the UI-related procedures, where the business logic for showing the UI takes place. Also, the default answer of the confirmation is handled there as well (what if the business logic calls this method with HideDialog to &ldquo;true&rdquo;).</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">53100</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;WLD BlockCustomer Meth&#34;<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">internal</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>BlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">not</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ConfirmBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#ce5c00;font-weight:bold">) </span><span style="color:#204a87;font-weight:bold">then</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span>AcknowledgeBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold">
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ConfirmBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ConfirmManagement<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;Confirm Management&#34;<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>ConfirmQst<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Label</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#39;Are you sure?&#39;</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DefaultAnswer<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DefaultAnswer<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">:=</span><span style="color:#f8f8f8;text-decoration:underline"> </span>true<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">then</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#ce5c00;font-weight:bold">(</span>DefaultAnswer<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#ce5c00;font-weight:bold">(</span>ConfirmManagement<span style="color:#ce5c00;font-weight:bold">.</span>GetResponseOrDefault<span style="color:#ce5c00;font-weight:bold">(</span>ConfirmQst<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DefaultAnswer<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>AcknowledgeBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>AcknowledgeMsg<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Label</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#39;You successfully executed &#34;BlockCustomer&#34;&#39;</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">not</span><span style="color:#f8f8f8;text-decoration:underline"> </span>GuiAllowed<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">or</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">then</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Message<span style="color:#ce5c00;font-weight:bold">(</span>AcknowledgeMsg<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p><em>The Event layer</em>
|
||||
This layer is going to add flexibility to any app that has a dependency on this app. By default, the pattern always foresees an <code>OnBefore</code> and an <code>OnAfter</code> event.</p>
|
||||
<p>This is the relevant code for the event layer:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">53100</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;WLD BlockCustomer Meth&#34;<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">internal</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>BlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span>OnBeforeBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>Cust<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span>OnAfterBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>Cust<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span>[IntegrationEvent<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>false<span style="color:#ce5c00;font-weight:bold">)</span>]<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnBeforeBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>[IntegrationEvent<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>false<span style="color:#ce5c00;font-weight:bold">)</span>]<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>OnAfterBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p><em>The method layer</em>
|
||||
The last layer is obviously where the business logic will be written.</p>
|
||||
<p>The relevant part is:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">53100</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;WLD BlockCustomer Meth&#34;<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">internal</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>BlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span>DoBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>Cust<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">local</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>DoBlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Record</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#f8f8f8;text-decoration:underline"> </span>IsHandled<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">then</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">exit</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#ce5c00;font-weight:bold">.</span>Blocked<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#ce5c00;font-weight:bold">:=</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#ce5c00;font-weight:bold">.</span>Blocked<span style="color:#000;font-weight:bold">::</span>All<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Cust<span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#204a87;font-weight:bold">Modify</span><span style="color:#ce5c00;font-weight:bold">(</span>true<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#ce5c00;font-weight:bold">...
|
||||
</span><span style="color:#ce5c00;font-weight:bold"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p>Usually indicated with a &ldquo;do&rdquo;-function, the business logic takes place in that procedure. Obviously, when you have a decent amount of code, it&rsquo;s recommended that you make it readable by applying all the Best Practices in terms of readability in the codeunit. Though, a few pointers here:</p>
|
||||
<ul>
|
||||
<li>keep the <a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity">cyclomatic complexity</a> low
|
||||
<ul>
|
||||
<li>one line (function call) after an IF-clause</li>
|
||||
<li>one line (function call) after a repeat</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>readable function calls</li>
|
||||
<li>&hellip;</li>
|
||||
</ul>
|
||||
<p><strong>Call out to the method from a table</strong></p>
|
||||
<p>Now, there is a reason that the one global procedure in the method-codeunit is <code>internal</code>. We shouldn&rsquo;t be calling this procedure directly. We should be calling it through it&rsquo;s &ldquo;class&rdquo; (usually, a table can be seen as a class). That means, we would have to create a public (not internal) procedure on table-level, which can be used in the business logic.</p>
|
||||
<p>In our example above, this could be that table extension:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">tableextension</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">53100</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;Customer Ext BASE&#34;<span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">extends</span><span style="color:#f8f8f8;text-decoration:underline"> </span>Customer<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>{<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>BlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>HideDialog<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Boolean</span><span style="color:#ce5c00;font-weight:bold">)
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">var</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>WLDBlockCustomerMeth<span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">Codeunit</span><span style="color:#f8f8f8;text-decoration:underline"> </span>&#34;WLD BlockCustomer Meth&#34;<span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>WLDBlockCustomerMeth<span style="color:#ce5c00;font-weight:bold">.</span>BlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>Rec<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>HideDialog<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">procedure</span><span style="color:#f8f8f8;text-decoration:underline"> </span>BlockCustomer<span style="color:#ce5c00;font-weight:bold">()
|
||||
</span><span style="color:#ce5c00;font-weight:bold"> </span><span style="color:#204a87;font-weight:bold">begin</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span>BlockCustomer<span style="color:#ce5c00;font-weight:bold">(</span>false<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">end</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span><span style="color:#f8f8f8;text-decoration:underline"></span>}<span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p>This practice improves readability. In fact, by doing this, you just extended the suggestions-list in VSCode (IntelliSense) indicating a new method that your class can do. This is very convenient for the developer that might need your new method.</p>
|
||||
<p><em>Note - it could very well be that there simply isn&rsquo;t any table that can act as a class for our method. In that case, you could use a codeunit as well.</em></p>
|
||||
<p><strong>Naming Conventions</strong></p>
|
||||
<p>You might have noticed that the naming of our method is quite strict:</p>
|
||||
<ul>
|
||||
<li>codeunit name: <code>WLD BlockCustomer Meth</code></li>
|
||||
<li>internal proc: <code>BlockCustomer</code></li>
|
||||
<li>do-procedure: <code>DoBlockCustomer</code></li>
|
||||
</ul>
|
||||
<p>It is important to align these namings. It indicates that the codeunit only does one thing (remember: encapsulation), and it improves searchability from outside the codeunit (for example when you&rsquo;re searching symbols or something).</p>
|
||||
<h2 id="usage">Usage</h2>
|
||||
<p>Currently, there is no usage of this pattern in the BaseApp.</p>
|
||||
<p>The pattern has a main advantage in an ISV product, just because of the decoupling and extensibility. Although, I have seen many occasions where parts of the pattern was useful on PTE&rsquo;s as well. You simply never know if ever at the customer site, there is going to be another partner that needs to create its own PTE, and has to depend on yours. So I&rsquo;d say, this pattern is everywhere applicable, no matter the type of the app.</p>
|
||||
<h2 id="benefits">Benefits</h2>
|
||||
<p>As I said, it will facilitate a lot of advantages. Let&rsquo;s explain a bit more in depth:</p>
|
||||
<h3 id="extensibility">Extensibility</h3>
|
||||
<p>Thanks to the <em>event layer</em>, by applying this pattern for all methods, we will automatically have the bare minimum of events that we need to hook into a method: the <code>OnBefore-</code> and the <code>OnAfter</code>. Of course it would make sense to even add more events to the method when appropriate (eg, when you&rsquo;re inserting a record in a table, it might be interesting to also raise an event just before you call the insert).</p>
|
||||
<h3 id="decoupling">Decoupling</h3>
|
||||
<p>Thanks to these same events, and the fact the pattern foresees a handler as well, we are able to &ldquo;decouple&rdquo; our method as well. What do I mean with that? Well, we can simply subscribe to the <code>OnBefore</code>event, and set <code>IsHandled</code> to <code>true</code>. This means it will never execute the do-procedure, which means, the original procedure/method/business logic is &ldquo;decoupled&rdquo;.</p>
|
||||
<p>We can use this obviously for implementing our own method (a new way to accomplish this method), or to disable the method by simply subscribing to it, and only providing the <code>IsHandled := true</code> in our subscriber. However, there are many more usages where we can use this for.</p>
|
||||
<p>Maybe one more example:
|
||||
if you would apply this pattern to your product, at the customer, you&rsquo;ll be able to hotfix your methods simply by decoupling them and fixing the method instead of waiting for a hotfix from the hotfix-departement.</p>
|
||||
<p>This gives a lot of flexibility.</p>
|
||||
<h3 id="readability">Readability</h3>
|
||||
<p>When we talk about readability, we actually talk about the part where we expose our method on the class. The rule is: never call the codeunit, but only from one place: from its &ldquo;class&rdquo; - or in BC terms: its table (or codeunit).</p>
|
||||
<p>In terms of readability, that means that intellisense comes into play. In stead of:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL"><span style="color:#204a87;font-weight:bold">Codeunit</span><span style="color:#ce5c00;font-weight:bold">.</span>Run<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">Codeunit</span><span style="color:#000;font-weight:bold">::</span>&#34;Sales-Post&#34;<span style="color:#000;font-weight:bold">,</span><span style="color:#f8f8f8;text-decoration:underline"> </span>SalesHeader<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p>you simply get</p>
|
||||
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-AL" data-lang="AL">SalesHeader<span style="color:#ce5c00;font-weight:bold">.</span>Post<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span><span style="color:#f8f8f8;text-decoration:underline">
|
||||
</span></code></pre></div><p>THAT is readable. The previous is not! That is just something we got used to.</p>
|
||||
<h3 id="testability">Testability</h3>
|
||||
<p>There are two things in terms of testability where this pattern helps a lot.</p>
|
||||
<p><em>Unit testing</em>
|
||||
You can interpret &ldquo;unit testing&rdquo; very broadly. But just imagine: when you&rsquo;re building your software entirely out of &ldquo;methods&rdquo; - which means: when you&rsquo;d build your software entirely with this &ldquo;Generic Method Pattern&rdquo;. Now, the list of methods, are all the units that you need to test: if you test all your methods, you kind of like test the majority of your software, right?</p>
|
||||
<p>So you could simply set up rules in your company like: EVERY method needs a test-codeunit. And even more: since every method only has one global function - it&rsquo;s pretty easy to know the context, and all the flavors to test your method.</p>
|
||||
<p>The pattern describes the tests that needs to be written.</p>
|
||||
<p><em>Disabling methods</em>
|
||||
Coming back to the &ldquo;decoupling&rdquo; part - in tests, you actually might need it more than you realize. Just imagine: you want to test method 1, but method 2 comes in the way by interfering with configurations that you need to do, or UI that is popping up, while it could be completely pointless.<br>
|
||||
Solution: simply - within your test-codeunit - subscribe (with a manual subscriber) to method 2, set <code>IsHandled</code> to <code>false</code> - done!</p>
|
||||
<h3 id="encapsulation">Encapsulation</h3>
|
||||
<p>Don&rsquo;t underestimate the power of the encapsulation part of this pattern. One of the first questions that people ask themselves when reading into this pattern is: &ldquo;<em>isn&rsquo;t it going to consume all my codeunit-id&rsquo;s</em>&rdquo; or &ldquo;<em>so many codeunits, that can&rsquo;t be readable, right?</em>&rdquo;.<br>
|
||||
The fact that the functionality of one method is encapsulated in one codeunit is very powerful. You&rsquo;ll avoid <a href="https://sourcemaking.com/antipatterns/boat-anchor">Boat anchors</a> simply because because, thanks to the encapsulation, there is a limited amount of code in the codeunit, of course.<br>
|
||||
And because of that, it so much more maintainable, upgradable, readable, .. . Only advantages.</p>
|
||||
<h2 id="when-not-to-use">When not to use</h2>
|
||||
<p>However, there are occasions where you can&rsquo;t use this pattern. Just imagine if you&rsquo;d put EVERY SINGE LINE of code in a method, including the simple validation code on a table, or library-functions like in helper codeunits. That would obviously not make any sense.</p>
|
||||
<p>So all I can say is: use your common sense.</p>
|
||||
<p>One example: set the bar at &ldquo;validation code&rdquo;: any code that is solely there to facilitate data integrity doesn&rsquo;t belong in method codeunits.</p>
|
||||
<p>Another tip might be: don&rsquo;t let the amount of codelines trick you in deciding to <em>not</em> use this pattern: when it&rsquo;s a method, it&rsquo;s a method. When it makes sense to be able to extend, decouple, .. then this pattern can help.</p>
|
||||
<h2 id="snippets">Snippets</h2>
|
||||
<p><a href="https://marketplace.visualstudio.com/items?itemName=waldo.crs-al-language-extension">waldo&rsquo;s CRS AL Language Extension</a> contains snippets that help you in setting up the boiler plate code in a matter of seconds.</p>
|
||||
<p>The snippets are:</p>
|
||||
<ul>
|
||||
<li><code>tcodeunitMethodWithoutUIwaldo</code></li>
|
||||
<li><code>tcodeunitMethodWithUIwaldo</code></li>
|
||||
</ul>
|
||||
<h2 id="list-of-references">List of references</h2>
|
||||
<p>There have been a number of occasions where people have been sharing this pattern. Here is one:</p>
|
||||
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
|
||||
<iframe src="https://www.youtube.com/embed/CWpaD9RUa6U" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video"></iframe>
|
||||
</div>
|
||||
<h2 id="discussions">Discussions</h2>
|
||||
<p>You can discuss this pattern <a href="https://github.com/microsoft/alguidelines/discussions/41">here</a></p></description></item></channel></rss>
|
||||
Loading…
Add table
Add a link
Reference in a new issue