Yesterday I initially posted that you couldn’t mix Unified Syntax with “traditional” interface and implementation sections. Or what I am now calling Segregated Syntax.

As sometimes happens, shortly after writing what I thought I knew to be true I discovered it wasn’t ! Sorry about that. 🙂

I promised to illustrate the scenario where I found it both possible and useful, and here it is.

As I mentioned, I’m working an ASP.NET MVC/WebApi project using Oxygene.

The project employs ASP.NET Identity with Entity Framework for an auth server component in the project. As part of the implementation I am incorporating OAuth middleware with an ‘api/Account‘ end-point in my REST Api to support auth flows including external logins.

Here’s my AccountController declaration:


interface

  type
    AccountController = public class(ApiController)
    private
      property Authentication: IAuthenticationManager read Request.GetOwinContext.Authentication;
      property UserRepo: UserRepository := new UserRepository; readonly;
    private
      method GetErrorResult(identityResult: IdentityResult): IHttpActionResult;
      method ValidateClientAndRedirectUri(request: HttpRequestMessage; var redirectUri: String): String;
    protected
      method Dispose(disposing: Boolean); override;
    public
      method ExternalLoginAsync(provider: String; error: nullable String := nil): Task<IHttpActionResult>;
      method RegisterAsync(user: UserModel): Task<IHttpActionResult>;
    end;


implementation
  
   // the donkey-work is down here as 'usual'

As you can see, although by no means massive, this is still quite a “busy” controller. The implementation details aren’t really relevant to the example. All you really need to know is that a couple of those methods have quite extensive implementations so to keep things clearer I chose in this case to use interface and implementation sections to keep things organised.

One effect this has (and you could argue this as a Good or a Bad thing I guess) is that any attributes on the method implementations are no longer apparent from / cluttering up (depending on your point of view) the class declaration. Using Unified Syntax any such attributes have to appear in the declaration since there is nowhere else for them to go.

Before we move on though, there are a couple of things worth pointing out for people not familiar with Oxygene, specifically in the declaration of the two properties.

First, the Authentication property:


   property Authentication: IAuthenticationManager read Request.GetOwinContext.Authentication;

This demonstrates the use of an expression in the read clause of a property. In traditional Delphi code this would necessitate a separate accessor function. Not so in Oxygene. This has been supported since the very early days of Oxygene (I think as far back as when it was known as Chrome in fact) but in retrospect has a lot in common with the new Unified Syntax now more generally available.

Next up, the UserRepo property:


      property UserRepo: UserRepository := new UserRepository; readonly;

Admittedly this isn’t very modern of me. If I was being fashionable I might be using Ninject or some other IoC framework. Then again, given the small size of this auth project, I might not. But that’s a separate discussion.

For now, let’s just focus on this property as written, and in that two things are a bit odd.

The Curious Case of the Read-Only Property That Was Written

First, instead of a read accessor the property is being directly assigned to in the declaration. And secondly, it is also marked readonly.

The result is that I have a UserRepo property which absolutely is read-only as far as the consumers of my controller class are concerned. Without that readonly directive, the property would be read/write.

To make readonly properties useful there has to be an exception that allows the property to be initialised and in Oxygene that includes a declared initialization (as in this case) or an assignment allowed in any ctor of the class. Both approaches will perhaps be familiar to C# developers.

The Delphi equivalent would involve a member variable and a ctor in addition to the property:


   // ...
   private
     fUserRepo: UserRepository;
   public
     property UserRepo: UserRepository read fUserRepo;
     constructor Create;  // with implementation somewhere down below to initialise fUserRepo;
   // ...

You can of course do effectively the same thing in C#, but there you also have some alternatives. Unfortunately (for C# developers) those alternatives could be something of a minefield since it was decided that the readonly directive can be applied only to member fields not properties.

You could avoid the need for a separate property declaration by using an initialised, readonly field:


   public readonly UserRepository UserRepo = new UserRepository;

This is very close to Oxygene‘s read only properties, except that the resulting member is a field, not a property.

It may be a moot difference in the case of read-only fields, but it is still a difference and doing this sets you up nicely for some lengthy debates about whether this constitutes a valid exception to the House Rules rules regarding exposure and naming of member fields as well as landing you in the clutches of code-analysis tools that will castigate you for directly exposing a member field.

To avoid such wrangles you could of course introduce a property so you can push the member field explicitly back into the private sphere where it belongs, accessed by an implicitly read-only public property (with only a getter) keeping your coding standards police off your back and the code analysis tools quiet.

For the purposes of this exercise I am going to expand the indentation of those braces, just to show how “noisy” this really is:


   private UserRepository _userRepo = new UserRepository(); readonly;
   public property UserRepository UserRepo
   {
       get
           {
               return _userRepo;
           }
   };

Nobody would do that in real life ? Au contraire. I had to contend with a class with a number of such read-only properties declared and laid out in precisely this way only today. I’m still feeling a little traumatised by the experience. 🙂

Save for the elimination of the ctor (assuming that a ctor is not needed for other things) this has more than a passing resemblance to the Delphi original; which perhaps isn’t all that surprising remembering that Delphi in many ways directly begat C#.

But, back to the mix-in of Unified and Segregated Syntax.

Mixing Things Up In

As part of the implementation of the ExternalLoginAsync() method, I needed a new class to encapsulate some data pertinent to the external login process. This class would be essentially a POCO albeit adorned with a simple factory method. Significantly, it was to be entirely private to the implementation of the AccountController.

As such I didn’t see the need for a separate unit and decided to place the new class in the implementation section of the existing AccountController unit.

But it bothered me that the quite straight-forward factory method was the only code involved in this class and breaking that out into a separate implementation body (in accordance with Segregated Syntax) irked me in this case.

Fortunately of course, my irk was unfounded and I was able to do this:


interface

  // .. the AccountController declaration is here ..

implementation

  type
    ExternalLoginData = class
    public
      property LoginProvider: String;
      property ProviderKey: String;
      property UserName: String;
      property ExternalAccessToken: String;

      class method FromIdentity(identity: ClaimsIdentity): ExternalLoginData;
      begin
        // manufacture happens here...
      end;
    end;


  // .. the AccountController implementation is here...


end.

A bit of further experimentation lead me to also identify that you can mix-in even within the same class.

So in the case of the AccountController itself I could keep the complex implementation details carefully coralled in the implementation section, but bring some of the trivial scaffolding up into the declaration in the interface section.

The Dispose() method override is a potential candidate for just that:


interface

    type
    [Authorize]
    AccountController = public class(ApiController)
    private
      property Authentication: IAuthenticationManager read Request.GetOwinContext.Authentication;
      property UserRepo: UserRepository := new UserRepository; readonly;
    private
      method GetErrorResult(identityResult: IdentityResult): IHttpActionResult;
      method ValidateClientAndRedirectUri(request: HttpRequestMessage; var redirectUri: String): String;
    public
      method ExternalLoginAsync(provider: String; error: nullable String := nil): Task<IHttpActionResult>;
      method RegisterAsync(user: UserModel): Task<IHttpActionResult>;

    protected
      method Dispose(disposing: Boolean); override;
      begin
        if disposing then
          UserRepo.Dispose;
      end;
    end;


implementation
  
   // etc etc, including the method bodies for those not implementing in the Unified Syntax

So there you have it.

Instead of handing down tablets of syntax and strait-jacketing the developer, Oxygene now grants the freedom to use, ignore or (let’s face it) abuse this particular aspect of the syntax in an impressively flexible and intuitive (or at least very natural-feeling) manner.

As I said before, although I was initially skeptical of the very idea of Unified Syntax it has very quickly become one of my favorite features of Oxygene.

4 thoughts on “Mix-in Unified and Segregated Syntax: An (Extended) Example

  1. It all started out innocently enough. I wondered whether it would be possible to make a method visible outside of a unit by simply tagging it ‘export;’ in the implementation section. That way, instead of having to parallel-maintain the interface section, you could switch the method between being visible and not with a single keyword.

    Now – hold on. If we were to do that, why not everything else that may occur within the interface section? Constants, classes, types, variables – all with the same methodology – just a strategically-placed keyword, and there’d be no further need for the interface section at all, and the implementation section would be implicit.

    Come to think of it, why do we need procedure and function? A procedure is merely a function that doesn’t return a type – and the returned type doesn’t need to be assigned or used nowadays. Why not call them all “methods” and let the parser figure out the implementation details. If the signature includes a return type, implement as a function, if not then as a procedure.

    Sure, retain compatibility with existing code by insisting that if the procedure keyword is used, then there can be no return type, but the type must be specified for a function.

    And then, why do we need “overload”? Overloaded methods all require different signatures, so what does “overload” add? Deprecate it! Exported overloaded methods need a Name clause – case-sensitive to suit “C” and default exported-named methods to stdcall…

    Oh – wait. We can’t have multiple “uses” – why not? All uses does is to include names exported from existing modules. There’s no logical reason to not allow many of them – the redeclaration logic should detect any attempt to implement multiple instances of the same name.

    So – now the objection is controlling the re-export of elements from a “used” module? Go back to the “strategically-placed keyword” idea. Now it’s controlled.

    I naively suggested such changes be made. Piecemeal, I thought – easily-digested bites. “Non-events” was the description used. “Frivolous bug reports”.

    To the terminally myopic, yes. Getting some easy trivial clutter out of the way before tackling the bigger issues to ensure that the inevitable howl of “it’ll break all our existing code” can be tackled head-on rather than having to fight a thousand side-issues.

    For instance “case” is essentially a convenient abbreviation for “if then else if then else…”. Why can’t it be applied to strings and any other type for which “=,>,<" are valid operators? Because you shouldn't compare floating-point. Well, use the full-form : You shouldn't compare floating-point UNLESS YOU KNOW YOUR DATA". Made worse by the faulty implementation of comparison operators for singles ("And we won't fix that because you shouldn't compare floating-point") – so why not for strings? Oh "because we haven't done it before" or "because the documentation says it can't be done".

    Sadly, the naysayers can obstruct any ideas about syntax-modification. It's more than a sad lack of imagination. It's wanton obstruction because "we are in control, we didn't think of that, we can describe the change as pointless or trivial or code-breaking or impossible or not-according-to-our-definition (justification not required), but most of all, we can simply ignore you".

    1. For those unaware, I think everything that Peter is railing against is long-since addressed in Oxygene (some of it only more recently, with Unified Syntax). 🙂

      They say Oxygene isn’t “your grand-daddy’s Pascal”. It’s also not your Daddy’s Delphi. 🙂

    2. Isn’t it stemming from those UNITs ( and PACKAGEs in Delphi ) being some separate beast of its own breed?

      UNITs were conceived in pre-OOP Turbo Pascal 4.0 and today they stand out in a way.

      For example the very thing that Delphi Packages to expose ALL content of interface sections of its units is unlucky.

      Personally i feel like id someone wants to re-create Delphi/Pascal syntax, one of low hanging fruits would be to unify package/unit concepts with classes. Then interface/implementation sections become published/public/private visibilities. And then USES and WITH are becoming synonyms of each other.

      I feel that Java and post-Java languages went correct path here and Delphi just got left anchored behind.

      1. aiui that’s exactly what has happened with interface and implementation in Oxygene. They are supported as remnants of the old Pascal in the same way that you can (redundantly) discriminate between functions or procedures as well as simply using methods that either do (functions) or do not (procedures) have return values.

        But the differences in visibility imposed by interface and implementation sections can be provided in Oxygene more directly as well (private vs public types, just like C# et al). Just because a class is (was) declared in the “interface” of an Oxygene unit did not mean it was publicly accessible.

        In the terms you used I guess you could say that Oxygene is a “Post-Java Pascal“. 🙂

Comments are closed.