Amazon.com Widgets Nick Hodges | A man's got to know his limitations

In Which I Argue That Embarcadero Should Open Source Their Unit Tests

By Nick at July 27, 2013 04:27
Filed Under: Software Development, Delphi, Unit Testing

All good developers write unit tests.  The Delphi team is no different.  The team has a suite of unit tests for the RTL and a very, very large set of tests for the compiler.  The tests for the RTL are, to a large degree, DUnit based.  The compiler tests are a bit different, as they date back well before DUnit even existed.  They are a set of console applications that write out PASS or FAIL to the standard output depending on whether the test passed or failed. I believe that this suite of tests also tests a lot of the lower level RTL.   I know the QA team doesn’t like to test the RTL using a tool that depends heavily on the RTL itself.

So anyway, this suite of tests exists.  They get run constantly as part of a continuous integration process at Embarcadero.  And the suite gets expanded as time goes by.  When I managed the R&D team, I even contributed to the test suite myself.

But given that you can’t ever have enough unit tests, and that like all companies, Embarcadero has limited resources, the test suite doesn’t expand fast enough.  (Actually, I suppose no test suite expands fast enough, right?)

So I have a plan:  Embarcadero should open source their unit test suite and accept inputs from the community. 

Here’s why I think they should do that.

  • It will enable the community to expand the suite of tests -- As I noted above, every unit test suite is too small and doesn’t cover enough of the possibilities.  Embarcadero can continue to expand their test suite by themselves, or they can harness the power of the community to write tests.  The current public code repositories allow for forking and pull requests, and it would be dead simple for me or anyone to fork the project, add tests, and then issue a pull request.  This will allow people to write tests for their favorite parts of the RTL, and as will be discussed below, allow them to report bugs by writing tests that should pass but fail.  Many hands make for light work.
  • It will help build customer confidence in the quality of the Delphi RTL –A public facing, expanding suite of tests with community participation will build confidence in the quality of the product.  If people know and see that the RTL and the compiler are bathed in a complete, growing suite of tests, they’ll feel better about the product.  If they see how thorough and complete the suite is, they’ll know that the product they use is solid.
  • It will help people learn the proper way to use the product – One of the things that unit tests can do is to provide a sort of “documentation” for the things being tested.  They can illustrate the proper way to use the RTL code, and show customers the things that can be done that they might not have known about.  A nice suite of tests for a new RTL unit or class will help customers see how to use the class and what it is supposed to do.
  • It will encourage the team at Embarcadero to write more tests – When Lee Ioccoca took over a failing Chrysler in the late 1970s, one of the first things he did was throw down the gauntlet in front of the company: He would give all buyers a 10 year, 100,000 mile warrantee for the car.  That was an impetus to the entire company to improve quality.  Publishing the compiler and RTL test suites will have the same effect on the team at Embarcadero.  If the tests are public, then the team will feel the pressure (the good kind) to ensure that any new code has tests.  The community won’t want to see a new RTL unit without any tests (Will we, guys, right?)
  • It will enable people to report bugs in a better and more useful way – The easiest kind of bug to fix is one with a failing unit test.  If things got really rolling, customers could write unit tests that reveal bugs, Embarcadero could fix the bugs, and then the test would be a true regression test.  That would be awesome.  Customers could even use the tests to suggest fixes.  Having all the tests would enable them and Embarcadero to be more confident in a suggested fix.

I could think of some objections that they might have.  Here are some of those objections, along with reasons why those objections should be ignored. 

  • “The code isn’t ready for public consumption” – No one cares.  Seriously.  Anyone in the community that complains about the quality of the tests or lack of coverage can get to work and fix things.  No complaining if you aren’t helping.  The tests are probably better than most, and even if they are bad, they’ll get fixed. 
  • “It’s too much work for us” – No it isn’t. “We don’t have the time.” Yes you do.  It shouldn’t take more than an hour to gather the tests and post them on BitBucket or GitHub.  (Please, not SourceForge.  And by the way, whatever you do – for the love of Baby Elvis  -- don’t post it in Subversion. Only Git or Mercurial will allow for the community involvement you want and need.).  Plus, that small investment will enable an army of developers to submit pull requests with new tests.  Those tests can be quickly reviewed and accepted.  It will take less time to accept tests than it will to write them.  Shoot, you could even enlist trusted community members to help out.  I can think of at least one Embarcadero MVP (cough, me, cough) that would be willing to help be a gatekeeper.
  • “This is internal, private stuff that we shouldn’t be sharing”.  No, this is exactly the kind of stuff you should be sharing.  There are no trade secrets here.  The tests are useless without the products.  There is nothing to be lost by doing this, and much to be gained.  This is the kind of thing that a modern, forward-looking company would do.  Be a leader.  Be brave and bold!

I thought long and hard for reasons why Embarcadero shouldn’t open source their tests, and I couldn’t think of any.  Seriously, I can’t think of a downside here.

So how about it, guys?

Service Locator is Indeed an Anti-pattern

By Nick at June 06, 2013 00:20
Filed Under: Delphi, Patterns, Software Development, Unit Testing

As you know, I love Dependency Injection.  I wrote a whole series of articles on it using the Spring for Delphi framework, and in my previous position instituted its pervasive use in the large project there. I’m scheming to integrate it into the legacy app I work on now.  I bought and read the definitive book on the subject:

But there was always one thing that bugged me -- In Mark Seemann's book and in this article (Service Locator is an Anti-pattern) he argues against the use of a ServiceLocator – that is, a class that grabs instances out of the DI Container and hands them to you for your use.  I never really agreed, as I didn’t see any other way to do it – of course you needed to grab instances out of the container via a Service Locator pattern.  How else would you do it? I mean, you can do Constructor Injection and all, but at some point you need to grab an instance of something, right?  I had read his stuff, read the comments and arguments on the topic, but was never really persuaded.  But then again, maybe I was missing something.  The question of “how” always held me back.

Well, I was working on some demo code for my book, and out of the blue, all of a sudden, it hits me:  Seemann is right.  The ServiceLocator is an anti-pattern, mainly because it is pretty much unneeded. 

Here’s what happened. 

First thing: if you go to my demo code on BitBucket, you’ll see a Dependency Injection demo there that uses the ServiceLocator to grab instances of registered classes.  It’s cool – you can understand the basics of DI by looking at it.  You can properly decouple the code and end up with nothing but a unit of interfaces in your uses clause.  Nice.  I even did a CodeRage presentation using this basic code.  That code illustrates how you can use a DI Container and the ServiceLocator to create loosely coupled code.  No worries.  However, you’ll notice that the calls to the ServiceLocator kind of become replacements for calls to Create

Only you can do the same thing with no ServiceLocator calls. 

Second:  The Delphi Spring Container has a set of methods that I confess I never quite understood:

 

    function InjectConstructor(const parameterTypes: array of PTypeInfo): TRegistration<T>; overload;
    function InjectProperty(const propertyName: string): TRegistration<T>; overload;
    function InjectMethod(const methodName: string): TRegistration<T>; overload;
    function InjectMethod(const methodName: string; const parameterTypes: array of PTypeInfo): TRegistration<T>; overload;
    function InjectField(const fieldName: string): TRegistration<T>; overload;

 

These methods allow you to inject (duh) different items into your classes and automatically instantiate them as a result.  I knew they were there, I knew that they were useful, but I never understood completely why they were in there.  You could pretty much get along without them because you had the ServiceLocator to grab anything you need.  

I was reading Mark Seemann’s book again, and reading about how you should be using constructor injection everywhere, and how you need to push the creation of your component graph all the way back to the composite root. In Delphi, that means all the way back to the first line of the DPR file.  And if you do that, you could end up with this monster constructor that requires every single class your application needs.  And it was this notion that made me think “The ServiceLocator is necessary to get rid of that huge constructor.”

So I confess I never quite got it. 

But yesterday, I’m working on sample code for my book, and of course, I have to show how the above methods work.  I’m working up demos (I’ll show a simple one below that illustrates the whole thing) and it hits me:  The key to the whole notion of a ServiceLocator being an anti-pattern lies in what these five methods can do. 

And basically what they can do is this:  They can cause the creation of every single class needed for your application during the registration process.  They can completely eliminate the need for you to ever call the ServiceLocator (with one exception, discussed below) because if you can call the ServiceLocator, you can use these methods to register the connection between what you need the ServiceLocator for and the registration process.

Put another way, every call to the ServiceLocator can be replaced by a registration call.  You don’t need the ServiceLocator because the registration process alone is enough.

So I think a simple example is in order.  I’ll try to keep it short and sweet. 

Consider the following unit of code:

unit uNoServiceLocatorDemo;

interface

uses
      Spring.Container
    , Spring.Services
    , Spring.Collections
    ;

type
  IWeapon = interface
  ['{0F63DF32-F65F-4708-958E-E1931814EC33}']
    procedure Weild;
  end;

  IFighter = interface
  ['{0C926753-A70D-40E3-8C35-85CA2C4B18CA}']
    procedure Fight;
  end;

  TBattleField = class
  private
    FFighter: IFighter;
  public
    procedure AddFighter(aFighter: IFighter);
    procedure Battle;
  end;

  TSword = class(TInterfacedObject, IWeapon)
    procedure Weild;
  end;

  TKnight = class(TInterfacedObject, IFighter)
  private
    FWeapon: IWeapon;
 public
    constructor Create(aWeapon: IWeapon);
    procedure Fight;
  end;

implementation

{ TBattleField }

procedure TBattleField.AddFighter(aFighter: IFighter);
begin
  FFighter := aFighter;
end;

procedure TBattleField.Battle;
begin
  WriteLn('The Battle is on!');
  FFighter.Fight;
end;

{ TKnight }

constructor TKnight.Create(aWeapon: IWeapon);
begin
  inherited Create;
  FWeapon := aWeapon;
end;

procedure TKnight.Fight;
begin
  WriteLn('The knight swings into action!');
  FWeapon.Weild;
end;

{ TSword }

procedure TSword.Weild;
begin
  WriteLn('"Swoosh" goes the sword!');
end;

initialization

  GlobalContainer.RegisterType<TSword>.Implements<IWeapon>('sword');
  GlobalContainer.RegisterType<TKnight>.Implements<IFighter>('knight');


end.

 

Here we have some classes that are all nicely decoupled.  Our registrations are neatly named.  The classes use constructor injection to ask for their dependencies, and the TKnight and the TSword are nicely registered, just waiting to be grabbed and used in a decoupled way using the ServiceLocator.  All is great.  And then in order to actually have our cast of characters do anything, you might do something like this:

 

procedure FightBattle;
var
  Battlefield: TBattleField;
  TempKnight: IFighter;
  TempSword: IWeapon;
begin
  Battlefield := TBattleField.Create;
  try
    TempKnight := ServiceLocator.GetService<IFighter>;
    TempSword := ServiceLocator.GetService<IWeapon>;
    TempKnight.Weapon := TempSword;
    Battlefield.AddFighter(TempKnight);
    Battlefield.Battle;
  finally
    Battlefield.Free;
  end;
end;

 

You need a knight and a sword?  Well, just call the ServiceLocator, grab the sword, arm the knight, add him to the battle, and off it goes.  You get this:

image

 

It all works, and it is all decoupled.  But you are still using the ServiceLocator

The argument against the ServiceLocator is pretty simple: It’s a singleton, singletons are global variables, and global variables are bad. (That’s a gross oversimplification – read the article and the comments for a better discussion….) Plus, if you don’t need it, why use it?

Well, you don’t need it.  Watch.

First thing to note is that Seeman says you should have one call to the ServiceLocator at the very root of your application.  You get one shot.  We’ll see that one shot below.

Second, let’s change how we register our classes and interfaces: 

 

 GlobalContainer.RegisterType<TBattleField>.InjectMethod('AddFighter', ['knight']);

  GlobalContainer.RegisterType<TSword>.Implements<IWeapon>('sword');
  GlobalContainer.RegisterType<TKnight>.Implements<IFighter>('knight').InjectConstructor(['sword']);

 

Some things to note:

  • We only changed the way things were registered.  We didn’t change the class structure or relationships at all.
  • We are now registering TBattlefield.  We need to do that for two reasons.  First, in our very simple example, it is the “root” of the application.  It is the place where everything starts in relation to our object graph.  To get an instance of TBattlefield, we make our one allowable call to ServiceLocator.  Second, we need to inject a method, as discussed next.
  • Into TBattleField we have injected a method, specifically the AddFighter method.  Here’s what the call to InjectMethod does -- it says “When the container creates an instance of TBattlefield, look up the AddFighter method and pass to it as its parameter an instance of the interface named ‘knight’”  Thus, when the container creates an instance of TBattleField for you, the AddFighter method will be automatically called, and a valid weapon will be passed to it.  There goes one call to the ServiceLocator
  • The second call to ServiceLocator is eliminated by the call to InjectConstructor.  This registration now means “When you ask for an IFighter, create an instance of TKnight, and when you do, pass the constructor an IWeapon from the registered type named ‘sword’”  Again, there goes the other call to ServiceLocator

Thus we’ve used the container to “wire up” all the dependencies and ensure that they are properly created before the main class or any other class is even asked for.  The call to GlobalContainer.Build in the DPR file will ensure this takes place. 

Finally, we run everything with the much simpler and cleaner:

 

procedure FightBattle;
var
  Battlefield: TBattleField;
begin
  Battlefield := ServiceLocator.GetService<TBattlefield>;
  try
    Battlefield.Battle;
  finally
    Battlefield.Free;
  end;
end;

 

And there’s our one call to ServiceLocator at the very root of our application (FightBattle gets called in the DPR file as this is a console application). 

You can do the same thing with constructors – you can call InjectConstructor, passing the names of registrations for each of the parameters in the constructor.  And if need be, for both InjectConstructor and InjectMethod, you can add in non-registered parameters such as integers and strings, etc.

Bottom line:  Use the injection methods and the container to connect up your classes and inject dependencies, not the ServiceLocator. 

And I haven’t even yet mentioned how you can replace the InjectXXXXXX calls with attributes. 

Okay, now I feel better since I agree with Mark Seemann over at http://blog.pleoh.dk.  Being in disagreement with a smart guy like that isn’t a comfortable place to be. 

THMTLWriter and XE4

By Nick at May 18, 2013 00:55
Filed Under: Delphi

I’m happy to say two things:

  • I’m still alive.  I can’t believe that it has been over two months since I posted. I have been working on my book, but it is sure slow going.  Writing is hard, as my wife says.
  • THTMLWriter works great with Delphi XE4. I’d be delighted to hear from you if you are using it.  And if you haven’t given Delphi XE4 a look, please do.  And use that link up there.  Please.

Flotsam and Jetsam #81

By Nick at March 01, 2013 07:36
Filed Under: Flotsam and Jetsam, Delphi
  • Embarcadero has revealed their plans for AnyDAC – and it is called FireDAC after all.  Marco blogged about it and has all the links.  Looks like all XE Enterprise developers get it as an upgrade/add-on, and Pro users can buy it for $399. 
  • I upgraded this site to BlogEngine.net 2.7.0.0.  It all seems to be well, but if you notice any glitches, broken links, missing graphics, or if one of your comments got lost in the shuffle, please let me know.
  • I can cross an item off my bucket list – I was honored by a mention in the Odd Lots column of the inestimable Jeff Duntemann.  I’ve been a fan for years, and was thrilled to get the mention. 
  • One final note:  There’s going to be less content here in the coming months. I’m going to put my patterns series on hold, and pretty much everything else I can spare, in order to work on my book.  I’ll be keeping up the F&J stuff – these are pretty painless – but the heavier content stuff won’t be happening as I work on my book.  Let me know if you want to help via codingindelphi@nickhodges.com and stay tuned for updates, etc.  And please feel free to let me know what you think over at the LeanPub site

Want to Help With My Book?

By Nick at February 26, 2013 13:08
Filed Under: Delphi

As you hopefully know, I’m working on a book.  I’m slowly but steadily making progress.  I’m at the point where I need some help.  I’ve gotten the first few chapters in a state that I feel ready to actually let someone else read them.

So if you are feeling generous, want to feel my undying gratitude, want to be mentioned in the Acknowledgements, and maybe even get a free copy, you can start technical editing!  If you are willing to provide some real and honest feedback on the first three chapters, knowing that things are still in a very early state, please email me at codingindelphi@nickhodges.com, and I can deliver the book to you in almost any form that you need. (Formatting, etc., is the least of my worries at this point……)

So, if you are interested, please let me know.  All help will be gratefully received. 

Delphi and the Factory Pattern: Factory Methods

By Nick at February 24, 2013 11:16
Filed Under: Delphi, Patterns

I’m currently reading “Head First Design Patterns”, and am finding it very useful and educational.  One problem, though – it’s all in Java.  So I thought that as part of the exercises, I’d translate the code to Delphi.  And also as part of my learning process, I thought it would be a good idea to post an article about each of the patterns.  I also strongly encourage you to buy the book and read it for yourself.

Let me be clear – I’m not doing much more than reproducing the demos in the book.  My purpose is to make the book more approachable for Delphi developers.  The result isn’t always the perfect way to do the pattern since the samples from the book are designed to be as simple as possible to illustrate the point.  I’m very aware that there are better ways to implement the patterns than are shown here.

Introduction

In the first of three posts about the Factory Pattern, we looked at the “Simple Factory” pattern and how it can be used to sequester off your calls to create things.  HFDP didn’t rank the Simple Factory as a full-fledged pattern, but gave it an “Honorable Mention”.  Either way, it’s an effective technique to remove the notion of creating things from your worker classes.  Classes should only do one thing, and Factories do the one thing of creating dependencies so your other classes can do their one thing.

The reason that HFDP doesn’t make the simple factory a full fledged pattern is that they believe it isn’t robust enough to handle variations of the pattern.  It’s great if you have one pizza store.  However, if you want to open a new kind of pizza store – say a store in New York that serves New York-style pizza and then one in Chicago which will server Chicago-style pizza – then you are going to have some seriously ugly case or if statements. 

Branching out to New Pizza Styles

Okay, so the next step is to have different kinds of Pizza depending on where the store is (or, I suppose, the kind of clientele you want to attract, but we’ll just go with regional differences).  First we’ll need a pizza store that can adapt to the different kind of pizzas that the store will need to make. 

Thus we’ll add an abstract  method to TPizzaStore that will create the pizza for us in the descendent classes

  TPizzaStore = class
  protected
    function CreatePizza(aPizzaName: string): TPizza; virtual; abstract;
  public
    function OrderPizza(aPizzaName: string): TPizza;
  end;

The CreatePizza function is abstract, so descendent stores will have to implement it.  That way, each store will get to decide what kind of pizza it will make.  The OrderPizza method makes sure that all pizzas are handled in the same way, but the actual creation will be delegated to the descendent class via CreatePizza.

This is where the factory method part comes in – the TPizzaStore is an abstract class that let’s its descendant decide what kind of pizza it will create.  The call to OrderPizza becomes a “Factory Method”, determining which pizza will be created and thus how each pizza will be prepared.

Next, we’ll create a number of different pizzas that will be created by the specific factory methods.  We’ll create a cheese, pepperoni, clam, and veggie pizza for both the New York and Chicago styles.  (Creating at California-style set of pizzas is left as an exercise for the reader). 

TNewYorkCheesePizza = class(TPizza)
    procedure Prepare; override;
  end;

  TNewYorkPepperoniPizza = class(TNewYorkCheesePizza)
    procedure Prepare; override;
  end;

  TNewYorkClamPizza = class(TNewYorkCheesePizza)
    procedure Prepare; override;
  end;

  TNewYorkVeggiePizza = class(TNewYorkCheesePizza)
    procedure Prepare; override;
  end;

  TChicagoCheesePizza = class(TPizza)
    procedure Prepare; override;
    procedure Cut; override;
  end;

  TChicagoPepperoniPizza = class(TChicagoCheesePizza)
    procedure Prepare; override;
  end;

  TChicagoClamPizza = class(TChicagoCheesePizza)
    procedure Prepare; override;
  end;

  TChicagoVeggiePizza = class(TChicagoCheesePizza)
    procedure Prepare; override;
  end;

You can see the code on BitBucket for the specific implementations of the Pizza classes.  They override some of the methods to provide specific implementations for preparing the pizzas.  For instance, Chicago pizzas are cut in squares and use mozzarella cheese. 

Once the pizzas are available for creation, the specific pizza stores can be created. Below is the declaration and implementation of the TNewYorkPizzaStore.  (The TChicagoPizzaStore looks pretty much identical, except of course that it creates Chicago-style pizzas.)  It uses the OrderPizza method to decide what kind of pizza to create.  Inside OrderPizza is the call to CreatePizza which will get the appropriate pizza type.   Thus, it is a perfect example of a factory method which created things that you need. 

type
  TNewYorkPizzaStore = class(TPizzaStore)
  protected
    function CreatePizza(aPizzaName: string): TPizza; override;
  end; 

... 

function TNewYorkPizzaStore.CreatePizza(aPizzaName: string): TPizza;
begin
  if aPizzaName = 'cheese' then
  begin
    Result := TNewYorkCheesePizza.Create('New York Cheese Pizza');
  end else
  begin
    if aPizzaName = 'pepperoni' then
    begin
      Result := TNewYorkPepperoniPizza.Create('New York Pepperoni Pizza');
    end else
    begin
      if aPizzaName = 'clam' then
      begin
        Result := TNewYorkClamPizza.Create('New York Clam Pizza');
      end else
      begin
        if aPizzaName = 'veggie' then
        begin
          Result := TNewYorkVeggiePizza.Create('New York Veggie Pizza');
        end else
        begin
          raise Exception.Create(aPizzaName + ' is an unknown pizza');
        end;
      end;
    end;
  end;
end;

We still have a great big ugly if statement (There doesn’t seem to be a way to get around that, eh?) but the subclass is the class that decides what kind of pizza gets made.   The TPizzaStore class has no idea what kind of pizza is going to get made when the OrderPizza method is called, which in turn uses the CreatePizza method to return the proper kind of pizza.  That’s the Factory Method pattern to a ‘T’.

So to sum up:  we have an abstract pizza store class that defines how pizzas are ordered and created without knowing what kind of pizza will be created.  The concrete descendants determine what kind of pizzas get created via a factory method – in this case, CreatePizza.

Finally, we can actually create some pizzas using Factory Methods:

procedure MakeMethodPizzas;
var
  ChicagoPizzaStore: uFactoryMethodPizzaStore.TPizzaStore;
  NewYorkPizzaStore: uFactoryMethodPizzaStore.TPizzaStore;
  Pizza: uFactoryMethodPizzaStore.TPizza;
begin
   ChicagoPizzaStore := uFactoryMethodPizzaStore.TChicagoPizzaStore.Create;
   try
     Pizza := ChicagoPizzaStore.OrderPizza('cheese');
     Pizza.Free;
     WriteLn;
     Pizza := ChicagoPizzaStore.OrderPizza('pepperoni');
     Pizza.Free;
     WriteLn;
   finally
     ChicagoPizzaStore.Free;
   end;

   NewYorkPizzaStore := uFactoryMethodPizzaStore.TNewYorkPizzaStore.Create;
   try
     Pizza := NewYorkPizzaStore.OrderPizza('cheese');
     Pizza.Free;
     WriteLn;
     Pizza := NewYorkPizzaStore.OrderPizza('clam');
     Pizza.Free;
     WriteLn;
   finally
     NewYorkPizzaStore.Free;
   end;
end;

 

The pizza store types are prefaced with their unit identifiers to keep them distinct from the pizza class from the abstract factory demo that we’ll see in the next installment of the Factory Pattern demos.

That’s the Factory Method Pattern – you create an abstract class and then descend from it to implement a method for creating the right class.

Next time, we’ll look at how you can create an entirely separate interface for completely abstracting the notion of creating things.

Fun Code of the Week #7

By Nick at February 24, 2013 00:08
Filed Under: Fun Code, Delphi

It’s all a big circle.

First, I posted a fun little way to handle the cursor in this Fun Code of the Week.

The first comment on that post was from my friend Tapper who said “What, no interface?”

Then, I post this about hints revealing errors with cursor handling as part of the demo.

And from that, we get a comment by Leif that I’m making Fun Code of the Week

So Tapper is happy, and we all have about three ways to handle the cursor. 

Wins for everyone!

 

unit CursorHandler;

interface

uses
      Controls
    ;

type
  ICursor = interface(IInterface)
  end;

function AutoCursor(const aCursor: TCursor): ICursor;

implementation

uses
  Forms;

type
  TAutoCursor = class(TInterfacedObject, ICursor)
  private
    FCursor: TCursor;
  public
    constructor Create(const aCursor: TCursor);
    destructor Destroy; override;
  end;

function AutoCursor(const aCursor: TCursor): ICursor;
begin
  Result := TAutoCursor.Create(aCursor);
end;

constructor TAutoCursor.Create(const aCursor: TCursor);
begin
  inherited Create;
  FCursor := Screen.Cursor;
  Screen.Cursor := aCursor;
end;

destructor TAutoCursor.Destroy;
begin
  Screen.Cursor := FCursor;
  inherited;
end;

end.

Even Hints Can Reveal Errors

By Nick at February 23, 2013 06:00
Filed Under: Software Development, Delphi

Introduction

I hope that you all know that when you do a full build on your Delphi project, you should never allow hints and warnings to remain in your code.  Warnings, in particular, are an indication that something is going on that you almost certainly don’t want to be going on.  But what about hints?  Hints can’t really be a problem, can they?

Well, yeah, they can definitely point to something happening that you don’t want to happen – or in the case below, of something not happening that you do want to happen. 

The Situation

Let’s say you are maintaining an older Delphi application and you run across some code that looks like this:

begin
  Screen.Cursor := crSQLWait;
  // A bunch of database code that might make
  // the user wait
  Screen.Cursor := crDefault;
end;

And naturally you think “Oh my, that will never do.  What happens if an exception occurs in that database code! The cursor might be stuck!  That needs a try…finally block around it!”.  And so you do the following:

begin
  Screen.Cursor := crSQLWait;
  try
  // A bunch of database code that might make
  // the user wait
  finally
    Screen.Cursor := crDefault;
  end;
end;

And that’s better, but something is still nagging at you, and it suddenly hits you – "what if the cursor wasn’t actually crDefault to start with?  Shouldn’t you restore the cursor to whatever it was before you started?”  So you are feeling a bit cocky and you proceed with a bit too much haste and you do this:

var
  OldCursor: TCursor;
begin
  OldCursor := Screen.Cursor;
  Screen.Cursor := crSQLWait;
  try
  // A bunch of database code that might make
  // the user wait
  finally
    Screen.Cursor := crDefault;
  end;
end;

But like I said, you are feeling a bit cocky, and you think “I’ll be this is all over the place” and you search for similar code patterns and you are right and you go off and fix this “omission” that is scattered all over your codebase.  Things are great, right? 

Finally you compile and there is a <shudder> hint in your code! 

[dcc32 Hint] Unit5.pas(29): H2077 Value assigned to 'OldCursor' never used

and you’re like “Whaaat?  It’s just a silly hint, who cares!”.  But of course, your conscience is nagging at you, and you remember that Nick told you to not allow any hints or warnings, not even stupid hints like this one, and you suddenly realize that your code has an <another shudder> bug in it and it is not doing at all what you wanted and intended for it to do.

And of course, you fix the subtle bug of forgetting to actually set the cursor back to its original value:

var
  OldCursor: TCursor;
begin
  OldCursor := Screen.Cursor;
  Screen.Cursor := crSQLWait;
  try
  // A bunch of database code that might make
  // the user wait
  finally
    Screen.Cursor := OldCursor;  // <--- forgot this part
  end;
end;

And then you think “Dang, that Nick dude was right!  Hints really can indicate problems”, and you never let another hint slide for as long as you live.

And of course, I should say that I totally made this scenario up, and that I would never, ever, ever do anything like that.  Nope, not me.  Nope.  No way. Neeeever happened.

Flotsam and Jetsam #80

By Nick at February 22, 2013 00:04
Filed Under: Flotsam and Jetsam, Delphi
  • Despite all my slaving over a hot keyboard, bringing you a never ending supply of intellectually stimulating and hopelessly useful content, in the entire history of this website, no one has ever donated to me via PayPal.  And there is a reason for that – the stupid donate button doesn’t work.  Well, I fixed it.  Or at least I think I did. 
  • And now, you can donate Bitcoins to me as well!  Just click on that little blue button on the right that says “Donate Bitcoins”.  Hey, hope springs eternal!
  • I think by now pretty much everyone in the Delphi community knows that Embarcadero has acquired AnyDAC.  I’m pleased by that, and I think you should be, too.  Anyway, it looks like they are going to rename it “FireDAC”.  I like that name.  And according to that link, you’ll be able to download it for XE3.  Just another reason to upgrade to the latest version of RAD Studio XE3. (It appears that this page on the wiki has now been removed.  Hmmm…..)
  • Tim Anderson has an interesting article about cross-platform development and the different strategies a framework can take towards producing a user interface for each platform.  I mention it because he discusses FireMonkey in it. 
  • Jeroen pointed out this cool table that has all the Delphi compiler defines for each specific version.  Nice.

Review of the Mobile Preview Webinar

By Nick at February 21, 2013 08:53
Filed Under: Delphi

I watched the RAD Studio Mobile Preview Webinar today.  Anders O, JT Thomas, Marco, and Sarina DuPont did a very nice job presenting the product, including some pretty cool demos.  Here are my thoughts in my ever-present bullet form.  Everything here is from notes I took during the webinar.

  • First, the webinar was today, and it hasn’t been put up on the web for general consumption yet.  They said that would happen soon.  I’ll make sure to point to it when it is up.
  • Overall, this is very, very impressive.  I really thought it was cool.  It appears that Embarcadero has really made developing for iOS easy and very “Delphi-ish”.  I don’t own any Apple products, but I must confess that this tool might make me jump on the bandwagon (though I am most looking forward to the Android side of things – see below….)
  • The IDE looked great.  The designer works just like the Windows designer you know and love. They showed using FireMonkey in a very nice looking designer with a cool graphic of an iPhone.  You can even choose a “palette” of iPhone 4, iPhone 5, or an iPad and the designer adjusts and looks just like the device.  You can rotate the designer to see how things will render at any orientation. 
  • The styling and controls looked very “iPhone-ish” to me.  I’m not an expert, but it looks like they’ve gone to a large effort to make an iOS-based Fire Monkey app look perfect on an iPhone.  I couldn’t tell exactly how native controls entered into things, but they definitely mentioned that the calendar control and the list box control were native controls.   There were countless styles for the buttons, tabs, and other controls that made everything look like apps on the iPhone/iPad are supposed to look. 
  • This question got asked about 400 times, and the team was very patient in answering it each time.  You need a Macintosh computer to develop and deploy on iOS. I repeat, you need a Mac.  There is no way around this. This isn’t a technical requirement – it’s the rules according to Apple.  They only allow deployment using a Mac and xCode, and so Embarcadero has to honor that.  Further notes in this area:
    • This doesn’t work like Kylix did -- the RAD Studio IDE runs in Windows and Windows only.  It can run in BootCamp or Parallels on the Mac.
    • They said that a MacMini will work fine.  I don’t know much about OS X, but they said that you’ll need at least Lion to run things.
    • Debugging happens via a server on the mac that talks to the IDE over TCP/IP.  You debug in the IDE (on Windows) just like you normally do.
    • Yes, you can develop in Windows on the Mac via a virtual machine, and deploy and run in the same Mac. 
    • You can’t run the simulator on Windows as Apple doesn’t have a simulator that runs on Windows.
    • You can’t run OSX in a virtual machine on Windows because Apple doesn’t allow that – you can only run OSX on Apple hardware.
    • Sarina deployed both to the simulator and her actual device (though her device was emulated on the screen by an app designed to do that – she did hold it up to take a picture and you can see that in the presentation…….)
  • Database access was interesting and appeared to be very much what we’d expect it to be.
    • Marco demonstrated a clientdataset hooking  up to a local file.  Then he demoed the dbExpress controls talking to both SQLite and Interbase ToGo locally – that is, to the DB itself residing on the device.  Or at least that was how I understood it.
    • Having TClientDataset on mobile devices is very cool.  I presume this means that the providers will work and allow you to talk to a DataSnap server.  That could be very powerful and cool.  I can see this being a cool thing for sharing apps between phones and the web.
    • No mention of how AnyDAC will enter into things.
  • A bunch of people asked about Android development, including me.
    • JT said that it would be available later this year.  Same with C++ for both iOS and Android.
    • He said the goal was to have the same exact FireMonkey code compile and run on iOS and Android.  That would be very, very cool.  The question that I had was about styling – but I presume there is a way to dynamically change the styling depending on the OS.  I hope so, as I don’t want an Android app looking like an iOS app, or vice-versa.
    • There were a lot of folks asking about this – I personally am really looking forward to doing Android development with Delphi.  A lot.
  • The compiler is Embarcadero’s – no more FreePascal involved anywhere in the tool chain.
  • Pricing, packaging and all that kind of stuff will come later.  You can get on the beta if you are an XE3 customer.  Just another reason to buy Delphi XE3
  • Did I mention that you need a Mac to develop for iOS?
  • Further thoughts:
    • I’m anticipating that there will be many Delphi-built apps showing up on Apple’s AppStore in the coming year, including some cool DataSnap-based apps.
    • The mobile development space has finally come alive, and Delphi’s right there on the leading edge.  Xamarin has recently announced a cross-platform solution for Android and iOS, but they don’t provide a UI framework.  FireMonkey is right there with everything you need.  This should be a very compelling and competitive offering from Embarcadero.    And they appear to be doing this just at the right time as things really get hopping in the mobile tooling marketplace. 
    • For once, Delphi will be doing something that Microsoft will never, ever do.  Microsoft will never provide tools for developing for iOS and Android.  Or at least I can’t conceive of them ever doing it.  So this is green fields for Delphi.  Competitors are broader and smaller – HTML5 and JavaScript (for which they have an excellent tool in HTML5 Builder) and Xamarin appear to be the main competitors at this point.  This is a nice change and a great opportunity for Embarcadero to get away from the head-to-head competition with Microsoft. 

Again, I was very impressed overall.  The demos were pretty cool, FireMonkey looks really good on the iPhone, and the database access looks like it’s exactly what we Delphi developers would expect.  This is a cool opportunity for Delphi developers.

Delphi and the Factory Pattern: Simple Factory

By Nick at February 16, 2013 22:54
Filed Under: Delphi, Patterns

I’m currently reading “Head First Design Patterns”, and am finding it very useful and educational.  One problem, though – it’s all in Java.  So I thought that as part of the exercises, I’d translate the code to Delphi.  And also as part of my learning process, I thought it would be a good idea to post an article about each of the patterns.  I also strongly encourage you to buy the book and read it for yourself.

Let me be clear – I’m not doing much more than reproducing the demos in the book.  My purpose is to make the book more approachable for Delphi developers.  The result isn’t always the perfect way to do the pattern since the samples from the book are designed to be as simple as possible to illustrate the point.  I’m very aware that there are better ways to implement the patterns than are shown here. 

The chapter on the Factory Pattern in HFDP is pretty long, and divided into three main sections.  I’ll do a post on each section: General discussion and the Simple Factory, the Factory Method Pattern, and the Abstract Factory. 

General Discussion

Regular readers of this blog will know that I’m a huge proponent of Dependency Injection.  I’ve gone so far as to say that Dependency Injection should just be a way of life for a developer.  If you aren’t following the principles of Dependency Injection, you aren’t writing good, clean code.

One of the basics of Dependency Injection is the notion that the creation of objects is a “single responsibility” and that your class shouldn’t take on that responsibility because it, too, should only have a single responsibility.  If a class is taking care of its responsibility and creating the things that it needs, it is doing too much. The notion of creating things is a big responsibility, and not something that should be taken lightly.  Creating things should be done by classes whose specific job it is to create things. 

And one of the basic tenets of development is to code against abstractions and not concrete implementations.  Well, every time you call Create means you are coding against a concrete implementation.  That should be avoided as much as possible, right?  If you press all your Create calls back to a factory, then you can minimize the number of calls to Create and keep them well sequestered away. 

Thus we have the Factory Pattern.  The job of the factory pattern is to remove the worry and concern of creating things and make it happen pretty much automatically.  A while back I even wrote a blog post entitled “Life is Too Short to Call Create”.  In other words, the main job of the Factory Pattern is to hide via encapsulation the process of creating something.  Factories are the main places where your calls to Create should happen.

The Simple Factory

HFDP uses the example of a pizza store to show how a factory might be used to create pizzas.  So following along with their example, we can declare a pizza class and some specific types of pizzas:

type

  TSimplePizza = class(TObject)
    procedure Prepare;
    procedure Bake;
    procedure Cut;
    procedure Box;
  end;

  TCheesePizza = class(TSimplePizza );
TPepperoniPizza = class(TSimplePizza );
TVeggiePizza = class(TSimplePizza );
...

{ TPizza }

procedure TSimplePizza .Bake;
begin WriteLn('Bake the pizza'); end; procedure TSimplePizza .Box;
begin WriteLn('Put the pizza in a box'); end; procedure TSimplePizza .Cut;
begin WriteLn('Cut the pizza'); end; procedure TSimplePizza .Prepare;
begin WriteLn('Prepare the Pizza'); end;

There’s nothing special here, just some classes that represent pizzas.  The pizzas know how to be prepared.  Now, of course, we have to have a place to make our pizzas, so we declare a pizza store that knows how to take a pizza order:

 TSimplePizzaStore = class
    function OrderPizza(aPizzaType: string): TSimplePizza;
  end;

...

function TPizzaStore.OrderPizza(aPizzaType: string): TSimplePizza;
begin
  if aPizzaType = 'cheese' then
  begin
    Result := TCheesePizza.Create;
  end else
  begin
    if aPizzaType = 'pepperoni' then
    begin
      Result := TPepperoniPizza.Create;
    end else
    begin
      if aPizzaType = 'veggie' then
      begin
        Result := TVeggiePizza.Create;
      end else
      begin
        raise Exception.Create('I don''t know what kind of pizza that is: ' + aPizzaType);
      end;
    end;
  end;

  Result.Prepare;
  Result.Bake;
  Result.Cut;
  Result.Box;
end;

Now that works great.  But what happens when you want to add a pizza?  You have to change the OrderPizza method.  But what if you want to do something else to the pizzas?  Say you want to use the pizza class to program your point of sale, and provide pricing and descriptions?  You’d have to do another one of those big ugly if statements there as well, resulting in two places to change the code for a new pizza.  And of course, if you came up with a delivery scheme, that might be a third place. 

The code for creating the pizzas is something that seems likely to change and be duplicated, and so that screams out “Encapsulate me!”.  This is a good example of a class trying to do two things:  order a pizza and create a pizza.  It’s not doing one thing like all good classes that follow the Single Responsibility Principle should.  When a class tries to do two things, it has two reasons to change, and when a class has more than one reason to change, it becomes less useful, more coupled, and more complicated to change. 

So instead of doing the pizza creation right in the OrderPizza method, let’s create a class whose sole job is to create the correct pizza on demand.  This class will be a “simple factory” class, and it will take the pizza creation code out of the OrderPizza method and put it into its own method:

type
  TSimplePizzaFactory = class
    function CreatePizza(aPizzaType: string): TSimplePizza;
  end;
...

{ TSimplePizzaFactory }

function TSimplePizzaFactory.CreatePizza(aPizzaType: string): TSimplePizza;
begin
  if aPizzaType = 'cheese' then
  begin
    Result := TCheesePizza.Create;
  end else
  begin
    if aPizzaType = 'pepperoni' then
    begin
      Result := TPepperoniPizza.Create;
    end else
    begin
      if aPizzaType = 'veggie' then
      begin
        Result := TVeggiePizza.Create;
      end else
      begin
        raise Exception.Create('I don''t know what kind of pizza that is: ' + aPizzaType);
      end;
    end;
  end;
end;

TSimplePizzaFactory is pretty straight-forward:  it creates the kind of pizza you ask it for.  Simple.

Now that we have a class that has the sole responsibility for creating pizzas, we can simplify the TSimplePizzaStore class, passing it a TSimplePizzaFactory:

  TSimplePizzaStore = class
  private
    FFactory: TSimplePizzaFactory;
  public
    constructor Create(aPizzaFactory: TSimplePizzaFactory);
    destructor Destroy; override;
    function OrderPizza(aPizzaType: string): TSimplePizza;
  end;

...

{ TSimplePizzaStore }

constructor TSimplePizzaStore.Create(aPizzaFactory: TSimplePizzaFactory);
begin
  inherited Create;
  FFactory := aPizzaFactory;
end;

destructor TSimplePizzaStore.Destroy;
begin
  FFactory.Free;
  inherited;
end;

function TSimplePizzaStore.OrderPizza(aPizzaType: string): TSimplePizza;
begin
  Result := FFactory.CreatePizza(aPizzaType);

  Result.Prepare;
  Result.Bake;
  Result.Cut;
  Result.Box;
end;

The new pizza store takes the pizza factory as a parameter on its constructor and stores it.  Then the OrderPizza method uses that factory to create the pizza instead of doing the creation itself.  That unpleasant if statement is neatly hidden away in the TSimplePizzaFactory class where it can be re-used by anyone that needs it.  The pizza store just knows that the factory will create the right pizza for it.

So tying it all together, the following code will create a pepperoni pizza:

procedure MakeSimplePizza;
var
  SimpleStore: TSimplePizzaStore;
begin
  SimpleStore := TSimplePizzaStore.Create(TSimplePizzaFactory.Create);;
  try
    SimpleStore.OrderPizza('pepperoni');
  finally
    SimpleStore.Free
  end;
end;

Things to Note

Okay, here are some things to note about all of this:

  • Sure, the code for creating pizzas didn’t really change – we still have that big ugly if statement.  But it is nestled away in a single class – isolated, decoupled, and ready for use anywhere.  It is also a single place to add new pizza types.
  • The code above simply calls Create on the factory as a direct parameter in the constructor for the pizza store.  The pizza store then owns, and thus frees, the factory. 
  • Strictly speaking, this use of a simple factory isn’t a pattern.  Or at least that is what the folks in HFDP argue.  I’m not sure that I agree with them.  This is a pretty simple yet effective pattern in my mind.
  • Now, remember, I’m just implementing the basics of the code in the book.  There are some clear improvements that could be made to this code, and indeed the next two blog articles will cover much of those improvements, but I’ll mention a couple here:
    • First, both TSimplePizza and TSimplePizzaStore (and even TSimplePizzaFactory) could implement interfaces, enabling us to code against interfaces.
    • The CreatePizza method on TSimplePizzaFactory could have been declared as a class static method, making it so that you don’t even have to create an instance of the factory.
    • Passing in the pizza type as a string isn’t perfect either – it should be an enumerated type
  • The code for this project can be found on BitBucket.

Conclusion

So that’s the first look at a simple factory – a class whose job is to create things for you instead of you creating them yourself.  That’s the heart of what Dependency Injection is all about, and it’s a critical part of making sure that your code is as loosely coupled as possible.

Flotsam and Jetsam #79

By Nick at February 14, 2013 06:30
Filed Under: Delphi, Flotsam and Jetsam
  • Today is Delphi’s 18th Birthday.  I'll always wear it as a badge of honor that I was there at the launch at SD ‘95 in the Moscone Center.  Quite a privilege.  Thanks to everyone who has made Delphi such a great tool to use.
  • I am signed up for the RAD Studio Mobile Preview Webinar.  Are you going to attend?
  • Colin Johnsun reports that the JVCL has migrated over to use GitHub.  I consider this good news.  While I prefer Mercurial, Git is a Distributed Version Control System, and DVCS’s are vastly superior to server based systems like SVN.  First off, they are designed to branch and merge with ease, meaning that coordinating development and contributing changes is way, way easier (the process of “pull requests” that Colin talks about).  If you aren’t using a DVCS, you don’t know what you are missing.
  • In case anyone cares, my entire tweet archive is now online here on my site.  Here’s the tweet that started it all.

Flotsam and Jetsam #78

By Nick at February 09, 2013 01:39
Filed Under:

Flotsam and Jetsam #77

By Nick at February 06, 2013 07:43
Filed Under: Delphi, Flotsam and Jetsam, Tweet Expansion

Delphi and the Decorator Pattern

By Nick at February 04, 2013 00:23
Filed Under: Delphi, Patterns

I’m currently reading Head First Design Patterns, and am finding it very useful and educational.  One problem, though – it’s all in Java.  So I thought that as part of the exercises, I’d translate the code to Delphi.  And also as part of my learning process, I thought it would be a good idea to post an article about each of the patterns.  I also encourage you to buy the book and read it for yourself.

Let me be clear – I’m not doing any more than reproducing the demos in the book.  I’m very aware that there are better ways to implement the patterns than are shown here.  The idea is to learn the pattern, not optimize the code.

Continuing on through HFDP, the next pattern we’ll cover is the Decorator Pattern. 

One of the themes of the book is to make your code as flexible as possible at runtime, and to design your code to prefer runtime flexibility over compile time flexibility.  Anytime you determine something at compile-time, you lock that feature in to your code.  It can’t be changed at runtime. 

Inheritance is a pillar of OOP, but it is a compile-time construct.  Inheritance is powerful, but inflexible at runtime.  You have the classes you have, and they can’t be altered or changed once you set them in the stone that is compiled code. If you are trying to come up with differing combinations to decorate each class, you can end up having a huge number of descendent classes which can become difficult to manage and maintain.  Changes to one of the features means any number of descendants might need to change as well. 

The decorator pattern is a way of circumventing these limitations, and providing the power of inheritance while at the same time providing run-time flexibility.  It actually uses some simple inheritance to “wrap up” a given class and provide additional functionality without having to change the original class. 

Here is the formal definition from Wikipedia:  The Decorator Pattern attaches additional responsibilities to an object dynamically.  Decorators provide a flexible alternative to sub-classing for extending functionality.  You can read more about the pattern on Wikipedia.

It’s actually pretty straight-forward.  Here’s what you do:

  • First, you start with the notion of a class that needs to be decorated.  It becomes the “base” class.  The example in HFDP is that of a coffee drink.  They coffee itself – a beverage – is the base class which can be any number of different coffee types. Each will be decorated with various flavorings, etc., such as milk, mocha, and cream whip. 
  • Then you create a single descendant that will be the base decorator class.  That class will take as a property an instance of the original base class.  The base decorator should have a constructor that takes the original base class as a parameter. 
  • Next, you create concrete instances of decorators that override the necessary methods and properties of the base decorator class.
  • From there, you can start with the base class, and then chain together as many decorators as you want.

Okay, let’s take a look at that in code.  Here is the base class, TBeverage:

type
  TBeverage = class
  private
    FDescription: string;
  protected
    function GetDescription: string;  virtual;
    procedure SetDescription(const Value: string);
  public
    function Cost: Double; virtual; abstract;
    property Description: string read GetDescription write SetDescription;
  end;

The base class is abstract.  It has two properties, with the Cost property being read-only and having an abstract, virtual getter. 

TBeverage is the base class for the beginning of the wrapping process.  We create descendants that will form the base class described above.  These classes override the Cost method, providing their own prices.  They will be the starting point for decorating.  In our case, we’ll create specific base coffee types that can be wrapped:

 TEspresso = class(TBeverage)
    constructor Create;
    function Cost: Double; override;
  end;

  THouseBlend = class(TBeverage)
    constructor Create;
    function Cost: Double; override;
  end;

  TDarkRoast = class(TBeverage)
    constructor Create;
    function Cost: Double; override;
  end;

  TDecaf = class(TBeverage)
    constructor Create;
    function Cost: Double; override;
  end;

The interesting part comes in the base decorator class:

  TBeverageDecorator = class(TBeverage)
  private
    FBeverage: TBeverage;
  public
    constructor Create(aBeverage: TBeverage);
    destructor Destroy; override;
  end;

TBeverageDecorator does three things.  One, it descends from TBeverage. Two, it gets another instance of TBeverage from its constructor in order to “wrap” itself around the starting base class.  And three, the destructor ensures that the internally stored instance gets freed properly when that time comes. 

Since TBeverageDecorator is itself a TBeverage, you can continue wrapping the previous result in a new one, decorating the decorator as it were.  In addition, it will have the exact same interface as the base beverage class, so it can act like a beverage because, well, it is one.   

As for classes that do the decorating, they will descend from TBeverageDecorator:

  TMocha = class(TBeverageDecorator)
  protected
    function GetDescription: string; override;
  public
    function Cost: Double; override;
  end;

  TSoy = class(TBeverageDecorator)
  protected
    function GetDescription: string; override;
  public
    function Cost: Double; override;
  end;

  TWhip = class(TBeverageDecorator)
  protected
    function GetDescription: string; override;
  public
    function Cost: Double; override;
  end;

Each of these classes does two things. 

First, they override the getter for the Description property.  They do it in an interesting way.  Since they are decorating the base Beverage, they assume that they are “additive”, that is that they will be adding on to the base description.  The TMocha.GetDescription method looks like this:

function TMocha.GetDescription: string;
begin
  Result := FBeverage.GetDescription + ', Mocha';
end;

This method grabs the description from the class that it is wrapping and adds on a comma and its own description.

Second, the Cost method is overridden to add the cost to the price of the class that it is decorating.

function TMocha.Cost: Double;
begin
  Result := 0.20 + FBeverage.Cost;
end;

So, now we have a bunch of types of coffee – the base classes --and a bunch of flavors to wrap around those classes and themselves.  Let’s put it all together:

First, we’ll create a routine to write out the coffee type to the console:

procedure OutputBeverage(aBeverage: TBeverage);
begin
  WriteLn('A ', aBeverage.Description, ' costs ', '$', Format('%2f', [aBeverage.Cost]));
  WriteLn;
end;

Then, we’ll create an Espresso and wrap it with Double Mocha and Whip:

procedure OrderCoffee;
var
  Beverage: TBeverage;
begin
  Beverage := TEspresso.Create;
  try
    Beverage := TMocha.Create(Beverage);
    Beverage := TMocha.Create(Beverage);
    Beverage := TWhip.Create(Beverage);
    OutputBeverage(Beverage);
  finally
    Beverage.Free;
  end;
end;

This will build the description and calculate the correct price, and result in:

 

 

 

Another way that you can create a coffee is by simply nesting each decorator in the constructor of the previous one.  This method actually provides a coding representation of how each decorator wraps up the previous one:

  // Alternate way to call the same thing as above....
  Beverage3 := TWhip.Create(TMocha.Create(TMocha.Create(TDarkRoast.Create)));
  try
    OutputBeverage(Beverage3);
  finally
    Beverage3.Free;
  end;

The complete implementation of our little coffee shop application can be found on BitBucket.  That code should be a faithful representation of the final project in the book.  And I have mentioned that I strongly recommend that you buy the book, right?

So, to summarize:

  • The whole thing starts with base class that will be decorated.
  • The decorator classes both descend from and maintains a reference to that base class. This means that they will have the same interface, yet the reference will allow composition instead of inheritance. 
  • One or more decorators can be wrapped around the base class and each other to produce a single entity. 
  • The Decorator can augment the behavior of the class it is wrapping.  We see this with the Cost and Description properties. 
  • You can dynamically decorate objects at anytime, enabling you to create any combination of decorators without having to create a descendent class for each.
  • Decorators allow you to extend behavior of existing classes without needing to modify existing code. 

There are some problems here – you can end up with a lot of little classes to manage; that might bother some people.  Use of decorators can lead to complex code and implementations – use them with care. 

However, the basic idea is to simplify and add flexibility to your code over a complex inheritance model. In addition, it makes it easier to build a single instance at run-time of complicated combinations of features or items.

Next up:  The Factory Pattern

My Book

A Pithy Quote for You

"Golf is a game of luck. The more I practice, the luckier I get."    –  Ben Hogan

Amazon Gift Cards

General Disclaimer

The views I express here are entirely my own and not necessarily those of any other rational person or organization.  However, I strongly recommend that you agree with pretty much everything I say because, well, I'm right.  Most of the time. Except when I'm not, in which case, you shouldn't agree with me.