Amazon.com Widgets Software Development

Another Gem from the VSoft Guys: TCommandLineParser

By Nick at November 16, 2014 02:02
Filed Under: Delphi, Software Development, Tech Stuff

You know, the gang at VSoft, led by Vince Parrett, have really contributed a lot to the Delphi and the Developer community.  First, they built FinalBuilder – probably one of the best known apps built with Delphi -- and now ContinuaCI for all developers.  And being Delphi developers, they have contributed the DelphiMocks and DUnitX frameworks to the Delphi community.  Recently, they added another little gem to that list – TCommandLineParser.

It’s seems less common than it used to be with “regular” applications, but command line switches certain remain popular and common with console applications.  They are used to pass filenames, boolean values, and other information on the command line. Handling those switches can be a bother, and it’s seems silly to repeat similar code for each application.  This is where TCommandLineParser comes in. 

TCommandLineParser is a library that makes it really easy to add and read command line parameters to your applications. Sure, the RTL provide the ParamStr/ParamCount functionality, but they don’t provide some of the features that TCommandLineParser does.  For instance, with TCommandLineParser you can:

  • Set switches to contain specific value types
  • Easily retrieve those switch values in your application in a simple class
  • Pass strings, boolean values, and numbers and other types

To get started using it, you can pull the code using Git from the following endpoint (You do have Git installed on your machine, right?) :

https://github.com/VSoftTechnologies/VSoft.CommandLineParser.git

The project comes with a simple demo application, but let’s build one ourselves so that we can step through the process and really see how it works.  So, let’s take the following steps:

 

  1. 1.  Create a new Console application by selecting File|New|Other|Delphi Applications|Console Application.
  2. 2.  Make sure that the directory where you put TCommandLineParser is on your path, either for the application you just created or as part of your library path for Delphi.
  3. 3.  In the uses clause of the project file, add the following two units: VSoft.CommandLine.Parser and VSoft.CommandLIne.Options.

4.  Now, add a new, blank unit to the file and call it CLPOptions.pas. This is the file that will hold the class that will end up with all of the command line parameter values.  In that file we’ll have an interesting class – one with nothing but class variables.  Put the following code into the unit.



type
  TSampleOptions = class
  public
    class var
      FileToProcess: string;
      OutputInUpperCase: Boolean; 
      NumberOfIterations: integer;
  end;

This class contains a string, a Boolean and an integer.  Other types that can be passed on the command line include enumerated types, sets, and floating point numbers.  Again, this class will end up holding the values passed on the command line, and since the variables are all class variables, they can be accessed directly without having to instantiate the class. 

5.  Next, we’ll register these items with the TOptionsRegistry class.  This class is the one that translates the command line parameters into options usable by your application.  You can define options as having a long name, a short name, and whether the parameter is optional or required.  The TOptionsRegistry.Parse method will then parse out the command line and fill in the values of the class we defined above.  In order to do that, create a new, empty unit, add it to the project, and call it CLPConfig.pas.  Then, add VSoft.CommandLine.Options and CLPOptions to the uses clause of your new unit.  Then, add the following code to the implementation part of the unit (you can leave the interface section empty):

 
procedure ConfigureOptions;
var
  Option : IOptionDefintion;
begin
  Option := TOptionsRegistry.RegisterUnNamedOption<string>('The file to be processed',
    procedure(value : string)
    begin
        TSampleOptions.FileToProcess:= value;
    end);
  Option.Required := true;

  Option := TOptionsRegistry.RegisterOption<Boolean>('OutputInUpperCase','o', 'The output should be in upper case',
    procedure(value : Boolean)
    begin
        TSampleOptions.OutputInUpperCase:= value;
    end);
  Option.Required := true;
  Option.HasValue := False;

  Option := TOptionsRegistry.RegisterOption<integer>('NumberOfIterations','n','The number of times the file should be processed',
    procedure(value : integer)
    begin
        TSampleOptions.NumberofIterations := value;
    end);
  Option.Required := False;   
  Option.HasValue := True;
  
end;

Here’s what is important to note about the following code:

  • The first thing to note is that each of the calls that registers a parameter takes a parameterized type of the type that should be received as part of the command line parameter. 
  • The first Option registered is an “unnamed” option, meaning that there is no switch or name associated with it.  Normally, a parameter will have a switch (for example “/d”)associated with it.  This option, however, will just be the filename.  The first parameter of RegisterUnNamedOption is a description of the option that will be shown to the user when “help” is displayed.  (We’ll discuss that in a bit).  The second parameter is an anonymous method that lets you do what you want with the value passed in the parameter.  It’s a TFunc<string> and in this case, we assign the string to the TSampleOptions.FileToProcess class variable.  Note that this option is also set to Required, meaning that unless the parameter is present, the application run and the “help” will be shown.
  • The second Option registered is a “regular” parameter, in that it is a switch.  That switch can two values – “/OutputInUpperCase” or “/o”.  These are defined by the first two parameters of the call to RegisterOption.  The third parameter is the help string, and the fourth is an anonymous method taking a single Boolean value that defines the presence or absence of the switch.  Because the Option.HasValue property is set to False, the switch will stand alone, and its presence means the value is True, and its absence means it is False.  In other words, the parameter has no value passed along with it. 
  • The third Option is yet another variation. This one has a switch, but it takes a value, because the Option.HasValue property is set to True.  This means that the parameter will appear as “/o:42”, using a colon to separate the switch from the passed value.  Note that this parameter is set to be optional, because the Required property is set to False.

Of course this procedure needs to be called very early in the executable timeline, so you should add an initialization section to the unit that looks like this:


initialization
  ConfigureOptions;

 

Switches are key to passing command line parameters, and TCommandLineParser will accept the following to define a switch:

  • A forward slash: /d:aValue
  • A single dash: -d:aValue
  • Double dashes: --d:aValue

Note that for options that have HasValue set to False, there is no need to pass a value. 

Of course, once you have set all these options, you need to write some code to retrieve them, and handle the situation when things aren’t right – required parameters are missing, or switches requiring values don’t have them. 

Go to the DPR file and add this code:


var
  ParseResult :  ICommandLineParseResult;
begin
  try
    //parse the command line options
    ParseResult := TOptionsRegistry.Parse;
    if ParseResult.HasErrors then
    begin
      Writeln(ParseResult.ErrorText);
      Writeln('Usage :');
      TOptionsRegistry.PrintUsage(
        procedure(value : string)
        begin
          Writeln(value);
        end);
    end else
    begin
      Writeln('FileToProcess : ', TSampleOptions.FileToProcess);
      Writeln('OutputInUpperCase : ', TSampleOptions.OutputInUpperCase);
      Writeln('Iterations : ', TSampleOptions.NumberOfIterations);
    end;
    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Note the following about the above code:

  • It declares ParseResult with is of type ICommandLineParseResult.  It will contain the results of parsing the command line when TOptionsRegistry.Parse is called.  The names make that pretty obvious, eh? 
  • If the result of the parsing HasErrors, then the “Usage” of the application is output.  It can be output anyway you like, as you pass the PrintUsage method an anonymous method that does the output in any way you want.  In this case, it simply prints out the value passed in to it.  This is where the “help” parameters above come in.  The PrintUsage method parses out all the registered parameters, grabs all the switch and parameter values, as well as the help string you passed in, and creates a string that shows the proper usage of the parameters.  Before printing that out, the code prints out the actual problem with the usage.
  • If all is well, and all the required parameters are present and properly formed, then the code will simply print out the values passed on the command line.

That’s it for code.  Now for using the application.  First, let’s get a look at what happens when you pass no parameters at all.  Press F9 and you should see something like this:

image

 

Note that you receive error messages, and a description of how the command line parameters work.

Then, go to Run|Parameters and in the Parameters box enter:

somefile.dat -o -n:42

Running the app should result in the following:

image

Which shows that the parameters were correctly passed. 

And that is about it.  It takes a bit of work to get going, but not much, and you get a lot of functionality for the little input that you have to make.

Like I said in the title – another gem from the folks at VSoft Technologies.

Flotsam and Jetsam #85

By Nick at September 21, 2014 04:50
Filed Under: Delphi, Flotsam and Jetsam, Software Development
  • I have been spending a lot of time with XE7 lately, mainly working on presentations for EKON18.  I’m speaking on a number of topics, and thus have been running XE7 through the paces pretty well.  Impressions so far:
      • Having Castalia as a free add-on is fantastic.  I’m currently only using about 10% of it, but I love it already and am looking forward to learning more.  You can get it absolutely free – the full edition – until 30 September as long as you are a registered XE7 owner.  Highly recommended.
      • One of the talks I’m doing is on REST services, and so I’ve been working with the Enterprise Mobility Server (EMS) in XE7.  This is a seriously very cool thing.  It makes building REST Servers as easy as falling off a log. It automatically provides support for users and groups.  You can building your own extensions as easily as building a Delphi package, and the server will scale no problem by running inside of IIS as an ISAPI extension.  It also makes it really easy to build clients to consume the services.  This is some really amazing and powerful stuff.  Seriously.  Not just mindless promotion here – this is really powerful and easy. Want to get started with it?  The documentation is terrific.
      • I know that some people get upset with me when I say this, but the IDE is really fast and stable.  I don’t know if it is just the way that I use it, but I really haven’t had any trouble with it at all.  It just works. 
      • Similar to the EMS stuff is the Backend as a Service (BaaS) support. If you want to build a mobile application that a million people will use, you can do it with the BaaS stuff via either Kinvey or Parse.  These back-ends take care of storing everything, including users, logins, data storage, and everything.  Much like the EMS Server.  So if you want a hosted solution, or want to host your own, then XE7 has you covered.
      • You can even use it to build apps for things like the new Moto 360 watch.  Cool.
      • Bottom Line:  It’s a seriously cool time to be a Delphi developer.  If you haven’t looked at XE7, do it now
  • I want to mention yet again how much I appreciate all of you who have bought my book.  The whole experience has been humbling as the sales have exceeded my wildest expectations.  Thank you.  In fact, it’s been such a good experience that I’m already thinking about writing another one.
  • I’ll be doing a Developer Skill Sprint this Tuesday on Aspect Oriented Programming with DSharp.  I’d be honored if you attend and ask questions.  These Skill Sprints have been really cool.  They are nice and short, but not too short. They happen at three times during the day, so no matter where you are, you should be able to tune in.  This is my second one, and they’ve been fun to do. 

Where to Get Delphi Help

By Nick at September 06, 2014 07:48
Filed Under: Delphi, Software Development, Tech Stuff

Sadly, the good old Embarcadero newsgroups NNTP Feed appear to have come to an end.  Alas.  I’ve been a member of those groups in one form or another for over 20 years, starting with the Compuserve forums and ending up with the wonderful and grossly underappreciated NNTP newsgroups.  I believe that Embarcadero is trying to get the newsgroups back up in a read-only status.  Nevertheless, it appears to be time to move on.

So where can we migrate to?  I see three places where the community can communicate and get questions answered.

    • The official solution is community.embarcadero.com.  This is the place that Embarcadero is bringing everything together that formerly was EDN, the Blog server, and the newsgroup server.  This new community has blogs, articles, and Forums.  The Forums are organized by topics rather than products and languages. It takes a bit of getting used to, but we can work with it that way, right?  In addition, there is the Answers section, which has a StackOverflow-like way of asking and answering questions. Overall, it looks like a pretty nice web site, though I know many of us will miss the NNTP forums.  This will take some getting used to, but things move forward, and this is the way that things are going.  I’m on board
    • StackOverflow has a very active Delphi sub-group where you can get excellent, fast answers to your questions.  If David Heffernan doesn’t answer your question, Ken White, Rob Kennedy, Mason Wheeler, Remy Lebeau or some other very active Delphi community member will jump on it.  StackOverflow is a fantastic resource, and if you have a Delphi question, it’s a great place to get an answer. Most often, someone has already asked your question, and the archives have the answer already. I for one will always choose the StackOverflow answer in a Google search as my first choice. 
    • Another place to ask questions and generally hang out is the Delphi Community on Google Plus.  There are almost 3500 of us there, and there is usually some lively discussion, questions being answered, interesting open source projects announced and discussed, and generally a good place for Delphi folks to be.  If you aren’t a member and aren’t participating, you should be.

So for now, those are the places to gather and get help.  Times are changing for the Delphi community, both in terms of what the tool can do and where we will communicate online.  I encourage folks to move on from the newsgroups and try out the newer places to hang out and get help.

Coding in Delphi Now Available in Print

By Nick at February 22, 2014 01:54
Filed Under: Delphi, Software Development

My book, "Coding in Delphi" is now available in print.  This is pretty cool. You can get it from CreateSpace or Amazon.  I'm grateful for every order. 

It seems very strange to have my own entry for sale on Amazon.  Writing a book is a lot of work, but I will say, it's quite satisfying to hold the book in your hand and see your name on Amazon.com.  :-)

I'd also be very grateful for book reviews on Amazon.  If you like the book, please let people know.  And if you don't like it, write a review and say why.  Either way, I'll appreciate your honest assessment.  You can write the review right from the Amazon order page.  

And again, I'm grateful to all of you who have had so many nice things to say, who helped edit the book, and who make the Delphi community so great.

The Delphi Unit Test Project

By Nick at August 17, 2013 07:02
Filed Under: Delphi, Unit Testing, Software Development

In a previous post, I humbly suggested that Embarcadero publish their unit tests for Delphi.  I still think it is a good idea, but I understand if they don’t do it.  They do have a lot to do.

So I thought – after suggestions from folks that read the post, including Kenneth Cochran – that it would be a good idea to just go ahead and start our own community project.  So I did.

The Delphi Unit Tests Project

This is a pretty straight-forward project – it is merely a set of unit tests for Delphi’s RTL.  You can find out the basics on the home page of the wiki, where you’ll also find further information about writing tests, etc.  It’s a wiki, so it will continue to be expanded. I’m kind of weird in that I actually enjoy writing unit tests, so I’ve been adding tests over the last week or so.

This is a community project based on Mercurial.  That means that anyone can fork it, add tests, and then submit a pull request.  We’ve already had four or five submissions, and I’m really appreciative.  It’s quite easy to contribute, and you can write tests for anything you like.  Any submitted tests must pass, of course.

We are also using the new Delphi unit testing framework, DUnitX.  It is still a bit rough around the edges, but hopefully this will be an impetus to get it fully up to speed.  I’ve volunteered to write the GUI runner, but there are some architectural issues that need to be taken care of.  Right now, you can output to NUnit xml and the console.  DUnitX is attribute based and really easy to use.

Things I’d  like to eventually get done:

  • I’d like to get at least one test for everything we can in the RTL.
  • I’d like to figure out a way to have tests written for QualityCentral reports.  The tests could “pass”, proving the bug exists, and then when they “fail”, that could show that the bug has been fixed. 
  • I’d love to see our tests eventually get integrated into the Embarcadero internal build.  That would be really cool.

In any event, come join the cause and write a test.  Even one single test would be fine!

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. 

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.

Delphi and the Observer Pattern

By Nick at January 27, 2013 11:46
Filed Under: Delphi, Patterns, Software Development

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.

The first real pattern that the book shows is the Observer Pattern.  You should use the observer pattern when you have one object that notifies other objects when events occur.    Or more succinctly, use it when you have an object that needs to notify other objects about stuff that happens. 

HFDP uses the example of a simple weather station that gathers data about the weather.  Each time the weather station takes readings, it needs to update the views of that weather. The weather station reports on Temperature, Humidity, and Pressure.  There are three views that the application provides – current conditions, statistics about the weather, a simple forecast.

The idea here is that the weather station is the subject – it is the object being observed and doing the notifying.  The different displays for the information are the observers – they watch what happens on the weather station and update themselves based on the notifications that they receive from the weather station.  Another way to look at it is that the weather station is a publisher of information, and the displays are subscribers.

The formal definition given for the Observer Pattern goes like this: The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically. 

But when it comes time to implement this, the temptation is to simply embed the displays inside of a method of the weather station.  You might create classes for each view, instantiate them in the weather stations constructor, and then simply update the views in a method called MeasurementsChanged.

But of course if you do this, you are breaking some of the base design rules.  First, you’d be coding against an implementation instead of against an interface.  Second, you’ve made it really hard to add a new data display should that become necessary.  Displays are hard-coded into the weather station and can’t be added or removed at runtime.  If we do want to add more displays, we’d need to modify the weather station itself.  Or, put more succinctly, the weather station and its displays are tightly coupled to each other.  And if you know one thing about me, I abhor tight coupling.  And you should too.

In any event, there is a better way – the Observer Pattern.  As noted above, observer pattern consists of a Subject that is monitored by Observers.   We’ll implement a very simple version of the observer pattern. The first thing we will do of course, is declare two interfaces:

type
  IObserver = interface
  ['{69B40B25-B2C8-4F11-B442-39B7DC26FE80}']
    procedure Update(aTemperature: integer; aHumidity: integer; aPressure: Double);
  end;

  ISubject = interface
  ['{A9240295-B0C2-441D-BD43-932AF735832A}']
    procedure RegisterObserver(aObserver: IObserver);
    procedure RemoveObserver(aObserver: IObserver);
    procedure NotifyObservers;
  end;

The first interface is IObserver, which the observing classes will implement.  In it they’ll be updated with all the weather information that the weather station has for us.  The second is ISubject, which will be implemented by the weather station.  It takes three methods, two for handling the connecting and disconnecting of IObservers, and the third for doing the actual notification to the observers. 

The first implementation we’ll look at is the Weather Station.  Here is its implementation declaration.

type
  TWeatherData = class(TInterfacedObject, ISubject)
  private
    FTemperature: integer;
    FHumidity: integer;
    FPressure: double;
    FObserverList: TList<IObserver>;
    function GetTemperature: integer;
    function GetHumidity: integer;
    function GetPressure: double;
  public
    constructor Create;
    destructor Destroy; override;
    procedure SetWeatherInformation(aTemperature: integer; aHumidity: integer; aPressure: double);
    procedure RegisterObserver(aObserver: IObserver);
    procedure RemoveObserver(aObserver: IObserver);
    procedure NotifyObservers;
    procedure MeasurementsChanged;
    property Temperature: integer read GetTemperature;
    property Humidity: integer read GetHumidity;
    property Pressure: double read GetPressure;
  end;

The plumbing for managing the weather implementation is all what you’d expect.  The interesting part, of course, is the implementation of ISubject.  Internally, it uses a TList<IObserver> to manage all the observers that get registered with it.  The RegisterObserver and RemoveObserver methods simply insert and remove, respectively, instances of classes that implement the IObserver interface.

The real action occurs in the NotifyObservers method.  We’ll get to that in a second.  First, though, let’s take a look at the observers.  Since all the displays are very similar, this is a good time to use good old-fashioned inheritance to declare a base class that implements the needed functionality, and then have descendent classes that do the work of providing the specified displays.  Here, then, is the interface for TWeatherDataDisplay:

TWeatherDataDisplay = class(TInterfacedObject, IObserver, IDisplay)
  private
    FSubject: TWeatherData;
    FTemperature: integer;
    FHumidity: integer;
    FPressure: Double;
  public
    constructor Create(aWeatherData: TWeatherData);
    destructor Destroy; override;
    procedure Update(aTemperature: integer; aHumidity: integer; aPressure: Double); virtual;
    procedure Display; virtual; abstract;
  end;

TWeatherDataDisplay has fields to keep track of the current weather information.  It’s descendants can do with it as they please.  It also implements the IDisplay interface so that it can report out what it has to say.  The Update method will allow the Subject – in this case the weather station – to update the displays.  Update is a virtual method, by the way, so that descendants can do different things with the incoming information. 

Okay, so let’s look under the hood.  The weather station can accept and remove IObserver implementers at runtime.   implements the NotifyObservers method as part of the ISubject interface.  It gets called whenever the weather information changes.  It is implemented as follows:

procedure TWeatherData.NotifyObservers;
var
  Observer: IObserver;
begin
  for Observer in FObserverList do
  begin
    Observer.Update(Temperature, Humidity, Pressure);
  end;
end;

This is pretty simple – it merely enumerates over each item in the observer list and calls the Update method, passing along the new weather data.  The base class stores the information, and its descendants process it.

The real “work” gets done when the weather station updates the temperature data and calls NotifyObservers:

procedure TWeatherData.SetWeatherInformation(aTemperature, aHumidity: integer; aPressure: double);
begin
  FTemperature := aTemperature;
  FHumidity := aHumidity;
  FPressure := aPressure;
  MeasurementsChanged;
end;

The entire implementation of our little weather station can be found as part of my demo code on BitBucket.org.

So all of this comes together in a method to create a weather station and add observers:

procedure DoWeatherStation;
var
  WeatherStation: TWeatherStation;
  CurrentDisplay: IDisplay;
  ForecastDisplay: IDisplay;
  StatsDisplay: IDisplay;
begin
  WeatherStation := TWeatherStation.Create;
  try
    CurrentDisplay := TCurrentConditionsDisplay.Create(WeatherData);
    ForecastDisplay := TForecastDisplay.Create(WeatherData);
    StatsDisplay := TStatisticsDisplay.Create(WeatherData);;
    WeatherStation.SetWeatherInformation(70, 55, 28.90);
    WeatherStation.SetWeatherInformation(68, 59, 28.96);
    WeatherStation.SetWeatherInformation(35, 66, 27.40);
    WeatherStation.SetWeatherInformation(55, 55, 27.40);

  finally
    WeatherStation.Free;
  end;
end;

Here are some interesting things to note:

  • This code doesn’t write anything to the console.  All of that is done by the display objects that get registered as observers.  Each observer is registered, and the code pretty much forgets about them.  To the weather station, they are merely IObserver interfaces, and the only thing you can do to an IObserver is call it’s Update method.  From the Weather Station’s perspective, there’s nothing else to it.
  • Four calls to SetWeatherInformation result in for reports from all of the updates to the temperature information.
  • Once you have a reference to a TWeatherStation, you can add or remove displays at runtime.
  • TWeatherStation doesn’t know anything about Weather displays – it only knows about IObservers.  This means that you could have observers that do other things besides being Weather Displays.  You could simply store the weather data, or anything else at all.  For instance, you could create a TWriteWeatherInfoToDatabase class that implements the IObserver interface.  The Weather Station itself neither knows nor cares.  IObservers are under no obligation to do anything specific with the data passed to them. 
  • We can change the observers anytime we want without altering the Subject.  We can add new observers, too.  Basically, observers and subjects are very loosely coupled, and either can be changed, altered, updated, and added to without having to worry about changing the other. 

So that should be a quick rundown on how the observer pattern works.  The obvious weakness here is that our IObserver interface is very specific to weather data.  You can create your own interface for your specific implementation.  The pattern remains the same no matter how the IObserver interface is designed.  This is obviously a good place for generics to enter the picture, and in fact, the Delphi Spring framework implements a generic IObservable<T> interface and implementing class.

So in summation, the Observer pattern ensures that publishing classes (subjects) can communicate updates to their subscribing (observer) classes with very loose and flexible coupling.  Observers can be updated and removed at runtime.  Adding observers requires no change to subjects.  Subjects don’t know much at all about what the observers are up to.  It’s all very easy and elegant and loosely coupled – just like you want it.

Next up – the Decorator Pattern.

Enumerating and the for…in Loop

By Nick at January 12, 2013 06:05
Filed Under: Delphi, Software Development

One of those fun little issues in our business is trying to figure out the difference between iterating and enumerating.  This StackOverflow answer does a pretty good job of explaining it.  Iterating is doing something – usually a series of steps – over and over again.  Enumerating is going over each item in a given collection.  A subtle difference, sure.  One usually iterates when enumerating. 

Okay, so enumerating is going over each item in a collection.  IEnumerable can enumerate over the items in a collection as we saw in my last article.  But you can enumerate over other things as well.  For instance, in Delphi, you can use the for…in statement to enumerate over the characters in a string. 

But this makes me wonder:  how does something become, well, enumeratable?  How do you make something so that you can use with the for…in statement? 

Well, it’s pretty easy.  The rules for Delphi are simple:

  • To create a class or record to enumerate, it must provide a method called GetEnumerator() which in turn needs to be a function that returns a class, an interface, or a record that is an enumerator.
  • To be returned as an enumerator, that class, record, or implemented interface needs to have the following:
    • A method called MoveNext that returns a Boolean indicating whether the end as been reached or not
    • A read-only property called Current that indicates the item that is currently being “looked at” as the enumeration occurs. 

So, at this point, a simple demo would be helpful, eh?

You can already enumerate the characters in a string, but it’s a simple example, and so the following example implements this easy to understand enumeration on a string:

TForInDemoClassEnumerator = class
  private
    FString: string;
    FIndex: integer;
  protected
    function GetCurrent: Char; virtual;
  public
    constructor Create(aString: string);
    function MoveNext: Boolean;
    property Current: Char read GetCurrent;
  end;

TForInDemo = class
  private
    FTheString: string;
    procedure SetTheString(const Value: string);
  public
    constructor Create(aString: string);
    function GetEnumerator: TForInDemoClassEnumerator;
    property TheString: string read FTheString write SetTheString;
  end;

 

This code declares two classes.  The first class is the enumerator – the class that does the work of  moving over each item, and which will be returned by the call to GetEnumerator.  The second is the class that will be enumerated.  Notice, too, that TForInDemoClassEnumerator has the read-only property Current with the reader GetCurrent and MoveNext methods.  The TForInDemo class has a call to GetEnumerator that returns an instance of TForInDemoClassEnumerator

First let’s look at TForInDemoClassEnumerator.  You create it by passing the constructor the item to be enumerated – in this case a string.  Hence, the constructor:

constructor Create(aString: string);

Here is the implementation of the MoveNext method:

function TForInDemoClassEnumerator.MoveNext: Boolean;
begin
  Result := FIndex < FString.Length;
  if Result then
  begin
    Inc(FIndex);
  end;
end;

This code does two things.  First, it sets the result. The function returns True if the enumerator is able to move to the next item, and False if it has reached the end of the items to be enumerated.  In this case, it merely checks to see the index is before the length of the string.   If the end has not yet been reached, it just increases the FIndex field.  So it’s job here is merely to move the index along, and report if the end has been reached.

The actual item itself is returned by the GetCurrent method, which is self-explanatory:

function TForInDemoClassEnumerator.GetCurrent: Char;
begin
  Result := FString[FIndex];
end;

And that is it for the enumerator.  It’s pretty simple.  But we’ll soon see that you can do some cool things with these enumerators because you have complete control over how they return the data that they are enumerating over.

The next step is to see how the actual class to be enumerated provides its enumerator to the compiler.  When the compiler builds the for…in loop construct, it looks at the in part of the construct and thinks “Hey, I need an enumerator here, so I’ll call GetEnumerator”.  If the item in question indeed has a method called GetEnumerator, it calls it, and all is well.  If not, the compiler raises an error because the type in the in part of the for…in loop isn’t enumeratable. 

But of course, our TForInDemo class has such a method, and it is quite simple:

function TForInDemo.GetEnumerator: TForInDemoClassEnumerator;
begin
  Result := TForInDemoClassEnumerator.Create(FTheString);
end;

It merely creates and returns an instance of our enumerator, passing it the string value it is storing for the purpose of enumerating.   Pretty easy and straight forward, really.

Now that we’ve created all these classes, you can run the following code:

procedure DoStuff;
var
  ForInDemo: TForInDemo;
  C: Char;
begin
  ForInDemo := TForInDemo.Create('HelloWorld');;
  try
    for C in ForInDemo do
    begin
      Write(C, ',');
    end;
    WriteLn;

  finally
    ForInDemo.Free;
  end;
end;

 

IEnumerator<T> Interface

Now the above discussion talks a lot about specific methods that must be included as part of an enumerator, and as part of a class that wants to be enumerated.  And of course, that should immediately make you think “Interfaces!”.  And sure enough, there are some nice interfaces that fall out of this. (You knew I’d work interfaces into things here eventually, didn’t you.  Yes, you did.) 

Consider this interface:

type
  IEnumerator<T> = interface
  ['{DD445F01-975D-405E-BCC1-09D3E78CB0FF}']
    function GetCurrent: T;
    function MoveNext: Boolean;
    property Current: T read GetCurrent;
  end;

That should look awfully familiar.  It’s the exact two methods and one property needed to implement an enumerator – hence the name. 

I’ve declared this IEnumerator<T> interface myself, but the Delphi RTL includes a similar one in the System.pas unit. And at its base, IEnumerable<T> is all about implementing the GetEnumerator method.   

It leverages generics because the type of what is being enumerated doesn’t matter as far as the interface is concerned.  And remember when I said that a call to GetEnumerator could return an interface?  Well it can, and the compiler will happily use an IEnumerator<T> to implement the for…in loop.

Thus, your enumerators can implement this interface and your calls to GetEnumerator can return this interface, and you can add flexibility to how they are implemented.  Here’s an example:

  TStringEnumerator = class(TInterfacedObject, IEnumerator<Char>)
  private
    FIndex: integer;
    FString: string;
    function GetCurrent: Char;
  public
    constructor Create(aString: string);
    function MoveNext: Boolean;
    property Current: Char read GetCurrent;
  end;

  TInterfaceEnumeratorDemo = class
  private
    FTheString: string;
    procedure SetTheString(const Value: string);
  public
    constructor Create(aString: string);
    function GetEnumerator: IEnumerator<Char>;
    property TheString: string read FTheString write SetTheString;
  end;

Notice that the call to GetEnumerator returns an IEnumerator<Char> which is actually the individual type being iterated. In this case, the generic type needs to be the same type as the variable being returned in the for part of the for…in loop.  

This enables you to do the following:

procedure DoInterfaceStuff;
var
  InterfacedEnumerator: TInterfaceEnumeratorDemo;
  c: Char;
begin
  InterfacedEnumerator := TInterfaceEnumeratorDemo.Create('GoodbyeWorld');
  try
    for c in InterfacedEnumerator do
    begin
      Write(C, ',');
    end;
    WriteLn;
  finally
    InterfacedEnumerator.Free;
  end;
end;

 

Specialized Enumerators

The implementation of an enumerator is, as I mentioned, really simple.  But what if you wanted to get a little creative in the GetCurrent method?  After all, at that point you have complete control over what the enumerator returns.  In our simple case with characters and strings, what if we decided to, say, always return the upper case version of the character?  Or if we were iterating over integers, return the squares of the numbers in the collection?  That would be super easy, right? Well, yes, it would.

Consider this code:

  TForInDemoClassUpperCaseEnumerator = class(TForInDemoClassEnumerator)
  protected
    function GetCurrent: Char; override;
  end;
...
function TForInDemoClassUpperCaseEnumerator.GetCurrent: Char;
begin
  Result := UpCase(inherited GetCurrent);
end;

This class descends from TForInDemoClassEnumerator and overrides the existing enumerator for our demo class and returns the upper case of the character in question. 

If we wanted, we could return this class from our GetEnumerator call, but that would be sort of playing a trick on the user of our code. How about if we provide two different enumerators, and then make each available for enumeration in a for…in loop.  Surely that is possible, right?  Of course it is. 

First, we’ll look at the end result and then work our way backwards to see how it was implemented, because you have to play a little trick to expose more than one enumerator for a class:

procedure DoMoreStuff;
var
  C: Char;
  ForInExtraDemo: TForInDemoExtraIterators;
begin

  ForInExtraDemo := TForInDemoExtraIterators.Create('Greetings');
  try
    for C in ForInExtraDemo.AsUpperCase do
    begin
      Write(C, ',');
    end;
    WriteLn;
end;

This little routine will display the string “Greetings” as “G,R,E,E,T,I,N,G,S” in the console.  But note in the for…in loop that the actual class is not passed to the in clause, but a method that returns a “proxy” class that has the desired enumerator attached to it instead.  This is implemented as follows:

TUpperCaseEnumeratorProxy = class
  private
    FOwner: TForInDemo;
  public
    constructor Create(aOwner: TForInDemo);
    function GetEnumerator: TForInDemoClassUpperCaseEnumerator;
  end;
..
constructor TUpperCaseEnumeratorProxy.Create(aOwner: TForInDemo);
begin
  inherited Create;
  FOwner := aOwner
end;

function TUpperCaseEnumeratorProxy.GetEnumerator: TForInDemoClassUpperCaseEnumerator;
begin
  Result := TForInDemoClassUpperCaseEnumerator.Create(FOwner.TheString);
end

This is just another class that can be enumerated – it has a call to GetEnumerator – and thus be returned by a method call on our “real” enumerating class.  It returns an instance of an enumerator called TForInDemoClassUpperCaseEnumerator which we looked at above.  So, if you want to iterate over the upper case version of the strings, you call it as we did in the DoMoreStuff method above.  The trick here is that instead of iterating over the class itself, you iterate over the proxy class using ForInExtraDemo.AsUpperCase.  It’s a neat little trick, eh?

Thus, the enumerating class becomes:

  TForInDemoExtraIterators = class(TForInDemo)
  private
    FUpper: TUpperCaseEnumeratorProxy;
  public
    constructor Create(aString: string);
    property AsUpperCase: TUpperCaseEnumeratorProxy read FUpper;
  end;
...
constructor TForInDemoExtraIterators.Create(aString: string);
begin
  inherited Create(aString);
  FUpper := TUpperCaseEnumeratorProxy.Create(Self);
end;

Conclusion

So, that should give you a little insight into what happens with for…in loops and  how you can create classes that participate automatically.  I’m working towards never using the old for I := 0 to Count –1 do; construct, and making my classes enumeratable.

The code for this article with further examples can be found with my demo code on BitBucket.

Loop Less with IEnumerable and Spring for Delphi

By Nick at January 06, 2013 10:57
Filed Under: Delphi, Software Development

I rave about the Delphi Spring Framework.  But I think my attention to the Dependency Injection Framework – which is only part of it -- has made you guys think that the two are synonymous.  Not true – Spring4D is more than just a Dependency Injection container.  In fact, there is a wealth of other stuff to be found in Spring4D.

Inspired by this StackOverflow question and a thread in the newsgroups, I thought that I’d write an article about a very powerful but not so well known (apparently) feature of Spring4D – IEnumerable<T> and the accompanying container interfaces and classes.

So the StackOverflow question basically asks this: How do I find out the maximum value of an integer in TList<integer>?

Well, the first thing you might do is use a for loop to check each item, and save each one as it gets larger.  Or if you were really tricky, you’d use a for…in statement to find it.  That’s the “straight-up” way to do it.

But that isn’t the real answer to the StackOverflow question.  The real answer is this:

program ListEnumerableDemo;

{$APPTYPE CONSOLE}

{$R *.res}

uses 
    System.SysUtils 
  , Spring.Collections;

var 
  List: IList<Integer>; 
  Enumerable: IEnumerable<integer>;

begin 
  try 
    List := TCollections.CreateList<integer>; 
    List.AddRange([1,6,2,9,54,3,2,7,9,1]);

    Enumerable := List; 
    WriteLn(Enumerable.Max); 
    ReadLn; 
  except 
    on E: Exception do 
      Writeln(E.ClassName, ': ', E.Message); 
  end; 
end. 

 

Now that looks quite a bit different than the code you were thinking of, I’ll bet.   There doesn’t even appear to be any looping going on at all.  There is in the background, but it’s all been abstracted away for you.  You want the maximum value to be found in the list?  Just ask for it.  Cool.

The key part above, of course, is the use of two things.  First, the IList<T> – an interface to a generic list – and secondly, the IEnumerable<T>.  Both of these types are provided by the Delphi Spring Framework.  Both are defined in the Spring.Collections.pas unit.  That unit contains a complete group of collection interfaces – IList<T>, IStack<T> ICollection<T>, etc. – as well as the definition of IEnumerable<T>. 

I’d recommend that you consider using Spring.Collections.pas instead of the Generics.Collections.pas unit which comes with Delphi.  First, it exposes all of the collection types as interfaces, and you should know by now that you should be coding against interfaces and not implementations.  Secondly, each of the types supports the IEnumerable<T> interface, meaning you have the power of this great interface on all of your collections.

We’ll tackle those two things in order.

Spring Collections

The Spring.Collections.pas unit is all you need in your uses clause to avail yourself of all that the Spring collections library provides.  The unit includes the following interfaces along with a class to provide easy access to implementations of these interfaces:

Interface Description
ICollection<T> A Collection is a group of items in no particular order.  You can't insert items into a specific location in a collection, only add or remove them.  A collection can’t be sorted because it has no order.
IList<T> A list is a group of items in a particular order.  Items can be sorted and inserted in particular locations.
IDictionary<TKey, TValue> A dictionary is a data structure that allows you to “look up” items.  Each entry takes a key and a value, and values can be looked up by asking for it via the item’s key.  This is a useful data structure, as any type can be uses as the index, and any type can be stored for lookup.
IStack<T> A stack is a First In, Last Out data structure. Think of a spring-loaded stack of plates at the cafeteria – you “push” plates onto the stack, and then “pop” them off in reverse order.
IQueue<T> A queue is a First In, First Out data structure.  Think of an ordinary line that you wait in, or a tube in which items are inserted at one end and taken out on the other.
ISet<T> A set is a data structure involving membership.  Items are either in the set or out.  A set’s methods allow you to determine the intersection, union, or overlap with any other container.

 

All of these types should be familiar to you – if not, you can certainly read up on them via Google.  The important part is that they are all generic (though there are non-generic types with store TValue as well) and they all implement IEnumerable<T>.

The unit also provides a class called TCollections which has nothing but class methods that return instances of the types listed above.  These methods act as proxies for the constructors of the implementing types.  You can create your own instances if you like, but for the most part, TCollections will do the job of getting an implementation of whatever container interface you want.  For instance, if you want to get a hold of a dictionary, you can do the following:

program ListEnumerableDemo;

{$APPTYPE CONSOLE}

{$R *.res}

uses 
    System.SysUtils 
  , Spring.Collections;

var 
  List: IList<Integer>; 
  Enumerable: IEnumerable<integer>;

begin 
  try 
    List := TCollections.CreateList<integer>; 
    List.AddRange([1,6,2,9,54,3,2,7,9,1]);

    Enumerable := List; 
    WriteLn(Enumerable.Max); 
    ReadLn; 
  except 
    on E: Exception do 
      Writeln(E.ClassName, ': ', E.Message); 
  end; 
end. 

The example above uses TCollections.CreateList<integer> to get an implementation of the IList<T> interface.

The implementations are all in units named Spring.Collections.Stack.pas and the like, but the Spring.Collections.pas unit exposes almost everything you need, and so as a rule, you should only need it in your uses clauses to take advantage of these powerful containers.

 

IEnumerable<T>

Those of you who also use .Net are familiar with IEnumerable already, but perhaps you didn't know that the same power was available to you in your Delphi code.  For those of you not familiar, you are in for a treat.

The IEnumerable<T> interface is implemented by all of the classes discussed in the previous section, and so any of them can be accessed as an IEnumerable<T>. 

Here is the declaration of IEnumerable<T>:

IEnumerable<T> = interface(IEnumerable)
    function GetEnumerator: IEnumerator<T>;
    function AsObject: TObject;
    function TryGetFirst(out value: T): Boolean;
    function TryGetLast(out value: T): Boolean;
    function First: T; overload;
    function First(const predicate: TPredicate<T>): T; overload;
    function FirstOrDefault: T; overload;
    function FirstOrDefault(const defaultValue: T): T; overload;
    function FirstOrDefault(const predicate: TPredicate<T>): T; overload;
    function Last: T; overload;
    function Last(const predicate: TPredicate<T>): T; overload;
    function LastOrDefault: T; overload;
    function LastOrDefault(const defaultValue: T): T; overload;
    function LastOrDefault(const predicate: TPredicate<T>): T; overload;
    function Single: T; overload;
    function Single(const predicate: TPredicate<T>): T; overload;
    function SingleOrDefault: T; overload;
    function SingleOrDefault(const predicate: TPredicate<T>): T; overload;
    function ElementAt(index: Integer): T;
    function ElementAtOrDefault(index: Integer): T;
    function All(const predicate: TPredicate<T>): Boolean;
    function Any(const predicate: TPredicate<T>): Boolean;
    function Contains(const item: T): Boolean; overload;
    function Contains(const item: T; const comparer: IEqualityComparer<T>): Boolean; overload;
    function Min: T;
    function Max: T;
    function Where(const predicate: TPredicate<T>): IEnumerable<T>;
    function Skip(count: Integer): IEnumerable<T>;
    function SkipWhile(const predicate: TPredicate<T>): IEnumerable<T>; overload;
    function SkipWhile(const predicate: TFunc<T, Integer, Boolean>): IEnumerable<T>; overload;
    function Take(count: Integer): IEnumerable<T>;
    function TakeWhile(const predicate: TPredicate<T>): IEnumerable<T>; overload;
    function TakeWhile(const predicate: TFunc<T, Integer, Boolean>): IEnumerable<T>; overload;
    function Concat(const collection: IEnumerable<T>): IEnumerable<T>;
    function Reversed: IEnumerable<T>;
    procedure ForEach(const action: TAction<T>); overload;
    procedure ForEach(const action: TActionProc<T>); overload;
    procedure ForEach(const action: TActionMethod<T>); overload;
    function EqualsTo(const collection: IEnumerable<T>): Boolean; overload;
    function EqualsTo(const collection: IEnumerable<T>; const comparer: IEqualityComparer<T>): Boolean; overload;
    function ToArray: TArray<T>;
    function ToList: IList<T>;
    function ToSet: ISet<T>;
    function GetCount: Integer;
    function GetIsEmpty: Boolean;
    property Count: Integer read GetCount;
    property IsEmpty: Boolean read GetIsEmpty;
  end;

That’s a lot of cool stuff, right?  Many of the methods here are pretty clear -- it's pretty obvious what the Min and Max methods do. But some of the others are a bit trickier.  You can get all of the items.  You can get the First and Last items.  You can get the first x number of items.  You can get the items back out as a List, an Array, or a Set.  And most powerfully, you can get any particular group of the items out using a predicate.

Predicates

What is a predicate?  A predicate is an anonymous function (or any function, really, but in our case it is an anonymous function) that takes a single const parameter of the type in question and returns True or False.

 TPredicate<T> = reference to function(const value: T): Boolean;

It is used with some of the methods of IEnumerable<T> to answer this simple question:  In or out?  If the predicate is true, then the individual item is “in”, or included.  If it is “out”, then the predicate will return False.  So if you want to get all the items in a list strings that contain the letter ‘z’, then you can do the following:

function ContainsLetterZ: IEnumerable<string>;
var
  List: IList<string>;
begin
  List := TCollections.CreateList<string>;
  List.AddRange(['zoo', 'park', 'city', 'town', 'museum', 'jazz festival']);

  Result := List.Where(function(const aString: string): Boolean
                     begin
                       Result := Pos('z', aString) > 0;
                     end);
end;

The above uses the Where method to determine items that should be returned as part of a new IEnumerable<string>.  The above is saying “return to me an enumerable item where all the strings in the list have ‘z’ in them.”

You can do similar things with the TakeWhile method, which returns items from the start of the list as long as the predicate is True, and stops once the predicate is False.   You can determine if a given container has or doesn’t have a given element.  You can Skip over a given number of elements and take the rest.  You can use a predicate to SkipWhile a certain thing is true, and then return the rest once the predicate returns True  Basically, once you have a reference to a collection or any IEnumerable<T> instance, you can get out of it pretty much anything you want.

Something to consider:  If you have a nicely composed class that includes a private IList<T> which gets exposed through proxy methods, then you might want to expose access to the items via a property of type IEnumerable<T> instead of exposing the actual list itself.

And the real power gets unleashed with the very powerful ForEach methods.  Folks have always pined for the lovely ForEach since the days of Borland Pascal’s old TCollection object, and now it’s back in full force, leveraging the power of anonymous methods.  Thus, you can have a collection and do what you please with the items.  Here is a simple example of just outputting them to the console window, but you can have your TAction<T> do anything at all that you like for each (sorry) element in the container.

procedure SimpleForEachDemo;
var
  List: IList<integer>;
  Action: TAction<integer>;
  i: Integer;
begin
  Action := procedure(const aInt: integer) begin Writeln(Format('This number is: %d', [aInt])); end;

  List := TCollections.CreateList<integer>;
  for i := 1 to 10 do
  begin
    List.Add(Random(100));
  end;

  List.ForEach(Action);
end;

So, basically you have a lot of untapped power there in Spring.Collections.pas, eh?  The use of IEnumerable<T> and predicates ought to transform your code and change the way you look for things in lists and collections.  If you aren’t using these powerful tools yet, I strongly recommend that you add them to your tool chest.

I’ve written a pretty thorough example application for IEnumerable<T> and put it up on BitBucket.  I also have some pretty simple examples showing predicates at work.

Remember, the Delphi Spring Framework is more than a Dependency Injection container.  And there’s more to it than the container classes as well.  I strongly recommend that you start treating Spring4D like part of the Delphi Runtime Library.  Heck, I wish Embarcadero would do just that.

Flotsam and Jetsam #72

By Nick at January 04, 2013 11:21
Filed Under: Delphi, Flotsam and Jetsam, Software Development
  • Am I weird?  One of the first things I do when I install Delphi is to turn off Brace Matching and Line Highlighting.  I find both of these features incredibly distracting, particularly the Brace Highlighting, which makes it impossible to see where the caret is in the text. 
  • This article by Hal Berenson should make interesting reading for Delphi folks interested in the economics of development tool vending and the business models around them.  Delphi isn’t mentioned, but it does discuss the changing business model of Visual Studio from within Microsoft and how Adobe’s tool business put pressure on MS and actually changed how they did business.  MS’s  Interesting stuff.
  • I love Twitter and try to tweet pretty frequently (I’d be honored if you followed me).  One of the fun part of tweeting is seeing the creative and interesting use of hashtags.   One current hashtag that is going around and that is of interest to us Delphi developers is #code2012.  In it, folks are putting the names of the languages that they coded in during the past year.  Someone has a nice graphic that shows the relative popularity – and Delphi isn’t doing too badly.  I just tweeted to help make that Delphi circle just a little bigger.  Winking smile
  • Holy cow, I feel like I did when Buffy ended – stunned and saddened.   Žarko Gajić is moving on from his position as the guide for About.Com Delphi.  Žarko has been doing that job for 15 years, and I’m willing to bet that his site is as common a search result as any in the community.  Well done, Žarko, and good luck in your future, Delphi-related endeavors.  And hey, the door is open – anyone willing to step into Žarko’s shoes?

Flotsam and Jetsam #71

By Nick at December 26, 2012 01:40
Filed Under: Delphi, Flotsam and Jetsam, General, Software Development
  • I’ve shamelessly tweeted it a couple of times, and I’ll promote it here as well – I’ve created a Bookstore page here containing a list of books that I think are must-reads for all developers.  What books would you add to the list?
  • Have you upgraded to Delphi XE3 yet? If you haven't, please do.
  • Okay, I need some advice:  I want to learn a functional programming language, but which one?  Clojure?  Haskell? F#?  What? 
  • I need some more advice:  I have a good working knowledge of SQL and SQL Server.  But I’m going to need to become a SQL Server 2008 expert in the coming months.  Can any of you fine people recommend the best book or other resource for going from the basics to really being a guru?  Again, I’m looking specifically at T-SQL and SQL Server itself.

Blast from the Past: Developers and Economics

By Nick at December 04, 2012 11:45
Filed Under: Software Development, Delphi

Here's another article from my series at CodeFez -- and here's the response that Steve Teixeira wrote to it.  The comments on both are a pretty interesting discussion.

I never cease to be amazed at how little the average developer knows about economics. I mean, I don't claim to be an expert, but I have taken a college class or two and read up on the basics. Even just understanding the basics, though, gives one surprising insight into why things happen the way they do in the marketplace.

For instance, we are in the process of hiring a new developer at my company. We figured out what qualifications we were looking for and determined about how much salary we wanted to pay. It quickly become apparent, however, that we weren't offering a high enough salary to attract the caliber of candidates we wanted. So what I did was to go on the newsgroups and start whining about not being able to find any good Delphi programmers. Okay, no, I didn't really do that. What we did, of course, was to increase the salary that we were offering. Simple supply and demand issue: There wasn't enough of a supply of good Delphi programmers at the price we wanted to pay, so the solution is to be willing to pay more – a no-brainer decision, really. Once we did that, we found that we have been able to find plenty of valuable candidates. Simple economics.

One common area that I see developers totally misunderstand is that of Delphi pricing. One thing you learn in Economics 101 is that the vast majority of companies are “price searchers”. That is, they are constantly searching for a price that will maximize their profits. (Some companies, mainly producers of commodities, are “price takers”. That is, they take whatever price is offered. Farmers are a good example. A corn farmer can only sell his corn at market price. If he asks for more, the market will simply buy corn from another farmer that will take the offered price). Borland is definitely a price searcher. They can set their prices as they please, and will do so to maximize profit. Of course, the market will respond to any particular price by demanding a certain number of units at that price. Price searchers are constantly adjusting prices to maximize the amount of money they make.

Note that they don't set price to maximize revenue, but rather profit. The cost of goods sold is a factor here as is the cost of simply having customers. Sometimes a company will actually price a product in order to limit the number of customers they have in order to maximize profits as sometimes having additional customers causes decreased profits. (That may be a bit counter-intuitive, but think of a product that has high production and support costs.) So for example, sometimes doubling your price can increase profits even though it drastically reduces sales. If doubling the price cuts the number of customers you have in half, but also cuts your production and support costs in half as well, your profit increases. (This is a very simple example, and it is actually hopelessly more complicated than that, but you hopefully get the basic idea).

So Borland, having learned from years of experience and copious sales data, is quite aware of what effect various prices have on sales. No doubt by now they have a pretty good idea what price will maximize their profits and how price changes will effect sales.

Where it gets really interesting is pricing outside of the United States. Europe, of example, is a completely different market than the US. Taxes, the demand curve, and the number of potential customers are all different. Borland clearly believes that they need to – and can – charge more in Europe than in the US. The price difference is not related to the exchange rate between the Euro and the Dollar; it has everything to do with maximizing profits. Clearly Borland believes that a higher price in Europe – again, a completely different market – will mean higher profits. That's why Delphi costs more in Europe. I suppose Europeans could view this as “price gouging”, but in reality, it's just the market signaling to Borland that it will bear a higher price than will the American market. Simple economics.

Another economic blunder that developers frequently make is ignoring economies of scale. Borland is a big company that is publicly traded. Many Delphi developers work in small, private companies. Borland has legal obligations, overhead costs, and market demands that most little-shop developers don't even know about, much less take into consideration. Borland's main competition is one of the largest corporations in the world. Borland faces investors who expect a return. Borland has to deal with major entities in the media that can write things that can have profound effects on Borland's business. All of this combines to make running Borland a complex and difficult task that most of us simply don't comprehend.

So I love it when a developer posts in the newsgroups something like this: “Borland should just hire two college students to go through and fix all the Delphi bugs in Quality Central.” Well, that sounds great, but is clearly isn't that simple. First, fixing bugs in a big product like Delphi is no small, trivial task. Finding people with the talent and skill to do Delphi bug-fixing isn't easy. And they certainly aren't going to be cheap. The notion that some college interns can do it is quite naïve. The economic blunder comes, though, in thinking that the cost of fixing all those bugs is merely the salary of a couple of developers. First, employees aren't cheap, no matter who you hire. Human capital is by far the most costly – and valuable – part of doing business. Secondly, I don't know what your development process is like, but bug fixing at Borland is more than a guy hacking out some code. Every fix has to be extensively tested for efficacy and correctness, and then the whole product has to be regression tested to ensure that any given fix doesn't actually break something else. Fixes need to be incorporated into shipping product and distributed to existing customers. The documentation needs to be updated. And who know what else needs to be done? The point is this: the costs of things that many people think are small are in fact much larger than the average developer appears to realize.

The economics of running a business like Borland isn't something about which I claim to be an expert. But I do know that I don't know enough to be able to claim to know better than Borland. Something to consider before you fire off a post in the newsgroups that starts out “Borland ought to just....”

Blast from the Past: Takes One to Know One

By Nick at November 25, 2012 13:15
Filed Under: Delphi, Leadership, Software Development, TechBiz

This one is a Blast from the Past -- I originally wrote and posted it on December 15, 2005 -- but it is as true today as it was then.  I even considered palming it off as fresh material. Smile

It's a standard Dilbert joke that managers are idiots.  One doesn't have to hang around programmers too long to find out that many of them work for managers that don't have a clue about developing software and thus make many a nutty decision based on profound ignorance.  Plenty of  Delphi fans have had a boss that follows the "Nobody ever got fired for choosing Microsoft Development tools" rule and choose Visual Basic as a corporate standard. <shudder>  And the old adage states that programmers make crappy managers.

So, I guess, based on the above, it's impossible for someone to be a good manager of programmers.  If one doesn't know anything about programming and has never been a programmer, then apparently, he will suck as a manager.  And if one has been a programmer, and is so good at it that he gets promoted to be a manager, he,too, will suck as a manager.  Sounds like a lose/lose situation all around --   programmers doomed to a life of sucky supervisors.

Well, I'm not buying it.  Surely somewhere, somebody is managing programmers well.  Somebody has to be leading folks to build some of the insanely good software projects that are going on out there.  So, what does it take to manage programmers well?  Good question.  I'd say that such skills and capabilities exist.  I'd also say that they are, sadly, in relatively short supply.  Too many Dilbert strips end up on too many cubicles in software development shops.

First, to be a good manager of programmers you have to be,well, a good manager.  That's easier than people think, really.  Here's my basic list of things one can do and not do to be a good manager:

  • Place the careers of the people that work for you above your own.  Never, ever, ever, ever, ever take a dump on an employee to make yourself look good to your boss.  Always let the boss take a dump on you instead of your employee. Take responsibility for everything bad that happens under your watch.  Dole out all the credit for good things that happen to your people.  If you have some bizarre, overwhelming need to impress and brown-nose your boss, let your employees make you look good.  It's your job to make your employees happy and productive.  It's not your job to get promoted.  (And do I need to say that if your employees are happy and motivated, then they'll do a good job, which means you are doing a good job?)
  • Place the needs of the employees over your own.  What's the quickest way for a Marine Corps officer to be considered the biggest jerk since Josef Stalin? Get in the chow line ahead of his Marines.  Officers don't eat until the troops do.  Take the same attitude, and your people will love you and work hard for you.  Give them the good computers.  Give them the good chairs.  Don't take a perk for yourself until they all have it.  Believe me -- they will notice this.  Another way to state this is don't ask your employees to do anything you yourself aren't willing to do. If you want your folks to work 12 hours a day, you need to be there 13 hours a day.
  • Recognize that your employees know what they are talking about and might actually know more about some things than you do.  (If they don't know what they are talking about and they don't know more about some things than you do,  then you need to get new employees).  If your employees seem to think that the WonderWidget is a much better solution to a problem than the SuperSprocket, then, hey,  maybe, just maybe, they are right.  Just because you read about the SuperSprocket in some magazine that takes $4.6 million dollars a year in advertising from SuperSprocket, Inc., doesn't mean that is the way to go. 
  • As a follow on to that, don't try to impress your employees with your knowledge.  Don't spout buzzwords unless you know what they mean. They probably are going to think that you are an idiot anyway, so feel free to appear to be ignorant about things that, well, you are ignorant about.  If you don't have a clue about what the best printer is for the needs of your team, then let the folks on your team that do know about such things choose the printer.  If you don't know the answer to something, say so.  The quickest way to be thought an idiot is to try to act like you know what you are talking about when you don't.
  • Manage yourself out of  a job.  The best managers are the ones that sit in their office all day surfing the internet because they've set things up so that their people can take care of everything and thus they don't have anything to do.  People love being the ones with the power, authority and skill to do the work. If you are in their shorts all day, making all the decisions, doing all the work, and taking all the credit, you will be a crappy manager.  Once you've managed yourself out of a job, then, besides surfing the net, you can spend all your time making things even better for your employees and protecting them from the foibles of your boss. 
  • Encourage your employees to tell you what is bugging them.  When I was running a 24/7 Intelligence Watch, I told my people that if they found a Dilbert cartoon that exactly described a stupid, irritating, or aggravating situation in our organization or something that I was doing that was "pointy-haired-boss-ish", they could bring it to me or put it on my desk anonymously.  If you are totally committed to the first two items on this list, they will come to you. If you aren't, they never will.  And if your employees aren't bringing issues and complaints and problems to you, then you have a big problem.
  • Reward your employees with what they want to be rewarded with.  Frankly, this is usually good old cash money. But if you can't do that,  perhaps they want better computers, a nicer desk chair, a day off, whatever.  If you want to reward someone, find out what they want and give it to them.  But please, PLEASE -- I'm begging you here -- do not call a big meeting and pass out a "Worker of the Week" award with some cheesy certificate ginned up with Microsoft Publisher.  When I was in the Navy and at a joint command, I had an Air Force Colonel that did this, and he was universally mocked and reviled for it. Everyone thought it was a joke.  No one wanted that silly certificate and everyone hoped and prayed that they wouldn't "win" the thing.  Those that did posted them like they post Dilbert cartoons on their cubicles -- sort of like a badge of "dishonor".

Now, that's all general stuff.  It applies to all managers, whether they lead a team of auto workers or a group of Delphi programmers.  What does it take to manage programmers well?

  • I think that to be a good manager of programmers, you have to be, or at least have been, a programmer yourself.  This goes against the conventional wisdom, I know, but I think that in order to understand the way programmers work, you really have to have done it yourself.  It's true that many programmers would make bad managers, but it doesn't follow that every programmer guarantees that one will be a bad manager.  Programming is one of those strange professions that mixes right- and left-brained skills.  To program well, you have to have an ordered, mathematically oriented mind, but at the same time you have to come up with artistic, creative solutions to puzzles and problems.  One really needs to be one to understand one.  Now the hard part here is that most programmers don't want to be managers. Alas -- a quandry there, eh?  Well, if you run across one thatdoes, don't hesitate to consider it.  If you are a programmer and want to be a manager, let your bosses know, they'll probably be happy to hear it.
  • Give programmers what they want:  challenging work, a quite place to do that work, a good fast computer, a good salary, and the opportunity to expand their skillset.  Don't be cheap on these things.  This may cost a bit more,but you'll make it back in spades.
  • To as large a degree as possible, let programmers choose the tools that they use.  I know, I know, this isn't always possible.  Sometimes those decisions are made above your pay grade.  But then again, if you use Delphi under the table to produce a solution twice as fast for half the cost, then maybe Delphi won't be under the table for long.  If one of your guys wants to try to build that new intranet application in Ruby On Rails, let him.  Why not? Who's going to know?  If it works and gets deployed early, it's likely that no one will care what tool or language was used to make it, and now you have a new skill in your quiver.
  • Be flexible.  Some programmers do their best work between 10:00pm and 04:00am.  Let them.  Some hate to wear ties, dress shirts, khakis, etc.  Don't make them.  Some are flat out nuts.  Let them be.  Nothing wrong with all of that as long as they produce good code, eh?

Okay, that's a pretty good list.  I've been on both sides of the fence, and as a consultant, I see all sorts of management types and methods.  I deal with programmers on a daily basis, and I are one myself, so I think I have a pretty good grip on what's going on from a lot of angles.  I'm sure you all will come up with more stuff and comment on it.  Please do.  After all, I'm not an expert on this stuff and I only write this to try to make you look good.  ;-)

My Book

A Pithy Quote for You

"Science is the belief in the ignorance of experts."    –  Richard P. Feynman

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.