{"id":3024,"date":"2019-10-31T12:02:52","date_gmt":"2019-10-31T00:02:52","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=3024"},"modified":"2019-10-31T12:03:00","modified_gmt":"2019-10-31T00:03:00","slug":"scope-elevation-creating-a-pseudo-namespace","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/3024\/","title":{"rendered":"Scope Elevation: Creating A &#8216;Pseudo-Namespace&#8217;"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">7<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span>\n<p>In my <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/3019\">previous post<\/a> I talked about how &#8220;namespaces&#8221; in Delphi really don&#8217;t exist for any practical purposes normally associated with the concept.  Having become familiar with the concept in other languages I found I was missing them, so I devised a way to obtain some of the benefits, despite the shortcomings in the language.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"has-drop-cap\">Before digging in to my (self-named) <em>Scope Elevation<\/em> pattern it might further help to understand what I am trying to achieve by first looking at the first-class <strong>namespace<\/strong> support in <strong>Oxygene<\/strong>.  As an alternative ObjectPascal implementation, comparing the feature in that very similar language should further help identify how and where Delphi falls short in this one respect.<\/p>\n\n\n\n<p>As mentioned in the previous post, namespaces in <strong>Oxygene<\/strong> are explicit but are also required.  So much so that in fact they supercede the concept of <strong>unit<\/strong>s entirely.  In Oxygene <strong>unit<\/strong> essentially has become just another name for a file but in that file you don&#8217;t <em>declare<\/em> a <strong>unit<\/strong>&#8216;s identity, rather you identify the <em>namespace<\/em> that will contain the identifiers introduced in that file.  Crucially, that namespace doesn&#8217;t have to have anything to do with the name of the file\/unit.<\/p>\n\n\n\n<p>Let&#8217;s use a hypothetical (at this stage) <strong>Oxygene<\/strong> implementation of the <code>TTest<\/code> class in <a href=\"https:\/\/github.com\/deltics\/deltics.smoketest\">Smoketest<\/a> and compare it with the Delphi implementation.  We aren&#8217;t too concerned with the specifics of the code implemented in these examples so they are not complete, but stripped down to bare minimums to illustrate the concepts of interest.<\/p>\n\n\n\n<p>So first, the <strong>Delphi<\/strong> reality:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-pascal\">\/\/ filename: Deltics.Smoketest.Test.pas\n\n  unit Deltics.Smoketest.Test;\n\ninterface\n\n  uses\n    Classes;\n\n  type\n    TTest = class(TInterfacedObject)\n      \/\/\n    end;<\/code><\/pre>\n\n\n\n<p>This <strong>unit<\/strong> introduces a new class type <code>TTest<\/code>.  Adopting the best practice of one-class-per-unit, this is the only class implemented in this unit.  As a result, code in a project that needs to reference this type (e.g. to implement a set of tests, since this is the base class required to do that) must include <em>this<\/em> specific <strong>unit<\/strong> in its <code>uses<\/code> clause.<\/p>\n\n\n\n<p>A project implementing a set of tests must also reference the <code>TestRun<\/code> object which is an instance of a different class, <code>TTestRun<\/code>.  Again, following the one-class-per-unit practice, this means referencing a further <strong>unit<\/strong> containing the <code>TTestRun<\/code> implementation:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-pascal\">\/\/ filename: Deltics.Smoketest.TestRun.pas\n\n  unit Deltics.Smoketest.TestRun;\n\ninterface\n\n  uses\n    Classes;\n\n  type\n    TTestRun = class(TInterfacedObject)\n      \/\/\n    end;\n\n  var\n    TestRun: TTestRun;<\/code><\/pre>\n\n\n\n<p>When implementing a test project, you need to know\/remember to <strong>use<\/strong> <code>Deltics.Smoketest.Test<\/code> in units that implement tests and also to <strong>use<\/strong> <code>Deltics.Smoketest.TestRun<\/code> where-ever you need to reference the <code>TestRun<\/code> object:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-pascal\">\/\/ filename: MyTests.dpr\n\nprogram MyTests;\n\nuses\n  Deltics.Smoketest.TestRun,\n  MyTestCases.pas in &#039;MyTestCases.pas&#039;;\n\nbegin\n  TestRun.Test(TMyTestCases);\nend.\n\n\/\/ ----------------------------------------\n\n\/\/ filename: MyTestCases.pas\n\nunit MyTestCases;\n\n  uses\n    Deltics.Smoketest.Test;\n\n  type\n    TMyTestCases = class(TTest)\n    end;<\/code><\/pre>\n\n\n\n<p>Ideally you would simply <strong>use<\/strong> <code>Deltics.Smoketest<\/code> consistently and have this bring into scope the public symbols from the entire <strong>Smoketest<\/strong> framework without you having to know which individual files in that framework those identifiers are introduced.<\/p>\n\n\n\n<p>Anyone familiar with <strong>.net<\/strong> programming will be very familiar with this convenience.  Some particularly large frameworks may comprise multiple namespaces but in general, each individual namespace typically introduces many different symbols which &#8211; if you examine the source for those frameworks &#8211; are contributed from many different files.  Equally in some cases some of the symbols in those files are never surfaced directly to consumers at all even though they are crucial to the internal operation of the framework.<\/p>\n\n\n\n<p>This is not directly achievable in Delphi (without <em>Scope Elevation<\/em>) but is in <strong>Oxygene<\/strong>.  Before getting into that however, we should first address one simple alternative: <strong>The Monolith<\/strong>.<\/p>\n\n\n\n<p>We <em>could<\/em> simply lump all of our classes into one, all-encompassing unit, ensuring that non-consumable internal implementation details are confined to separate units, almost guaranteeing violation of many good practices, including the one-class-per-unit principle, introducing multiple concerns and multiple responsibilities (not necessarily in the classes, but in the physical organisation of those classes).  For small, simple frameworks this <em>may<\/em> be an appropriate choice, but for larger or more complex frameworks (as measured by N of identifiers as much as N LOC) it quickly becomes unwieldy.<\/p>\n\n\n\n<p>Compounding the problem, taking such an approach paves a tempting path  to tightly coupled classes in the framework since they have ready and convenient access to each others &#8216;internals&#8217;.<\/p>\n\n\n\n<p class=\"has-background has-pale-pink-background-color\">This is the path I took with the original <em>Deltics.Smoketest <\/em>framework, 1.0 which proved to be a truly <em>horrific<\/em> mistake.  Multiple attempts to simplify and improve that framework over the years were thwarted by the tight coupling that the monolith created made worse by attempts to break the monolith in some areas which really only made multiple monoliths stacked on top of each other.  A significant portion of the blame falls squarely on me for the lack of discipline needed to avoid falling into the traps, but I think we&#8217;ve all been down the road of believing we need only be careful to &#8220;avoid the pitfalls&#8221; and violating our own principles will be justified and worth it &#8220;this time&#8221;.  On the brighter side, this pretty much dictated the &#8220;green field&#8221; do-over for 2.x which I think is <em>much<\/em> &#8216;cleaner&#8217; as a result.<\/p>\n\n\n\n<p>So let&#8217;s now look at how these types might be realised in an <strong>Oxygene<\/strong> implementation to see how a modern <strong>ObjectPascal<\/strong> language can get the benefits of genuine namespaces.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p class=\"has-drop-cap\">As mentioned in the introduction, units in <strong>Oxygene<\/strong> do not redundantly declare their own identity but instead identify the namespace container for the symbols they introduce.  This means we can stick to our principles and have one-class-per-unit (where &#8216;unit&#8217; now simply means &#8216;file&#8217;).  But in each unit we can identify the in which to place the identifiers introduced by each file.  Since the namespace is not tied to the identity of the unit, different units can all identify the same namespace.<\/p>\n\n\n\n<p>First, the <code>TTest<\/code> class:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\n\/\/ filename: Deltics.Smoketest.Test.pas\n\nnamespace Deltics.Smoketest;\n\nuses\n  Classes;\n\ntype\n  TTest = class(TInterfacedObject)\n    \/\/\n  end;\n\nend.\n<\/pre><\/div>\n\n\n<p>And then the <code>TTestRun<\/code> class and <code>TestRun<\/code> object:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\n\/\/ filename: Deltics.Smoketest.TestRun.pas\n\nnamespace Deltics.Smoketest;\n\nuses\n  Classes;\n\ntype\n  TTestRun = class(TInterfacedObject)\n    \/\/\n  end;\n\nvar\n  TestRun: TTestRun;\n\nend.\n<\/pre><\/div>\n\n\n<p class=\"has-background has-luminous-vivid-amber-background-color\">Worth pointing our here is that with the <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/2460\">Unified Syntax introduced in Oxygene 9.x<\/a> there is no need for separate <code>interface<\/code> and <code>implementation<\/code> sections in <strong>Oxygene<\/strong> (though you can still have them if you prefer and <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/2470\">even mix\/match as required<\/a>).<\/p>\n\n\n\n<p>So we still have two separate files, one each for <code>TTest<\/code> and <code>TTestRun<\/code>, but in each case they identify the same <strong>namespace<\/strong> as the target scope for the symbols they introduce.  Meanwhile, on the other side of the tracks, when we add to the <strong>uses<\/strong> clauses in our <strong>Oxygene<\/strong> code we identify <em>namespaces<\/em>, not units or files.  References to the <em>physical<\/em> files are handled separately as a set of project references maintained as project meta-data.<\/p>\n\n\n\n<p class=\"has-background has-light-green-cyan-background-color\">For different platforms Oxygene supports different forms of project references.  On <strong>.net<\/strong> you add references to <strong>.net <\/strong>assemblies or <strong>nuget<\/strong> packages.  On <strong>Java<\/strong>\/<strong>Android<\/strong> you add references to <strong>.jar<\/strong> files or <strong>maven<\/strong> packages etc etc.  On <em>all<\/em> platforms you can also reference <em>Shared Code<\/em> projects, which are other <strong>Elements<\/strong> language source files (Swift, C#, Java, Go or Oxygene).<\/p>\n\n\n\n<p>As a result, whether we are coding our main test project and referencing the <code>TestRun<\/code> object or implementing a set of tests in a test case, we simply reference the <strong><code>Deltics.Smoketest<\/code><\/strong> namespace.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\n\/\/ filename: MyApp.Tests.pas\n\nnamespace MyApp.Tests;\n\nuses\n  Deltics.Smoketest;\n\nbegin\n  TestRun.Test(MyTestCases);\nend.\n\n\/\/ ----------------------------------------\n\n\/\/ filename: MyApp.TestCases.pas\n\nnamespace MyApp.Tests;\n\n  uses\n    Deltics.Smoketest;\n\n  type\n    MyTestCases = class(TestCase)\n    end;\n<\/pre><\/div>\n\n\n<p>This is far from being a real-world example of an <strong>Oxygene<\/strong> test project and is intended only to show the namespace referencing.<\/p>\n\n\n\n<p>Notice how in this case we don&#8217;t need to <strong>use<\/strong> <em>anything<\/em> in our main program code in order to reference the test case class we created for the test project since this is declared to be in the same <strong>namespace<\/strong> as the main program itself anyway!<\/p>\n\n\n\n<p>You might already also have recognised that this allows potentially anyone to introduce <em>additional<\/em> identifiers into the <code>Deltics.Smoketest<\/code> namespace by identifying that namespace in their own units.  As long as the code containing those units is added to the references for a project, those additional identifiers are introduced for any existing code already using the <code>Deltics.Smoketest<\/code> namespace.<\/p>\n\n\n\n<p>You might find this thought discomforting at first but again, this is a pattern that will be very familiar to .net developers where this precise technique is often used to introduce additional class extenders to assist in configuration of framework extensions (unlike Delphi type helpers, type extenders on other platforms allow multiple extenders to be in scope simultaneously).<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p class=\"has-drop-cap\"><strong><em>Scope Elevation<\/em><\/strong> provides a way in <strong>Delphi<\/strong> to get <em>almost<\/em> the same level of convenience for the <em>consumers<\/em> of a framework, with the additional cost of just a little more work for the implementation of the framework itself.<\/p>\n\n\n\n<p>If you have already looked at the <strong>Smoketest 2.x<\/strong> framework you may already have identified what I am talking about.  The <code>Deltics.Smoketest<\/code> unit is the <strong>Scope Elevation<\/strong> unit for the framework (or <strong>Pseudo-Namespace<\/strong> if you prefer).<\/p>\n\n\n\n<p>The <code>Deltics.Smoketest<\/code> unit contains little more than <em>declarations of symbols that are concretely defined elsewhere in the framework<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-pascal\">  unit Deltics.Smoketest;\n\ninterface\n\n  uses\n    Deltics.Smoketest.SelfTest,\n    Deltics.Smoketest.Test,\n    Deltics.Smoketest.TestRun,\n    Deltics.Smoketest.Utils;\n\n  \/\/ Elevate the scope of the TTest class so that test class implementation units\n  \/\/  need only reference Deltics.Smoketest.\n  type\n    TTest         = Deltics.Smoketest.Test.TTest;\n    TSelfTest     = Deltics.Smoketest.SelfTest.TSelfTest;\n    EInvalidTest  = Deltics.Smoketest.Utils.EInvalidTest;\n\n  const\n    METHOD_NAME = Deltics.Smoketest.Test.METHOD_NAME;\n    TEST_NAME   = Deltics.Smoketest.Test.TEST_NAME;\n\n\n  \/\/ This function provides read-only access to the TestRun variable maintained\n  \/\/  in the TestRun implementation unit.\n  function TestRun: TTestRun;<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">The Good<\/h4>\n\n\n\n<p>For types scope elevation simply and efficiently creates type <em>aliases<\/em> which allows code that <strong>uses<\/strong> <code>Deltics.Smoketest<\/code> to reference types that are actually declared in other units without having to <strong>use<\/strong> those other units themselves.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">The Not So Good<\/h4>\n\n\n\n<p><strong>Constants<\/strong> cannot be easily aliased so we have to create duplicates which happen to share the same name.<\/p>\n\n\n\n<p><strong>Functions<\/strong> either have to be wrappers, adding an additional call-hop or requiring in-lining.  Or with a bit more work you can instead declare a function variable which points to the underlying concrete function, eliminating the additional call-hop or reliance on in-lining.<\/p>\n\n\n\n<p><strong>Enumerations<\/strong> (not illustrated by Smoketest) are a bit tricky.  You need to both <em>alias the type<\/em> <strong>and<\/strong> <em>declare constants<\/em> for the enum members that you wish to be available to consumers of your framework:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-pascal\">type\n   TMyEnum = MyCompany.MyFramework.TMyEnum;\nconst\n   meFirstValue  = MyCompany.MyFramework.meFirstValue; \n   meSecondValue = MyCompany.MyFramework.meSecondValue;\n   meThirdValue  = MyCompany.MyFramework.meThirdValue;<\/code><\/pre>\n\n\n\n<p>This can be tedious for enums with a lot of members, but also useful in the rare case that you have certain enum members which consumers of your framework perhaps should not be using.  You also need to be aware that the constants will not support an enum type prefix if you habitually used scoped enums (again, this might be a &#8220;good thing&#8221; depending on your p.o.v).<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Why Bother ?<\/h3>\n\n\n\n<p>As mentioned, <strong>Scope Elevation \/ Pseudo-Namespace Unit<\/strong> requires some additional work on the part of the framework developer for what initially appears to be no benefit to themselves as it primarily serves to simplify the work for the <em>consumers<\/em> of the framework.<\/p>\n\n\n\n<p>In practice of course often a framework developer is their own best customer so they are helping themselves by helping others.<\/p>\n\n\n\n<p>In addition, the provisioning of a specific unit to act as the &#8220;public face&#8221; of your framework can help you stick to good software practices in the implementation details instead of compromising those principles as trade-offs against consumability.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">7<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> In my previous post I talked about how &#8220;namespaces&#8221; in Delphi really don&#8217;t exist for any practical purposes normally associated with the concept. Having become familiar with the concept in other languages I found I was missing them, so I devised a way to obtain some of the benefits, despite the shortcomings in the language.<\/p>\n","protected":false},"author":2,"featured_media":3022,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4,180],"tags":[13,185],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/niklaus-wirth-edit.jpg?fit=934%2C362&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-MM","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":3019,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/3019\/","url_meta":{"origin":3024,"position":0},"title":"What&#8217;s in a Name[space] ?","date":"29 Oct 2019","format":false,"excerpt":"A recap of unit aliases and how they relate to namespace prefixes as a prelude to a more interesting examination of Scope Elevation.","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/niklaus-wirth-edit.jpg?fit=934%2C362&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1817,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1817\/","url_meta":{"origin":3024,"position":1},"title":"Getting the Battery Level on Android With Delphi","date":"01 Oct 2013","format":false,"excerpt":"Over the past few days I posted a two part series showing how to obtain the current battery level as part of the implementation of an Android AppWidget using Oxygene. As far as I can tell AppWidgets simply aren't possible using Delphi but reading the battery is quite straightforward Android\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1300,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1300\/","url_meta":{"origin":3024,"position":2},"title":"What&#8217;s in a Name(space) ?","date":"28 Nov 2012","format":false,"excerpt":"The ever evolving DWScript project continues to advance the Pascal language at an impressive pace. Just today it was announced that this scripting version of Pascal now has \"namespace\" support. When I first read the details of the implementation, my initial reaction was that it \"felt a bit backwards\". The\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1503,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1503\/","url_meta":{"origin":3024,"position":3},"title":"Sharing Code Across Platforms in Oxygene","date":"22 Aug 2013","format":false,"excerpt":"There seems to be a perception among some people that Delphi is in the unique position of allowing developers to share and re-use code across the various platforms that it's compiler can now (and will soon) target. But this is not the case. Oxygene has had this capability right from\u2026","rel":"","context":"In &quot;Cooper&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1634,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1634\/","url_meta":{"origin":3024,"position":4},"title":"An App With View","date":"17 Sep 2013","format":false,"excerpt":"Not a Merchant Ivory production, but Part 3 in the Oxygene for Java camera app for Android series. So far we have seen that we can work directly with the Android platform manifest and layout files and how the Oxygene language is a first class citizen in the Java platform\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2624,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2624\/","url_meta":{"origin":3024,"position":5},"title":"Expressive If and Case &#8230;","date":"25 Apr 2017","format":false,"excerpt":"A quick post on a small but hugely useful little language feature in Oxygene... if expressions. Many people will be familiar with the so-called ternary operator. Delphi developers will also be aware that there is no direct equivalent in Delphi. In 'C' and other languages we can write a statement\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/3024"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=3024"}],"version-history":[{"count":1,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/3024\/revisions"}],"predecessor-version":[{"id":3025,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/3024\/revisions\/3025"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media\/3022"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=3024"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=3024"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=3024"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}