2009-05-31

Generation gap - update

Martin wrote to me and explained something I wasn't aware of. He doesn't catalogue best practises or only the ones he likes, he is cataloguing all patterns he can find.

He said he would rather someone made an informed bad decision than an uninformed good one. Not quite sure I agree with that either :-)

2009-05-23

Generation gap

I have just read this blog by Martin Fowler. I like a lot of what Martin writes, but this is not one of them.

The article suggests using inheritance to separate code-generated classes and manually written classes. You would descend from a code-generated class instead of trying to modify the code-generated source.

The problems I see with this are

Attributes


If I have a descendant of a code-generated class how do I attach .NET attributes to members? I’d have to override them and add the attribute in the descendant which would mean all of my members need to be virtual. Obviously this wouldn’t work for Private members.

I expect you’d have to attach all of your attributes in the tool which generates the source code, but I don’t like this idea. I will explain why later.

Sealed / final


What if we want to create a sealed/final class? We can’t. What if we want a specific member to be sealed/final? Then we couldn’t add attributes to the members.

Partial


Microsoft introduced Partial classes/methods to try to get around the problem of mixing code-generated and manually written code.

public class Person
{
  protected partial void BeforeSetName(ref string newValue);

  private string name;
  public string Name
  {  
    get { return name; }
    set
    {
      BeforeSetName(ref value);
      name = value;
    }
  }
}


The manually written part of the class can now optionally implement BeforeSetName

  public partial void BeforeSetName(ref string newValue)
  {
    if (newValue == null)
      newValue = "";
  }


and to decorate items with meta-data....

[MetadataClass(typeof(PersonMetaData))]
public class Person
{
  ...
}

public class PersonMetaData
{
  [SomeAttributeINeed]
  public string Name { get; set; }
}



I think the partial methods idea is a good one, but meta-data classes? Yuck! They violate the DRY principle, whenever I change the real Person class I have to update the PersonMetaData class too.

Solution


So, what is the solution? How about this?
Code generation tools should be good at what they do!

When I specified the code-generation for ECO MOdeler there were no partial classes/methods, everything had to be generated to a single file which had to mix manually written and auto-generated code together...


  //User code here
  #region ECO Modeler generated
    ...
  #endregion
  //User code here


The code-generator would only rip out and replace code within those regions, leaving the user written code intact. Now at the time partial classes didn’t exist so if I had the chance I would now most likely use BeforeX AfterX type partial methods instead of using *some* regions, but in places I still think they would be necessary.

For example I think that some attributes are quite valid to be entered into your code-generator and some aren’t. In such a case I would expect to see something like this

  #region auto-generated
  [SomeAttributeFromCodeGeneration]
  #endregion
  [SomeManuallyAddedAttribute]
  public string Name { get; set; }


One example of what is or is not relevant to your code-generator is interface realisation. The modeller I was using defined the business classes, from the point of view of the people within the business. Now if one of those classes needs to implement IComparable<T> this is an implementation detail and doesn’t belong in the business model (from which you generate source code) because it will just muddy the information presented to non programmers. ECO Modeler handled this nicely.

Step 1: Code is generated

public class Person : ICloneable, IRoleHolder
{
  ...
}


Step 2: Programmer implements IComparable<T>

public class Person : ICloneable, IComparable<Person>, IRoleHolder
{
  ...
}


Step 3: Model is changed so that Person realises the IStockHolder interface and removes the ICloneable interface

public class Person : IComparable<Person>, IRoleHolder, IStockHolder
{
  ...
}


ECO Modeler did this by storing information about which interfaces it added to the class last time it generated code. If they are no longer in the model they need to come out, any new ones in the model need to be added, and anything else needs to be left alone.

My point here really is this. Why should we be writing programming patterns which do not solve the problem at hand? Why develop programming patterns around holes in our technology? If it is causing us problems then our technology should improve! Code generators should be capable of parsing source code as well as generating it. They should be able to work in their own code arena without messing up ours!

So on this one I disagree, the problem lies in the tools and should be addressed there, not addressed in the coding of our applications.

2009-05-16

I've just ordered some books

Someone kindly gave me a £100 gift certificate for Amazon.  I posted a request for book suggestions to 3 groups where I would expect to receive good recommendations


I received a lot of recommendations (thanks everyone!) - here are the ones I have bought:

  Building Domain Specific Languages in Boo
  Writing Secure Code, Second Edition
  Analysis Patterns Reusable Object Models (OBT)
  How to Solve It: A New Aspect of Mathematical Method
  Object Oriented Project Design
  Extreme Programming Explained: Embrace Change
  Getting Things Done: How to Achieve Stress-free Productivity
  
Here are the books that made it onto my "future" list which I didn't have enough cash for this time around.

  http://www.amazon.co.uk/gp/registry/wishlist/13GXONVVMLHZZ

I generally went for the cheaper books first, so that I could get as much input as possible.  "The art of computer programming" looks good but I'd have hardly been able to get much else - especially as I considered Oren's book on DSLs a "must buy". 

The "Patterns of software architecture" series look good, although I suspect the 3rd in the series is the equivalent of "Nightmare on Elm Street 2" because the table of contents don't look too good and all the second hand prices are much lower :-)

I wish I could just download this stuff straight into my head!  Reading is so time consuming.


2009-05-14

MUMS - How good you are when things go wrong

I always say this so I have probably blogged it in the past, in light of my MOZY incident probably recently, but "It's not how good you are when things go right, it's how good you are when things go wrong".

My wife and I are (unexpectedly) expecting our 4th baby.  We paid for a private scan at MUMS last week.  Part of the package is a DVD of the scan.  The scan was a really good one, but unfortunately when we got home we realised our DVD was completely blank.

I phone them up and they offered a free scan.  I was still disappointed because there was a beautiful part of our previous scan that would be lost, where we were zoomed right into our baby's hand as she repeatedly clenched and reopened her hand, but I agreed because at least we would have something.

When we had our scan they gave us probably double the normal amount of time.  In addition to that they upgraded our scan from a plain ultra sound to one of those 4D scans.  We were given twice as many printed photos of the scan, and absolutely loads of still images were written to the DVD.  They more than made up for the initial unfortunate mistake.

MUMS is a good company, because they are good when things go wrong!

2009-05-13

Bletchley Park

If you are unaware Bletchley Park played a vital part in World War II, it undoubtedly shortened the war (possibly by years) by decoding intercepted Nazi messages which had been encoded on the Enigma machine.  This site is credited with being the place where the first programmable computer was used to crack the more complex Lorenz Cipher Machine.

According to this petition number 10 Downing Street...


...the park is severly lacking in funds and has at best 2 to 3 years before it is forced to close down.  The idea that a site with such a historical significance could be bulldozed and redeveloped is astonishing!

Please help to preserve this computer related historical UK site by making as many UK residents as possible aware of this petition!


2009-05-08

Locking in ECO 5

Jonas has just added the following feature to ECO 5 which should turn up in the next build.

Let's say you have a package with a single class LockObject in it. This LockObject must have TimeStamp locking, but you use this package in many applications.  In ECO 5 you can set the default locking mode for a package.

Now let's say you have multiple packages that you use in many applications and the locking type is different per app.  App 1 uses AllMembers locking, App 2 uses no locking at all; how can you specify the locking type?  Now you can add a .NET attribute to the top of your application specific EcoSpace class....

[UmlTaggedValue("Eco.OptimisticLocking", "AllMembers")]
public class Application1EcoSpace : DefaultEcoSpace
{
  etc....
}

Locking is determined like so:
  1. The kind specified on the class itself.
  2. The kind specified on any super class.
  3. The kind specified on the package.
  4. The kind specified on the EcoSpace.
Someone I know recently got stung by this, so I thought I’d mention it...

static void Main(string[] args)
{
  int a = 1;
  int b = a;
  Console.WriteLine(AreSame(a, b).ToString());
  Console.ReadLine();
}

static bool AreSame(object a, object b)
{
  return a == b;
}


What’s the output to the console? Does a equal b? Even if you didn’t know the answer you will have guessed it is False otherwise this blog would be totally pointless!

It’s false because the parameter types of AreSame are both "object". For a value type such as "int" to be passed as an object it needs to be boxed, so a new object instance is created which stores the value "1", but this is done for both parameters so we end up with 2 new instances both holding the value 1.

1 equals 1 for value types but the default comparison for System.Object is to compare references. If they are not the exact same object (and in this case they are not) then the result is false. Now if we typecast both a and b back to integers this would pass, but the fact that we are using System.Object parameters suggests we don’t know the true type. Instead we need to use Object.Equals, because no matter what the original type is it should have a correct implementation of Equals().

static bool AreSame(object a, object b)
{
  if (a == null && b == null)
    return true;
  if (a == null || b == null)
    return false;
  return a.Equals(b);
}


So the moral of the story is this. If ever you are passed "object" references make sure you check for equality using Equals!

2009-05-07

I don't like AccuRev

A company I have been contracting for decided to use AccuRev as its source control solution. I've not liked it from the start because it is too much work, the terminology in it is quite frankly stupid, and it is far too "chatty" when you work remotely.  Anyway, for some time now I have suspected it has been losing source code. On a few occasions I have found myself looking at source code and thinking "I could swear I have already done this!".

Well, last week I wrote some pretty nice code which used multiple threads in a test case to ensure I experienced expected behavior when multiple users update the same objects in a database.  Today one of the other programmers said to me "Didn't you write more tests than this?" and showed me the tests.  My multi-threaded tests were gone!

I knew it all along, but now it is indesputible, AccuRev has been losing my work!

2009-05-06

The Pragmatic Programmer

My copy of this book has just turned up. I am book hungry these days, can't wait to read it :-)

2009-05-04

Connascence

I’ve just finished reading What every programmer should know about object oriented design. The first couple of sections are a bit useless really, but the 3rd section is very good.

I particularly liked the section on the difference types of connascence in software. There’s some basic information about it here if you fancy a brief overview of what it is about.

It’s a really good book, I recommend you read it! Should only take a day if you only read the 3rd section.

I've just ordered a Java book

http://java.sun.com/blueprints/corej2eepatterns/index.html

It was only $0.41 used in the USA, came to about £6 with posting to the UK. I don't write Java and at the moment have no interest in learning it, but I expect I will be able to read it without problems (never really looked at it).

So why did I buy this book? Because it is about this...

Patterns

That's why :-)

Prism - Invariants, and pre/post conditions - update

Just found out that I can do this too

public invariants
  Overdraft >= 0 : ’OverdraftGreaterThanOrEqualToZero’;
  Balance + Overdraft >= 0 : ’BalancePlusOverDraftGreaterThanOrEqualToZero’;
end;


Then in my handler routine I get that message!

if not IsValid then
  throw new Exception(ErrorMessage);


Excellent :-)

Prism - Invariants, and pre/post conditions

I’ve been looking at Prism some more recently. I’m a bit annoyed with myself really because someone has been telling me to look at it for years but I wanted to concentrate on C#. Now that I am looking at

it I see things in there which I really like.

Recently I am looking at invariants, pre-conditions, and post-conditions. First let me show you the invariant support. An invariant is like a class constraint, it specifies a condition which must be true

but when must it be true?

type
  BankAccount = public class
  public
    property Balance : Decimal read write;
  public invariants
    Balance >= 0;
  end;


The invariant is enforced each time a public method exits. Actually it is enforced after the post-conditions of a public method exits but we don’t have any post conditions yet.

class method ConsoleApp.Main;
begin
  var account : BankAccount := new BankAccount();

  //The next line throws an assertion error
  account.Balance := -1;
end;


Property getters and setters are considered methods, so as long as you aren’t publically exposing a field (which you should never do) then you are protected. In the following example the setter for Balance is Private but it is set via a public constructor, so the assertion is checked when the public constructor exits.

type
  BankAccount = public class
  public
    constructor (OpeningBalance : Decimal);
    property Balance : Decimal read private write;
  public invariants
    Balance >= 0;
  end;

implementation


constructor BankAccount(OpeningBalance : Decimal);
begin
  Balance := OpeningBalance;
end;


class method ConsoleApp.Main;
begin
  var account : BankAccount := new BankAccount(-1);
end;


Obviously we can’t set a balance for an account directly because its setter is private, so let’s add another feature we could use instead. Next I will add a Withdraw method with overdraft facility.

type
  BankAccount = public class
  public
    constructor (OpeningBalance : Decimal);
    property Balance : Decimal read private write;

    method Withdraw(Amount : Decimal);
    property Overdraft : Decimal read write;
  public invariants
    Balance + Overdraft >= 0;
    Overdraft >= 0;
  end;

implementation


constructor BankAccount(OpeningBalance : Decimal);
begin
  Balance := OpeningBalance;
end;

method BankAccount.Withdraw(Amount : Decimal);
begin
  Balance := Balance - Amount;
end;


As you can see the invariants of this class are that the Overdraft must be >= 0 and the Balance plus the Overdraft must be >= 0. The following program illustrates use of this.

class method ConsoleApp.Main;
begin
  var account : BankAccount := new BankAccount(10);
  account.Overdraft := 10;
  account.Withdraw(20);

  //Outputs -10
  Console.WriteLine("Balance : " + account.Balance.ToString);

  //The next line throws an assertion error
  account.Withdraw(1);
end;


So that’s an invariant now let’s look at pre-conditions. The Withdraw method would currently accept an Amount of zero which obviously makes no sense, what’s worse though is that it could accept a negative number and actually increment the balance so let’s add a pre-condition to prevent this.

constructor BankAccount(OpeningBalance : Decimal);
require
  OpeningBalance >= 0;
begin
  Balance := OpeningBalance;
end;

method BankAccount.Withdraw(Amount : Decimal);
require
  Amount > 0;
begin
  Balance := Balance - Amount;
end;


Now if I try to create the bank account with a negative opening balance, or if I try to withdraw an amount of money that is not greater than zero I will experience an assertion. It’s possible also to add post-conditions by using the "ensure" keyword.

method BankAccount.Withdraw(Amount : Decimal);
require
  Amount > 0;
begin
  Balance := Balance - Amount;
ensure
  Balance = old Balance - Amount;
end;


Note here that I use "old Balance", which is the value that Balance was when the method was called. The combination of pre/post conditions say that "If you pass me a positive amount of money I will decrement the Balance by that exact amount".

I haven’t finished yet! The default behaviour is to use Debug.Assert whenever an invariant is broken, a pre-condition is not met, or a post-condition is not satisfied. It is possible to change this behaviour for a Release build so that your invariants are not only checked during debugging. This is particularly useful when you are persisting and retrieving objects’ state in a database, if another application bypasses your business classes and writes directly to the database your invariants ensure that your application fails immediately rather than working with an invalid state and possibly causing more invalid state elsewhere. To do this create a static class like so

type
  ClassContractChecker = public static class
  private
  protected
  public
    class method Check(IsValid : Boolean; ErrorMessage : String);
  end;

implementation

class method ClassContractChecker.Check(IsValid : Boolean; ErrorMessage : String);
begin
  if not IsValid then
    raise new Exception(’Unexpected class contract violation ’ + ErrorMessage);
end;


Then in the project’s properties look on the DEBUG tab and enter

  Assertion class name : MyNameSpace.ClassContractChecker
  Assertion method : Check


NOTE: This is a separate setting for each build configuration, so set it to RELEASE

Now instead of using Debug.Assert any time something goes wrong the Prism compiler will execute this static method so that we can throw an exception instead (currently this doesn’t work for RELEASE builds, I have reported it as a bug so hopefully it will be fixed).

This kind of programming allows us to identify errors in our objects’ states early on. Using this approach will cause an app to "fail hard" at the first sign of something unexpected happening. This may sound harsh at first but the app failing immediately and prominently is better than it being wrong for a long period of time and causing weird side effects in your logic which could end up with nonesense data - that would be a much worse situation.