2009-05-04

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.

2009-04-30

Injecting into the ECO cache

In my previous post I showed an interface ILockable. The actual interface is

public interface ILockable
{
  Guid GetLockID();
  Type GetLockObjectType();
}


Any lockable resource implements this interface. In its constructor it creates an instance of a class which descends from LockObject, a Document class for example would create an instance of DocumentLockObject which descends from LockObject. The "Document" class would store away the ID of the DocumentLockObject in a private attribute. Now when my LockingService is asked to lock multiple (un-related) instances which implement ILockable I want to do this

1: Create a new EcoSpace
2: Load objects efficiently
3: Get locks
4: Update the DB
5: Dispose of the EcoSpace

If I experience an OptimisticLockingException then loop and try again. The item I would like to discuss is #2, "Load objects efficiently". In my model a LockObject has a *--1 association to Session identifying which session has locked it, I want to ensure that the LockObject + LockObject.ExclusiveLockedSession instances are loaded as quickly as possible. If I have a collection of LockObject I can easily use the following code to efficiently load all relevant sessions

objectSpace.EnsureRelatedObjects(result, x => x.ExclusiveLockedSession);


This extension method assumes that the association name is the same as the class’s property name and is implemented like so:

public static class PersistenceServiceExtender
{
  public static void EnsureRelatedObjects<T>(
    this IEcoServiceProvider instance,
    IEnumerable<T> objects,
    Expression<Func<T, object>> member
  ) where T : IEcoObject
  {
    MemberExpression memberExpression = (MemberExpression)member.Body;
    var ps = instance.GetEcoService<IPersistenceService>();
    ps.EnsureRelatedObjects(objects, memberExpression.Member.Name);
  }
}


This is possible because I have a list of ECO class instances as my basis and can therefore rely on the ExclusiveLockedSession association to get ECO to quickly load the related objects. The problem I need to solve is this: given an interface (ILockable) how do I get all LockObjects? Remember that these lockable objects (Document, Image, Video, etc) have no common superclass and therefore have no common association to their LockObject, and this is exactly why I wanted to know the LockObject’s primary key in my last post.

Given a collection of ILockable I am able to determine 2 things.
1: The primary key of its LockObject
2: The exact type of the LockObject it refers to (DocumentLockObject, VideoLockObject, etc).

In my new EcoSpace instance I can now inject locators for these objects directly into the cache.

private IEnumerable<LockObject> GetLockObjects(IEcoServiceProvider objectSpace, IEnumerable<ILockable> subjects)
{
  //Get a reference to the cache content service so that we can inject
  var cache = objectSpace.GetEcoService<ICacheContentService>();

  //Create an IObjectList, a list of object locators of type LockObjecct
  var variableFactoryService = objectSpace.GetEcoService<IVariableFactoryService>();
  IObjectList locators = variableFactoryService.CreateTypedObjectList(typeof(LockObject), false);

  //Inject each locator directly into the cache, avoiding the DB completely
  foreach (var subject in subjects)
  {
    Guid lockObjectID = subject.GetLockObjectID();
    Type lockObjectType = subject.GetLockObjectType();
    IObject lockObjectLocator = cache.GetObject(lockObjectID, lockObjectType);
    locators.Add(lockObjectLocator);
  }

  //Now I have a list of locators I can fetch the instances from
  //the DB in an efficient way by converting them to IList<LockObject>
  var result = locators.GetAsIList<LockObject>();

  //And finally I ensure related objects
  objectSpace.EnsureRelatedObjects(result, x => x.ExclusiveLockedSession);
  return result;
}

2009-04-27

Setting the ID of an ECO object before it is saved

This might seem like a bit of an odd requirement. I am currently implementing an offline pessimistic locking service in an ECO app. This will mean that I can use a LockingService to place read/write locks on objects. As usual I have gone for an interface approach (ILockable) rather than making all my lockable classes descend from a base Lockable class. Remember, it's what I DO, not what I AM.

The idea is that I have a Lockable object which holds a list of Sessions. These Sessions indicate who has a read lock, and who has a write lock on the object. Each ILockable business entity will create its own private instance of Lockable when it is created.

The thing is, this application will at times need to lock thousands of objects in as little time as possible. As there is no common ancester for these ILockable classes I can't just use EnsureRelatedObjects to traverse an association name and load all LockObject instances in a single select.

I decided that what I needed was to be able to get the ID of the privately owned LockObject and store it in the ILockable entity. This way ILockable only needs to look like this

public interface ILockable
{
  Guid GetLockID();
}


I can then
  1. Make a list of lock ID's I need to lock.
  2. Inject each into the EcoSpace cache directly, because I know that each ID is always a LockObject.
  3. Add the resulting IObject to an IObjectList.
  4. Call IPersistenceService.EnsureRange on the IObjectList to fetch them all at once.

The key to this approach is to know the ID of the LockObject from the owning ILockable without having to navigate the association self.LockObject in order to retrieve it. Now this isn't really that difficult if the object has already been saved because you can use the IExternalIdService to get the object's primary key.

However, the LockObject is created WITH the ILockable object, we can't get the LockObjects key yet because it hasn't been saved. We can't save the LockObject first because the app might never save the ILockable entity and we'd get an orphaned LockObject.

So, here is a little trick to set the primary key of a new ECO object instance before you have saved it. This way we know what the primary key will be before we even save it. First I created an interface like so:


public interface IObjectIdentityService
{
  void SetIdentity(IObjectProvider instance, Guid identity);
}

Then in the LockObject class I added the following code to the IEcoServiceProvider (new object instance) constructor.


ID = Guid.NewGuid(); //Just a GUID attribute on the class
serviceProvider.GetEcoService<IObjectIdentityService>()
  .SetIdentity(this, ID);

That's all there is to it. Obviously I need the key on my objects to be a GUID because there is no way of getting an integer value you can be sure is unique. Finally here is the implementation of the IObjectIdentityService, I implemented it within my EcoSpace to gain access to FrontsidePolicy.ObjectRepresentationProvider, but I could have easily passed this in a constructor:


void IObjectIdentityService.SetIdentity(IObjectProvider instance, Guid identity)
{
  if (!instance.AsIObject().ServiceProvider.GetEcoService<IStateService>().IsNew(instance))
    throw new InvalidOperationException("Instance must be new");

  Locator locator = FrontsidePolicy.ObjectRepresentationProvider.LocatorForIObject(instance.AsIObject().ObjectInstance);
  ObjectId newID = new DefaultId(identity, locator.Id.ClassId);
  FrontsidePolicy.Cache.SetObjectId(locator, newID);
}

Using a GUID as the key in ECO

  1. Drop a DefaultORMappingBuilder component next to your persistence mapper.
  2. Point PersistenceMapperxxxxx1.NewMappingProvider and RuntimeMappingProvider to point to this new component.
  3. On your PersistenceMapper component expand SqlDatabaseConfig and click the [...] next to KeyMappers, ensure that you have an item named "GuidMapper" with the MapperTypeName set to "Eco.Persistence.GuidKeyMapper". If not then add it.
  4. On your DefaultORMapperBuilder set IdKeySignature to System.Guid (case sensitive).
  5. Set its IdMapperName to GuidMapper.

Now regenerate your DB.

2009-04-23

Prism AOP - 4

I’ve played a little more with Prism. I find it a little difficult to mentally code on two levels. Level one being the code I am writing for the aspect, and level two being the code I am writing which will executed by the target. Having said that, as soon as I ran my app and saw the output everything was worthwhile.

Here is my Person class

type
  [aspect: EcoAspects.BusinessClass(’DomainClasses.Package1’)]
  Person = public class
  private
    FFirstName: String;
    FLastName: String;
  protected
  public
    property FirstName : String read FFirstName write FFirstName;
    property LastName : String read FLastName write FLastName;
  end;


here is the code which uses that class

class method ConsoleApp.Main;
var
  P: Person;
begin
  P := new Person();
  for A in typeOf(Package1).GetCustomAttributes(true) do
    Console.WriteLine(a.ToString());
  
  P.FirstName := ’Peter’;
  P.LastName := ’Morris’;
  ShowGetValueByIndexResult(P as ILoopBack2, 0);
  ShowGetValueByIndexResult(P as ILoopBack2, 1);
  DoSetValueByIndex(P as ILoopBack2, 0, ’Hello’);
  DoSetValueByIndex(P as ILoopBack2, 1, ’There’);
  ShowGetValueByIndexResult(P as ILoopBack2, 0);
  ShowGetValueByIndexResult(P as ILoopBack2, 1);

  Console.ReadLine();
end;

class method ConsoleApp.ShowGetValueByIndexResult(Obj: ILoopBack2; I: Integer);
begin
  Console.WriteLine(Obj.GetValueByIndex(I).ToString());
end;

class method ConsoleApp.DoSetValueByIndex(Obj: ILoopBack2; I: Integer; Value: Object);
begin
  Obj.SetValueByIndex(I, Value);
end;


and finally, here is the output.

  Eco.UmlCodeAttributes.UmlMetaAttributeAttribute
  Peter
  Morris
  Hello
  There


Fantastic! Using a single line of code I am able to morph the Person class so that it acts as though I had written it like this (might not compile, I wrote this next source in notepad)

type
  Person = public class(Object, ILoopBack2)
  private
    FFirstName: String;
    FLastName: String;
  protected
    method GetValueByIndex(I: Integer): Object; virtual;
    method SetValueByIndex(I: Integer; Value: Object); virtual;
  public
    property FirstName : String read FFirstName write FFirstName;
    property LastName : String read FLastName write FLastName;
  end;

method Person.GetValueByIndex(I: Integer): Object;
begin
  case I of
    0: exit FirstName;
    1: exit LastName;
  end;
end;

method Person.SetValueByIndex(I: Integer; Value: Object): Object;
begin
  case I of
    0: FirstName := String(Value);
    1: LastName := String(Value);
  end;
end;


In addition my code will find a class DomainClasses.Package1 and add an attribute

type
  [Eco.UmlCodeAttributes.UmlMetaAttributeAttribute("ownedElement", typeof(Person)]
  Package1 = class
  end;


As you can see the implementation of the aspect "BusinessClass" is very specific to ECO and saves a lot of writing. What is good too is that I could easily remove the project’s reference to the BusinessClass aspect which generates ECO changes and replace it with a DLL which has a BusinessClass aspect for something else - maybe a blank one which does nothing so that you can use the same class definitions as data-transer-objects.

But my interest in this technology goes far beyond easily implementing an object relational mapper in an abstract way, supporting the ORM is only the first step towards achieving what I really want - archetypes. Once I have the experience to create all of the meta-information required for mapping I can start creating my models out of patterns. I do this a lot at the moment, but all manually. For example in one project I had to allow my Employee, Van, and VendingMachineColumn classes to all hold stock. Each of these would need to hold stock, record stock adjustments such a stock found/lost during stock checks, and also due to stock transfers.

It would be a bad design to descend all of these classes from a StockHolder class. Holding stock is something you DO, and not something you ARE, so inheritance here is wrong. What I would typically do here is

1: Create a StockHolder class which holds the stock + adjustment history.
2: Employee, Van, and VendingMachineColumn would all own an instance of StockHolder.
3: Each class would implement

public interface IStockHolder
{
  StockHolder GetStockHolder();
}


This is a one-way relationship, if I needed for example to find all stock holders with X amount of a certain stock item so that I could request a transfer this would not be sufficient. In which case I would introduce an abstract method to StockHolder

  object GetOwner();


Then I’d have a descendant of StockHolder for each owner. EmployeeStockHolder, VanStockHolder, VendingMachineColumnStockHolder; each would have an association back to their owning object (Employee, Van, VendingMachineColumn) which they would return by overriding GetOwner. Now this is not a lot of work, but it is repetitive. You see the pattern in the UML but do you instantly recognise it? Is it really self-descriptive?

My AOP goal is to be able to do something like this

type
  [aspect: BusinessClass(’MyNameSpace.Domain.MyPackageName’)]
  [aspect: StockHolder]
  Employee = class
  public
    ...
  end;

  [aspect: BusinessClass(’MyNameSpace.Domain.MyPackageName’)]
  [aspect: StockHolder]
  Van = class
  public
    ...
  end;

  [aspect: BusinessClass(’MyNameSpace.Domain.MyPackageName’)]
  [aspect: StockHolder]
  VendingMachineColumn = class
  public
    ...
  end;


The StockHolder aspect would create the descendant (TargetClassName)StockHolder with an association back to the target, and override GetOwner. The thing is, HOW the aspect is implemented is not relevant, all I am saying is "this holds stock". It is short, descriptive, and instantly understandable. It’s also only a few seconds of work to make a class hold stock.

type
  [aspect: BusinessClass(’MyNameSpace.Domain.MyPackageName’)]
  [aspect: StockHolder] //Holds stock
  [aspect: ContactDetailsHolder] //Has personal contact information
  [aspect: Auditable] //Can make employees subject to an internal audit
  [aspect: TaskAssignable] //Can assign tasks to this employee
  [aspect: CustomerRole] //Employees can purchase goods
  Employee = class
  public
    ...
  end;


That’s the kind of thing I’d like to end up with. Much more descriptive than UML I think :-)

Here is the code. It’s just proof of concept code at the moment. I’ve decided to prefix Type_ Method_ Property_ etc to the start of types, methods, and property definitions where they are referring to values from the model the aspect is being applied to; this was something I decided to do to help me to mentally split the "this code" scenario and "target code" scenario.


namespace EcoAspects;

interface

uses
  System.Collections.Generic,
  System.Linq,
  RemObjects.Oxygene.Cirrus,
  System.Text;

type
  BusinessClassAttribute = public class(System.Attribute, ITypeInterfaceDecorator)
  private
    FPackageName: String;
    method AddClassToPackage(Services: IServices; aType: ITypeDefinition);
    method AddILoopBack2Interface(Services: IServices; aType: ITypeDefinition);
    method AddILoopBack2GetValueByIndex(Services: IServices; aType: ITypeDefinition);
    method AddILoopBack2SetValueByIndex(Services: IServices; aType: ITypeDefinition);
    property PackageName: String read FPackageName;
  protected
  public
    constructor (PackageName: String);
    method HandleInterface(Services: IServices; aType: ITypeDefinition);
  end;

implementation

uses
  System.Windows.Forms,
  Eco.ObjectImplementation,
  RemObjects.Oxygene.Cirrus.Statements,
  RemObjects.Oxygene.Cirrus.Values;

constructor BusinessClassAttribute(PackageName: String);
begin
  FPackageName := PackageName;
end;

method BusinessClassAttribute.HandleInterface(Services: RemObjects.Oxygene.Cirrus.IServices; aType: RemObjects.Oxygene.Cirrus.ITypeDefinition);
begin
  AddClassToPackage(Services, aType);
  AddILoopBack2Interface(Services, aType);
end;

method BusinessClassAttribute.AddClassToPackage(Services: IServices; aType: ITypeDefinition);
var
  Type_PackageReference: ITypeReference;
  Type_PackageDefinition: ITypeDefinition;
  Type_UmlMetaAttributeAttribute: IAttributeDefinition;
begin
  Type_PackageReference := Services.FindType(PackageName);
  if (Type_PackageReference = nil) then
  begin
    Services.EmitError(’Package class not found: ’ + PackageName);
    exit;
  end;

  //If it is an ITypeDefinition that means it is declared as source in the current
  //binary and we can therefore modify it - so we can attach .NET attributes.
  //If it isn’t an ITypeDefinition but only an ITypeReference then it is immutible
  //and we cannot change it.
  Type_PackageDefinition := Type_PackageReference as ITypeDefinition;
  if (Type_PackageDefinition = nil) then
  begin
    Services.EmitError(’Package class cannot be modified, it is not part of the same project: ’ + PackageName);
    exit;
  end;

  Type_UmlMetaAttributeAttribute := Type_PackageDefinition.AddAttribute();
  Type_UmlMetaAttributeAttribute.Type := Services.FindType(’Eco.UmlCodeAttributes.UmlMetaAttributeAttribute’);
  Type_UmlMetaAttributeAttribute.AddParameter(’ownedElement’);

  //The value we use for Type must be a TypeOfValue based on aType.
  Type_UmlMetaAttributeAttribute.AddParameter(new TypeOfValue(aType));
end;

method BusinessClassAttribute.AddILoopBack2Interface(Services: IServices; aType: ITypeDefinition);
var
  Type_ILoopBack2: IType;
begin
  Type_ILoopBack2 := Services.FindType(’EcoSupport.ILoopBack2’);
  if (Type_ILoopBack2 = nil) then
  begin
    Services.EmitError(’EcoSupport.ILoopBack2 not found, are you missing an assembly reference?’);
    exit;
  end;

  aType.AddInterface(Type_ILoopBack2);
  AddILoopBack2GetValueByIndex(Services, aType);
  AddILoopBack2SetValueByIndex(Services, aType);
end;

method BusinessClassAttribute.AddILoopBack2GetValueByIndex(Services: IServices; aType: ITypeDefinition);
var
  Type_ILoopBack2: IType;
  Method_ILoopBack2_GetValueByIndex: IMethod;
  Method_GetValueByIndex: IMethodDefinition;
  Statement_CaseIndexOf: CaseStatement;
begin
  //Find ILoopBack2 and ILoopBack2.GetValueByIndex
  Type_ILoopBack2 := Services.FindType(’EcoSupport.ILoopBack2’);
  Method_ILoopBack2_GetValueByIndex := Type_ILoopBack2.GetMethods(’GetValueByIndex’)[0];
  
  //Implement GetValueByIndex on the target
  Method_GetValueByIndex := aType.AddMethod(’GetValueByIndex’, Services.GetType(’System.Object’), false);
  Method_GetValueByIndex.AddParameter(’I’, ParameterModifier.In, Services.GetType(’System.Int32’));
  Method_GetValueByIndex.Virtual := VirtualMode.Virtual;
  Method_GetValueByIndex.Visibility := Visibility.Protected;

  //Explicitly tie our GetValueByIndex to ILoopBack2.GetValueByIndex. This ensures they are linked
  //even though our method is protected. This hides the method when using code-completion on the
  //target (because it is protected), but exposes it via the interface - much cleaner!
  aType.AddImplements(Method_GetValueByIndex, Type_ILoopBack2, Method_ILoopBack2_GetValueByIndex);

  //Build case statement
  Statement_CaseIndexOf := new CaseStatement();
  Statement_CaseIndexOf.What := Method_GetValueByIndex.GetParameter(’I’);

  //As a CaseIndex for each property on the class
  var CaseIndex: Integer := 0;
  for PropertyIndex : Integer := 0 to aType.PropertyCount - 1 do
  begin
    var Prop : IProperty := aType.GetProperty(PropertyIndex);
    //Ignore properties which cannot be read
    //Ignore properties which take parameters (properties with indexers);
    if (Prop.ParameterCount = 0) and (Prop.ReadMethod <> nil) then
    begin
      //Create an expression which is basically Self.Property.Read
      var Property_Read : ProcValue := new ProcValue(new SelfValue(), Prop.ReadMethod);

      //Create an exit statement which is basically - exit Self.Property.Read
      //So that we exit the method, returning the result of reading the property value
      var Statement_Exit : ExitStatement := new ExitStatement(Property_Read);

      //Create the CaseIndex which consists merely of the Statement_Exit
      var CaseItem_Index : CaseItem := new CaseItem(Statement_Exit, CaseIndex);

      //Add the CaseIndex to the Statement_CaseIndexOf, and increment the case index
      Statement_CaseIndexOf.Items.Add(CaseItem_Index);
      CaseIndex := CaseIndex + 1;
    end;
  end;

  //Set the body of the GetValueByIndex method we created. Normally we can just write the exact
  //code we need between the begin/end identifiers, but in this case we have generated the statements
  //to execute dynamically, so we need to "unquote" them - which basically means "expand" or "compile".  
  Method_GetValueByIndex.SetBody(Services,
    method begin
      unquote(Statement_CaseIndexOf);
    end);
end;

//This method is very similar to GetValueByIndex, so I will only describe the setter
method BusinessClassAttribute.AddILoopBack2SetValueByIndex(Services: IServices; aType: ITypeDefinition);
var
  Type_ILoopBack2: IType;
  Method_ILoopBack2_SetValueByIndex: IMethod;
  Method_SetValueByIndex: IMethodDefinition;
  Statement_CaseIndexOf: CaseStatement;
begin
  Type_ILoopBack2 := Services.FindType(’EcoSupport.ILoopBack2’);
  Method_ILoopBack2_SetValueByIndex := Type_ILoopBack2.GetMethods(’SetValueByIndex’)[0];

  //SetValueByIndex
  Method_SetValueByIndex := aType.AddMethod(’SetValueByIndex’, nil, false);
  Method_SetValueByIndex.AddParameter(’I’, ParameterModifier.In, Services.GetType(’System.Int32’));
  Method_SetValueByIndex.AddParameter(’Value’, ParameterModifier.In, Services.GetType(’System.Object’));
  Method_SetValueByIndex.Virtual := VirtualMode.Virtual;
  Method_SetValueByIndex.Visibility := Visibility.Protected;

  //Make explicit interface
  aType.AddImplements(Method_SetValueByIndex, Type_ILoopBack2, Method_ILoopBack2_SetValueByIndex);

  //Build case statement
  Statement_CaseIndexOf := new CaseStatement();
  Statement_CaseIndexOf.What := Method_SetValueByIndex.GetParameter(’I’);

  var CaseIndex: Integer := 0;
  for PropertyIndex : Integer := 0 to aType.PropertyCount - 1 do
  begin
    var Prop : IProperty := aType.GetProperty(PropertyIndex);
    if (Prop.ParameterCount = 0) and (Prop.WriteMethod <> nil) then
    begin
      //Here we need 2 statements for every CaseItem. So we need a BeginStatement
      //which is basically a begin/end block
      var Statement_CaseItemBegin : BeginStatement := new BeginStatement();

      //Create an expression which is equivalent to Self.Property.Set(Value);
      var Property_Write : ProcValue := new ProcValue(new SelfValue(), Prop.WriteMethod, Method_SetValueByIndex.GetParameter(’Value’));

      //Create a statement based on this expression. We can use AssignementStatement without passing a value because we have
      //already specified the value in the previous expression.
      var Statement_SetPropertyValue : AssignmentStatement := new AssignmentStatement(Property_Write);

      //Add this assignment to the Begin/End block statement
      Statement_CaseItemBegin.Add(Statement_SetPropertyValue);

      //And add a plain "Exit" after it within the Begin/End block.
      var ExitMethod : ExitStatement := new ExitStatement();
      Statement_CaseItemBegin.Add(ExitMethod);

      //Craete a CaseItem for the current property index which will execute our Begin/End block.
      var CaseItem_Index : CaseItem := new CaseItem(Statement_CaseItemBegin, CaseIndex);

      //Add the Begin/End block statement to the Case statement.
      Statement_CaseIndexOf.Items.Add(CaseItem_Index);
      CaseIndex := CaseIndex + 1;
    end;
  end;

  //Set the "unquoted" statement block as the method’s body.  
  Method_SetValueByIndex.SetBody(Services,
    method begin
      unquote(Statement_CaseIndexOf);
    end);

end;

end.

2009-04-21

ECO – Ensure related objects

Sometimes you have a list of objects (say List<PurchaseOrder>) and you want to get all associated objects (say OrderLines) for all the orders in the list. There are 2 ways of doing this in ECO

  1. You call a PersistenceService method which takes the list of orders and a string identifying the association name. I don't like this approach because the name of the association may change during modelling and this wont be picked up as an error until runtime.
  2. You use the overloaded method which takes an IAssociationEnd. I don't like this either because you have to find the IAssociationEnd instance from the meta-model at runtime, and to do this you'd probably use a name anyway.

So, what's the alternative?



public static void EnsureRelatedObjects<T>(this IPersistenceService instance, IEnumerable<T> objects, Expression<Func<T, object>> member) where T : IEcoObject
{
    MemberExpression memberExpression = (MemberExpression)member.Body;
    instance.EnsureRelatedObjects(objects, memberExpression.Member.Name);
}


Now you can write code like this

EcoSpace.Persistence.EnsureRelatedObjects(orders, o => o.Lines);
EcoSpace.Persistence.EnsureRelatedObjects(orders, o => o.Customer);

And it will be checked at compile time too.

2009-04-10

Prism AOP - 3

I am playing with Prism’s new Aspect Oriented Programming feature. As a learning exercise I am implementing some of the features ECO requires on a class. If all goes well I will end up with aspects I can apply to plain classes and have them run in ECO. One of those features is the ILoopBack2 interface.

In order to tackle this interface a small piece at a time I have created my own ILoopBack2 interface, so far with only one method.

ILoopBack2 = public interface
  function GetValueByIndex(I: Integer): System.Object;
end;


This method allows the ECO to evaluate OCL (Object Constraint Language) expressions such as "self.FirstName" and have them route via the class’s property, just in case there is any logic in the getter. By implementing an interface which uses an index to identify the property to read it is possible to avoid reflection.

So, getting on with it, here is my class definition

type
  [aspect: EcoAspects.BusinessClass(’DomainClasses.Package1’)]
  Person = public class
  private
    FFirstName: String;
    FLastName: String;
  protected
  public
    property FirstName : String read FFirstName write FFirstName;
    property LastName : String read FLastName write FLastName;
  end;


As you can see this is a very plain class, no magic at all except for the aspect I have applied to it. And now some code which uses the class

P := new Person();
P.FirstName := ’Peter’;
P.LastName := ’Morris’;
Console.WriteLine((P as ILoopBack2).GetValueByIndex(0).ToString());
Console.WriteLine((P as ILoopBack2).GetValueByIndex(1).ToString());


Output
  Peter
  Morris



From the example code it is evident that an instance of the Person class is castable to ILoopBack2 and also implements the GetValueByIndex method.

To achieve this the my needs to

1: Add the interface to the class
2: Generate a method
3: Implement the method.

The aspect class is a System.Attribute which implements ITypeInterfaceDecorator.

type
  BusinessClassAttribute = public class(System.Attribute, ITypeInterfaceDecorator)
    ...
  end;

procedure BusinessClassAttribute.HandleInterface(
  Services: RemObjects.Oxygene.Cirrus.IServices;
  aType: RemObjects.Oxygene.Cirrus.ITypeDefinition);
begin
  AddClassToPackage(Services, aType);
  AddILoopBack2Interface(Services, aType);
end;


The implementation for AddILoopBack2Interface consists of the following


procedure BusinessClassAttribute.AddILoopBack2Interface(Services: IServices; aType: ITypeDefinition);
var
  //The type which represents ILoopBack2
  ILoopBack2Type: IType;

  //The type which represents the method GetValueByIndex on ILoopBack2
  ILoopBack2_GetValueByIndex: IMethod;

  //The new method I will create on the Person class
  GetValueByIndexMethod: IMethodDefinition;

  //A case statement I will use in the method
  IndexCaseStatement: CaseStatement;
begin
  //Find the type for ILoopBack2
  ILoopBack2Type := Services.FindType(’EcoSupport.ILoopBack2’);

  //If not found then we are missing a reference, report a compiler error
  if (ILoopBack2Type = nil) then
  begin
    Services.EmitError(’EcoSupport.ILoopBack2 not found, are you missing an assembly reference?’);
    exit;
  end;

  //Get a method reference to ILoopBack2.GetValueByIndex
  ILoopBack2_GetValueByIndex := ILoopBack2Type.GetMethods(’GetValueByIndex’)[0];



This initial code just does some basic checking to ensure the assembly with the interface is referenced by the target assembly (the assembly which owns the Person class). To hide the implementation of GetValueByIndex I want to make the implementing method protected, In Prism you have to explicitly link the interface method to the implementation method if it is not public. For example


type
  IMyInterface = public interface
    procedure Method1();
    procedure Method2();
  end;

  SomeClass = class(System.Object, IMyInterface)
  private
    //Private, so much be explicit about what it implements
    procedure Method1; implements IMyInterface.Method1;
  public
    //Public, the link to the interface method is inferred
    procedure Method2;
  end;



Anyway, back to the important code. Here is the next part of the AddILoopBack2Interface method.

  //Add the interface to Person
  aType.AddInterface(ILoopBack2Type);

  //Create a method which returns a System.Object
  GetValueByIndexMethod := aType.AddMethod(’GetValueByIndex’, Services.GetType(’System.Object’), false);

  //Add a parameter "I: Integer"
  GetValueByIndexMethod.AddParameter(’I’, ParameterModifier.In, Services.GetType(’System.Int32’));

  //Make the method protected + virtual
  GetValueByIndexMethod.Virtual := VirtualMode.Virtual;
  GetValueByIndexMethod.Visibility := Visibility.Protected;

  //Explicitly link the method to ILoopBack2.GetValueByIndex, because the method is not public
  aType.AddImplements(GetValueByIndexMethod, ILoopBack2Type, ILoopBack2_GetValueByIndex);



The implementation of this method will basically be

  case I of
    0: exit FirstName;
    1: exit LastName;
  end;


To do this we need a case statement.

  //Build case statement
  IndexCaseStatement := new CaseStatement();
  IndexCaseStatement.What := GetValueByIndexMethod.GetParameter(’I’);


Next we need to loop through each property on Person and create the case item for it.

  //The case index.  We wont include array properties so this keeps
  //track of how many properties we have added to the case statement
  var CaseIndex: Integer := 0;

  //Loop through each property declared on the type Person
  for PropertyIndex : Integer := 0 to aType.PropertyCount - 1 do
  begin
    //Get a reference to the property
    var Prop : IProperty := aType.GetProperty(PropertyIndex);

    //Only continue if the property has no parameters (is not an array property)
    //and only if it is possible to read this property
    if (Prop.ParameterCount = 0) and (Prop.ReadMethod <> nil) then
    begin
      //Get the method which reads the property value
      var ReadProperty : ProcValue := new ProcValue(new SelfValue(), Prop.ReadMethod);

      //Construct an "exit" statement which returns the value of the property
      var ExitMethod : ExitStatement := new ExitStatement(ReadProperty);

      //Construct a "case item" which executes the exit statement for the
      //given index
      var IndexCaseItem : CaseItem := new CaseItem(ExitMethod, CaseIndex);

      //Add the case item to the case statement
      IndexCaseStatement.Items.Add(IndexCaseItem);

      //Increment the case index for the next property added
      CaseIndex := CaseIndex + 1;
    end;
  end;


Now I have a case statement which I have constructed dynamically I need to assign it as the body of the method which implements ILoopBack2.GetValueByIndex

  GetValueByIndexMethod.SetBody(Services, 
    method begin
      unquote(IndexCaseStatement);
    end);


The "unquote" statement tells the compiler to expand the statement into "real" code.

That’s the lot. This effectively take the following code

type
  [aspect: EcoAspects.BusinessClass(’DomainClasses.Package1’)]
  Person = public class
  private
    FFirstName: String;
    FLastName: String;
  protected
  public
    property FirstName : String read FFirstName write FFirstName;
    property LastName : String read FLastName write FLastName;
  end;


and compiles it as if I had written

type
  Person = public class(System.Object, ILoopBack2)
  private
    FFirstName: String;
    FLastName: String;
  protected
    function GetValueByIndex(I: Integer) : System.Object; virtual;
  public
    property FirstName : String read FFirstName write FFirstName;
    property LastName : String read FLastName write FLastName;
  end;

implementation

function Person.GetValueByIndex(I: Integer) : System.Object;
begin
  case Index of
    0 : exit FirstName;
    1 : exit LastName;
  end;
end;



I hope like me you see the benefits of this!

2009-04-08

AOP 2

This is fun :-) I’ve created an aspect like so

type
  BusinessClassAttribute = public class(System.Attribute, ITypeInterfaceDecorator)
  private
    FPackageName: String;
    property PackageName: String read FPackageName;
  protected
  public
    constructor (PackageName: String);
    method HandleInterface(Services: RemObjects.Oxygene.Cirrus.IServices; aType: RemObjects.Oxygene.Cirrus.ITypeDefinition);
  end;


I can now decorator my class like so

type
  [aspect: BusinessClass(’DomainClasses.Package1’)]
  Person = class
  end;

I can ensure this class  exists in the aspect implementation method.

constructor BusinessClassAttribute(PackageName: String);
begin
  FPackageName := PackageName;
end;

method BusinessClassAttribute.HandleInterface(Services: RemObjects.Oxygene.Cirrus.IServices; aType: RemObjects.Oxygene.Cirrus.ITypeDefinition);
var
  PackageType: ITypeReference;
begin
  PackageType := Services.FindType(PackageName);
  if (PackageType = nil) then
    Services.EmitError(’Package class not found: ’ + PackageName);
end;


Now when I compile my code I get the following compiler error:

Error  1  (ASPE) Package class not found: DomainClasses.Package1

Adding a class named Package1 to the source makes the error go away. Okay, maybe I am getting a little too excited about this, I am a nerd :-)

My first AOP

Here’s what I did.

01: I created a support project which just has a logger class in it.

namespace EcoSupport.pas;
interface
uses
  System.Collections.Generic,
  System.Linq,
  System.Text;

type
  Logger = public class
  private
  protected
  public
    class procedure Log(Message : String);
  end;

implementation

class procedure Logger.Log(Message : String);
begin
  System.Diagnostics.Debug.WriteLine(’Log: ’ + Message);
end;
end.


02: I created an Aspect which decorates methods, giving me the opportunity to intercept all method calls on the class it decorates.

namespace EcoAspects;

interface

uses
  System.Collections.Generic,
  System.Linq,
  System.Text,
  RemObjects.Oxygene.Cirrus,
  EcoSupport;

type
  [AttributeUsage(AttributeTargets.Class)]
  LogAspect = public class(System.Attribute, RemObjects.Oxygene.Cirrus.IMethodImplementationDecorator)
  private
  protected
  public
    method HandleImplementation(Services: IServices; aMethod: IMethodDefinition);
  end;

implementation

method LogAspect.HandleImplementation(Services: IServices; aMethod: IMethodDefinition);
var
  Name : String;
begin
  Name := aMethod.Name;
  aMethod.SetBody(Services,
    method begin
      EcoSupport.pas.Logger.Log(’Entering ’ + Aspects.MethodName);
      try
        Aspects.OriginalBody; //Call the original method body
      finally
        EcoSupport.pas.Logger.Log(’Leaving ’ + Aspects.MethodName);
      end;
    end
    );
end;
end.


03: Now my aspect is ready I can apply it to a class.

namespace PrismConsoleApplication1;

interface

uses
  System.Collections.Generic,
  System.Linq,
  EcoSupport,
  System.Text;

type
  [Aspect:EcoAspects.LogAspect]
  TestSubject = public class
  private
  protected
  public
    method DoSomething();
  end;

implementation

method TestSubject.DoSomething();
begin
  System.Diagnostics.Debug.WriteLine("DoSomething");
end;
end.


04: Finally a test

namespace PrismConsoleApplication1;

interface
uses
  System.Linq;

type
  ConsoleApp = class
  public
    class method Main;
  end;

implementation

class method ConsoleApp.Main;
var
  TS: TestSubject;
begin
  TS := new TestSubject();
  TS.DoSomething();
end;
end.


The output from this is.....

Log: Entering .ctor
Log: Leaving .ctor
Log: Entering .ctor
Log: Leaving .ctor
Log: Entering DoSomething
DoSomething
Log: Leaving DoSomething

Now so far this is all stuff you can do with tools such as PostSharp. The problem with PostSharp is that it is a post-compile processor so the aspects are applied after compilation is complete, which means that we can’t use any of the aspect introduced features within the same library without comprimising compile-time checking. For example in PostSharp if an aspect introduces an interface with a LogMessage method we can’t do this...

[Logger]
public class Person
{
}

var p = new Person();
p.LogMessage(“Hello”);

Because the Person class doesn’t have a LogMessage method until after it has been compiled. To get around this PostSharp users will typically do something like this

var p = new Person();
((object)p as ILogger).LogMessage(“Hello”);

What I don’t like is
1.  More typing
2.  It’s not compile-safe. If I remove the [Logger] attribute from Person it will still compile and I wont know about the problem until runtime.

This is exactly why I like the look of Prism, take a look at this.

type
  [AttributeUsage(AttributeTargets.Class)]
  LogAspect = public class(System.Attribute, RemObjects.Oxygene.Cirrus.IMethodImplementationDecorator)
  private
  protected
  public
    [Aspect:AutoInjectIntoTargetAttribute]
    class method LogMessage(aName: String);
  end;

The AutoInjectIntoTargetAttribute tells the compiler to add that method to the target.

type
  [Aspect:EcoAspects.LogAspect]
  TestSubject = public class
  private
  protected
  public
  end;

p := new TestSubject();
p.LogMessage(‘Hello’);

This compiles even in the same library, because the aspects are able to modify the project structure before the compile process completes, so TestSubject really does have the LogMessage method. Pre-compile AOP, how cool is that?

2009-03-31

My next new best friend

http://blogs.remobjects.com/blogs/ck/2009/02/06/p251

Read the comments I posted to see why I like it!

Unemployed

My employer's support contract has finally come to an end which means I have to look for another job, haven't had to do that in a while!

Drop me an email if you have any positions vacant, in the meantime it's time to do a little "networking".

2009-03-24

Unity - contexts

The outcome of this fairly long exchange on codeplex has made me very happy!

The BNP need my help


It seems they are unable to spell the word "money", because every time they send me their drivel of a newsletter they always want money. Usually it is for their "Van of truth" (which amuses me immensely) but this time it is to help them to become "the most technically advanced political party in the UK".
So, what are they going to do to earn this esteemed title?
  1. Set up our own BNP call centre
  2. Set up the party campaign central office
  3. Purchase 18 computers/screens/software
  4. Activate our brand new central database platform
  5. Recruit more staff to cope
  6. Train all staff in new systems
  7. Set up central mailing and telephone points for party
  8. Open our new logistical distribution warehouse
Riiight.
  1. Call centre – Surely other parties have these?
  2. Central office – I am pretty sure other parties have these!
  3. 18 computers / screens / software – Screens? Are they going to watch TV on them? MONITORS! At least we are talking I.T. now though.
  4. Central database platform – Most likely a list of names and addresses in MS Access, which is probably a nice upgrade from an Excel spreadsheet.
  5. Recruit staff – Not I.T. related.
  6. Train staff – A good idea!
  7. Mailing / telephone points – Get an address and a telephone?
  8. Warehouse – Bob's garage is too small for their Winston Churchill leaflets then?
If they think that is technologically advanced I had better not start my own political party, because my mobile phone is more technologically advanced than that, and it's broken!
I love the part where he says "This is a task of almost biblical proportions", brilliant! Nick Griffin has obviously not read The Bible! I can imagine Moses now. "Let my people go, or I will set up a small call centre with a telephone line, 8 computers with "Screens" and empty Bob's garage!"
As usual the entire thing is full of rubbish. Don't people realise that this party will never get into power, all they are doing is electing people into a system which will give them money for doing nothing at all?

2009-03-08

No Silverlight?

I'm trying to view this page in Firefox. When it loads the browser tells me I need Silverlight, so I download and install it and then restart my browser only to be told I need to install Silverlight.

That's not impressive at all!

2009-03-04

Delphi flickers

My app has a wizard approach, the current control appears within a panel with Align set to fill the hosting panel. My first wizard step control merely had an image on it which resizes with its parent control. When I resize the form the host panel resizes, which resizes the wizard control, which resizes the image; and boy does it flicker!

I just had to spend some time upgrading my old Delphi DIB controls to D2009 just to get an image that doesn't flicker, crazy! By the way, I tried the same thing in VS2008 and there was no flicker at all, and I thought Delphi was supposed to be the tool that produced fast UI apps.

2009-03-03

Synchronising downloads and updates (2)

There was a potential deadlock in the last piece of code. When you obtain any kind of lock you will mostly use a try..finally block to ensure the lock is released when you have finished with it. The using() command expands to a try..finally block so the original code might look okay, however if you mentally expand the code you will see the problem.

using (FileLockingService.FileReadLock(product1.ID))
{
    //Some code here
}

This becomes

var disposable = FileLockingService.FileReadLock(product1.ID);
try
{
    //Some code here
}
finally
{
    disposable.Dispose();
}

So why is this a problem? In a single threaded application it isn't, but this is a website so there are multiple threads running at the same time. Now take into account the fact that a web request has a timeout, what if the thread is aborted after the lock is obtained? Ordinarily this isn't a problem because the acquisition is followed immediately by a "try", but if we expand this code further it is evident that this isn't the case for the code I originally wrote. The code below is indented per method rather than the normal logical indendation

  • var disposable =
    • //Code inside FileLockingService
    • var lockHandler = GetLockHandler(int id);
    • lockHandler.EnterWriteLock();
      //The next command must be a try block
    • var enterWriteLockResult = new DisposableAction(..............); //Oops!
      • if (action == null) throw new ArgumentNullException("Action");
      • this.Action = action;
      • this.Context = context;
    • return enterWriteLockResult;
  • try
    {
        //Some code here
    }
    finally
    {
    disposable.Dispose();
    }

So here you see that rather than there being a TRY block immediately after the EnterWriteLock the code above would create a DisposableAction, check a parameter, assign two instance members, and then return a result. If anything went wrong at any of these points (OutOfMemoryException, ThreadAbortException, etc) then we'd end up with a lock that would not get removed. The code has been changed as follows.

    public class FileLockingService : IFileLockingService
    {
        readonly object SyncRoot = new object();
        readonly Dictionary<int, WeakReference> Locks = new Dictionary<int, WeakReference>();

        public ReaderWriterLockSlim GetLockHandler(int productId)
        {
            WeakReference resultReference;
            ReaderWriterLockSlim result;
            lock (SyncRoot)
            {
                if (Locks.TryGetValue(productId, out resultReference))
                {
                    result = (ReaderWriterLockSlim)resultReference.Target;
                    if (result != null)
                        return result;
                }
                result = new ReaderWriterLockSlim();
                Locks[productId] = new WeakReference(result);
            }
            return result;
        }
    }

and when I use this service:

    FileLockingService.GetLockHandler(product.ID).EnterReadLock();
    //.NET wont allow any exceptions until flow passes into the try block
    try
    {
        //This is the earliest point that an exception can occur after acquiring the lock
        using (var sourceStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            Response.ClearHeaders();
            Response.AddHeader("Content-Type", "Application/Binary");
            Response.AddHeader("Content-Disposition", "attachment; filename=" + product.ClientFileName);
            using (var resultStream = DownloadService.Process(currentUser, new List<string>(), product.ClientFileName, sourceStream))
            {
                int bytesRead;
                byte[] data = new byte[1024];
                while ((bytesRead = resultStream.Read(data, 0, data.Length)) > 0)
                    Response.OutputStream.Write(data, 0, bytesRead);
                Response.End();
            }//using
        }//filestream
    }
    finally
    {
        FileLockingService.GetLockHandler(product.ID).ExitReadLock();
    }

Lesson learned: When it comes to thread synchronisation don't do anything fancy!

2009-03-02

Synchronising downloads and updates

Apparently my boss used to be annoyed with something on his old website. When he wanted to upload an updated binary he often couldn't because his product was so popular that someone was always downloading it at the same time. He'd have to continuously hit Delete in his FTP client until eventually he'd slip in and manage to delete it before updating the new version.

This obviously isn't an ideal solution because:

  1. He constantly had to sit there for around an hour trying to delete it.
  2. Once deleted from the disk any user attempting to download would get a 404 – Not Found error.
  3. During upload any user attempting to download would get an Access Denied error of some kind.

For this website I have decided first of all to only update the files via a HTTP form post. So firstly any long running upload will not deny access to the currently available file, this eliminates problem 3. Additionally, using a form post means I can overwrite the existing file, so this eliminates problem 2.

The potential problems I have now though are:

  1. If he uploads but the file is in use the process will fail, causing him to have to upload again. From his upload use case this is worse than before because it takes much longer to discover your upload hasn't worked.
  2. If a user attempts to access the file during the process of copying from memory to disk they will still get an access error. Although this is now much less likely it could still happen.

My solution was to implement an IFileLockingService. Downloading a file should place a read lock, uploading the file should place a write lock. Multiple read locks may exist at once, but a write lock is exclusive. Any conflicts will result in the lock request waiting until it may proceed.

//Downloading
using (FileLockingService.FileReadLock(Product.Id))
{
    //Write a binary response based on the file
}

//Uploading
using (FileLockingService.FileWriteLock(Product.Id))
{
    //Write the posted file to disk
}

To implement the read/write lock I used a ReaderWriterLockSlim instance per Product.ID. To keep memory usage down I ensured that I used a WeakReference to hold the ReaderWriterLockSlim reference so that it may be collected once no longer referenced.

public class FileLockingService : IFileLockingService
{
    readonly object SyncRoot = new object();
    readonly Dictionary<int, WeakReference> Locks = new Dictionary<int, WeakReference>();

ReaderWriterLockSlim GetLockHandler(int id)
{
    WeakReference resultReference;
    ReaderWriterLockSlim result;
    lock (SyncRoot)
    {
        if (Locks.TryGetValue(id, out resultReference))
        {
            result = (ReaderWriterLockSlim)resultReference.Target;
            if (result != null)
                return result;
        }
        result = new ReaderWriterLockSlim();
        Locks[id] = new WeakReference(result);
    }    
    return result;
}

public IDisposable FileReadLock(int productId)
{
    var lockHandler = GetLockHandler(productId);
    lockHandler.EnterReadLock();
    return new DisposableAction(context => lockHandler.ExitReadLock(), null);
}

public IDisposable FileWriteLock(int productId)
{
    var lockHandler = GetLockHandler(productId);
    lockHandler.EnterWriteLock();
    return new DisposableAction(context => lockHandler.ExitWriteLock(), null);
}
}

DisposableAction is a class I have mentioned here

2009-03-01

The best tool for the job

If I had to write a large business app which accessed a DB, or a website, I would use .NET without hesitation. When it comes to small apps (less than 10MB) that will be downloaded by home users what should I use? I have such a project coming up soon, my boss has bought D2009 and wants me to use that because he is paranoid about people reverse engineering the binaries. I'm a little hesitant but I must admit that I think in this case Delphi 2009 probably is the best tool for the job, and I like to use the best tool for the job rather than the tool I like to use best for my job.

Hopefully things will go smoothly, it will be nice writing apps in two different languages.

Music to fight to

An odd title for a coding blog I know, but I love martial arts too, especially competitive ones.

I'm just putting together a CD for my car. The tunes on the CD music really make my adrenaline pump, so I am putting together a compilation of tunes which make me want to win a fight...with style!

  1. Nirvana – Smells like teen spirit.
  2. Fat boy slim – Right here right now.
  3. William Orbit – Adagio for strings (Ferry Corsten Remix with first 2 mins cut off).
  4. The Prodigy – Breathe.
  5. The Prodidy – Firestarter.
  6. Chemical Brothers – Block rockin' beat.
  7. Chemical Brothers – Setting Sun.

2009-02-25

PayPal doesn’t do discounts

I can't believe it, I really can't!

I'm writing a shopping cart for a website. One of the features required is to give the user an X amount discount off their next order when they buy a specific product. So let's say the user has a £20 discount on their next order, how does PayPal let me apply that? Simple answer, it doesn't!

You can't send a cart line with a negative price "Discount for 20 GBP", nor can you send a cart line with a positive price but a negative quantity (that was desperation). The way to do this apparently is to send a cart total. YES! By sending the entire order aggregated into a single order line. NOOOOOOO!!!!!!

So PayPal wants my user to order £100 of goods, click Check-out, and then be presented with "Total for your order £100 (£20 discount)", that's it? In my opinion, that's not very good. In fact, considering PayPal is probably the largest Internet payment organisation in the world I consider this to be atrocious!

Oh well, back to it...

2009-02-24

More Balsamiq madness!

Someone pointed this link out to me today:

http://www.screensketcher.com/examples.html

It's another application along the lines of Balsamiq. This app does seem very "sharp", it has very snappy response times etc, which is nice and everything BUT I still don't like these kinds of apps!

I do prefer the name though, it suggests "I sketch screens" rather than "I am a bottle of vinegar".

2009-02-17

This is just a test

I've just spotted a "Publish to Blog" option in Word 2007. So I thought I'd give it a spin and see what happens. If it works then Blogging is going to be a much more pleasurable experience.

  1. My spelling is atrocious.
  2. I find complex formatting on BlogSpot is terrible.
  3. I will no longer have to edit HTML just to get my code to look right.

Talking of code, I had better try that out too...

    public class PreSaveConstraint

    {

        public readonly IObject Instance;

        public readonly string Name;

        public readonly Func<bool> CheckIsValid;


 

        public PreSaveConstraint(IObject instance, string name, Func<bool> checkIsValid)

        {

            if (instance == null)

                throw new ArgumentNullException("Instance");

            if (string.IsNullOrEmpty(name))

                throw new ArgumentNullException("Name");

            if (checkIsValid == null)

                throw new ArgumentNullException("CheckIsValid");


 

            Instance = instance;

            Name = name;

            CheckIsValid = checkIsValid;

        }

    }


 

Well, here goes. If you can see this then it worked!

2009-02-13

Proof of the existence of God

Finally there is proof that God exists. The proof has come in the guise of a product named Balsamiq. Balsamiq allows you to create mock GUI when specifying an application. Rather than having graphics that look like real forms etc it uses a pencil drawing lookalike approach.

Here is my reasoning.
  1. It does nothing you can't do for free in the IDE you undoubtedly already have.
  2. The result looks far worse than a mock up you can create in your IDE.
  3. Once you have the mock up you can't do anything useful with it except export it as an image or print it. You can't, for example, actually use that for a real form later in the project's life cycle.
  4. The result looks crap. Not poor, crap! It looks like a 7 year old has drawn it with a wax crayon....a blunt one.
  5. Balsamiq brought in revenue of over 100,000 US Dollars in its first 5 months.
Now the way I see it is this. Lots of people are sending money to a guy to buy software that does something they can already do much better for nothing. The only possible conclusion I can reach is that the developer must have sold his soul to the devil. Taking into account that we now have conclusive proof that Satan exists it is logical to conclude therefore that it is an absolute certainty that God also exists.

I rest my case.

2009-02-12

ASP.NET Development server and PayPal instant payment notification

I am currently developing part of a website where I pass cart information to PayPal to accept payment. PayPal will call back a "secret URL" on my website to allow me to confirm the cart details haven't been tampered with.

I hate installing software I don't need. This is especially the case with software like IIS which just feels so intrusive, which is why I use the ASP.NET Development Server when creating websites. The problem with this server is that it only accepts connections from the local machine. My computer is behind a hardware firewall and my web server wont accept remote connections, so how can I test my PayPal IPN call back?

Simple. Obviously I have to open a port on my firewall and direct it to my machine. So I opened port 80. Then I used this tool to list on port 80 and redirect all traffic to port 10101 (the port my ASP.NET development server was listening on). The result is that a remote computer can now make a HTTP request to my computer, and I can receive it + debug it in Visual Studio without having to install IIS.

The great thing about this port forwarder is that it is only 44KB in size and doesn't require any installation!

2009-02-10

Ultimate integration testing

I am just creating some classes that allow the user of an app to specify date/time validity. As I am modeling them it reminded me of some recurring event classes I once wrote to schedule payments between bank accounts.

One day my customer phoned me up. "Has your invoice been paid this month?" he asked.
"Yes" I said.
"Ah good, your code works then!"

2009-02-09

Onion architecture

Jeff seems to have put it very well in his blog. Much better than I did myself back in December 2006 when I blogged about my "Onion" idea.

My mistakes were
01: I was missing a domain services layer.
02: I tried to explain it using a specific example (wizard app with a "process stack" aka "task stack"), and later decided I didn't like the example :-)
03: When I drew my diagrams I showed them as a typical stacked diagram, because my graphics skills are crap :-)

Here's my badly put idea of onion layered applications:
http://mrpmorris.blogspot.com/2006/12/net-onion-part-1.html

Here's Jeffrey's
http://jeffreypalermo.com/blog/the-onion-architecture-part-1/

Well done Jeff, very nicely put!

Rhino Mocks, returning a different result every time

[TestMethod]
public void Meh()
{
var mockFileSystem = MockRepository.GenerateMock<IFileSystemService>();
mockFileSystem.Stub(fs => fs.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None))
.IgnoreArguments()
.Return(new MemoryStream());

var result1 = mockFileSystem.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None);
var result2 = mockFileSystem.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None);
Assert.AreNotSame(result1, result2);
}


This test case shows a problem I was having. The return value of the stubbed CreateFileStream method isn't calculated each time it is called, it is calculated once at the point you defined the stub method and then returned for every subsequent call. The problem with this is that my real test needed to call CreateFileStream twice and get two different streams, the test was failing because the method being tested disposes of the stream it uses; this was resulting in an ObjectDisposedException in my test.

The correct way to implement this is to override the return value using WhenExecuted()

[TestMethod]
public void Meh()
{
var mockFileSystem = MockRepository.GenerateMock<IFileSystemService>();
mockFileSystem.Stub(fs => fs.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None))
.IgnoreArguments()
.Return(null)

//*****The return value is replaced in the next line!
.WhenCalled(invocation => invocation.ReturnValue = new MemoryStream());

var result1 = mockFileSystem.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None);
var result2 = mockFileSystem.CreateFileStream(null, FileMode.Append, FileAccess.Write, FileShare.None);
Assert.AreNotSame(result1, result2);
}

2009-02-08

Why are all my Visual Studio unit test results "Not executed"

When I run my unit tests in my project I am seeing a result "Not executed" for every one. I have restarted my computer so I doubt this is some kind of hung process issue.

Google has revealed nothing that is not related to load balancing, and I am not load balancing!

Solved

In order to determine the error you have to do this

  1. Open the Visual Studio command prompt
  2. Change to the directory where the binary output of your test project is.
  3. Type mstest /testcontainer:The.Name.Of.Your.Test.Assembly.dll

At the bottom of the output you will see the following text

Run has the following issue(s):

In my case it was the following:

Failed to queue test run 'Peter Morris@PETERMORRIS-PC 2009-02-09 10:00:37': Test Run deployment issue: The location of the file or directory 'C:\SomePath\SomeProject.Tests\bin\Debug\Rhino.Mocks.dll' is not trusted.

Now if VS had told me this in the IDE I could have fixed it in minutes! All you have to do is open Windows Explorer and find that DLL. Right-click on it and go to Properties. Then click the "Unblock" button.

If the IDE had told me the reason then it would have taken me 5 minutes to fix (as it did once I knew what it was)

2009-02-06

Silent errors

I'm working on an app which uses a 3rd party library for producing SWF and FLV files. For some reason the trial worked perfectly but when I switched my app to the full version there was no audio output.

We'd been looking at this problem for a while, emailing support etc, but just couldn't see what was wrong. It wasn't until I went back to my proof of concept app and ran it that we realised the full version did produce audio, it was just my main app that wouldn't work properly. Then I spotted the error...

var compressor = new TVE4();
compressor.LoadSettings(SettingsPath);
compressor.SetOutputFile(outputFileName);
compressor.EncodeSequenceAudio(Composition.EffectiveProductionAudioFileName);
compressor.Key1 = 12345;
compressor.Key2 = 54321;
(loop to encode frames)


Do you see the error? It was only as I switched between the proof of concept code and my app code in the IDE that I noticed the two following lines moving up and down...

compressor.Key1 = 12345;
compressor.Key2 = 54321;
Once I spotted it the problem was obvious! If I don't set my license key before encoding anything (including audio) it is not going to work. Moving the key up a couple of lines fixed the problem. It was a simple absent minded mistake to have made, but why did it take over a day to solve?

There were so many factors involved. We aren't using the "full edition" of the tool we are using a feature restricted version so we thought it might be that for a while. Then we thought it might be our settings files. Then their support department kept talking about missing codecs (which made no sense to be honest.) Then there was the fact that in the app it runs in a thread. All sorts of variables that seemed much more likely than a simple 2 line coding error.

The thing is, the EncodeSequenceAudio method returns a bool to indicate success or failure. I hadn't even spotted this. I am so accustomed to experiencing exceptions that I didn't even think to expect a boolean return type. In addition to this the examples that ship with the product don't check for a result either.

2009-01-28

Perceived speed

I'm writing an app which basically performs the following steps in a wizard-like interface:
  1. Select an audio file of someone speaking + loads a text script in.
  2. Process the audio file and the script, can take about 5 seconds for a minute of audio.
  3. Select a character to use in the animation.
  4. Select some additional graphics and scene settings.
  5. Use the data generated in step #2.
Sitting there for 5 seconds wasn't really a problem, not to process a 1 minute audio file. A longer audio file would take a little longer, but 10-15 seconds is okay, isn't it? Well, what if I could make it take no time at all?

Obviously I can't, but I can make it look like it takes no time at all. The fact is that I don't need the processed data until Step 5. The user will probably spend at least 30 seconds twiddling settings in each Step 3 and 4. How much processing power does a bit of GUI interaction take? Hardly any at all!

So I made Step 2 run in a separate thread. As soon as the user clicks "Next" on step 1 they instantly see Step 3. They spend some time there and move onto Step 4. By this point the processing is probably already complete, if however it isn't I simply disable Step #4's "Next" button with a flashing label at the top of the form "* Processing Lip Sync". A 0.5 second timer keeps checking for the completed flag to be set, when it is the label disappears and the button enables.

Unless the user is rushing through the steps they are unlikely to get held up at all. The processing takes just as long as before (maybe a tad longer), but from the user's perspective it takes no time at all.

2009-01-27

Data Transfer Objects

My observations on data transfer objects

  1. They should not be a one to one representation of your domain classes.
    Sometimes you want a subset of the information of a single instance, sometimes your DTO will collect data from various instances (starting with an aggregate root). You might create different types of DTO from the same domain classes based on what the user needs to do. Sometimes the user only wants OrderNumber + DateRaised + TotalValue (to show as a list of orders), sometimes they want the entire order details (including lines) for editing.

  2. The domain classes should have no knowledge of your DTO classes.
    So you shouldn't have any methods such as

    pubic PersonDto CreateDto();
    public UpdateFromDto(personDto);

    DTO's are not part of the business domain, so you should never do this!

  3. The DTO you send out might not be the same type as you get back.
    For example you don't want the user to edit the order number or the date raised. If there are only a couple of properties like this you might opt to use the same DTO class but just ignore those properties when updating the domain instances, or you might decide on Request/Response DTOs

  4. The DTOs should have no knowledge of the domain classes.
    This is because the DTO classes will be shared between the client and the server, and the client will have no domain class knowledge. If you have domain classes on the client then you probably don't need DTOs.

  5. There is only one way to update domain instances from a specific DTO.
    A DTO doesn't always update domain classes, but when you receive a specific kind of DTO and need it to update domain instances it will always update in the same fasion.
So, how do you create DTOs from domain instances and how do you update domain instances from DTOs? The first thing to be aware of is that this code belongs in a layer above the domain layer, in a services layer or the app layer itself. Then we need some way of saying

  "I want to convert this Order to an OrderSummaryDto"

or

  "I want to convert this Order to an OrderDto, which includes its order lines"

and then finally

  "I have received a DTO, I need to update the relevant domain instances"

We need to do this in a reusable way, because the same DTOs may be reused in various parts of the application layer. To achieve this I used the Dependency Injection Container from Microsoft named "Unity".

Naming conventions I used are
  • xxxDtoFactory - Creates a DTO of a specific type from a specific domain instance.
  • xxxDtoTranslater - Takes a DTO of a specific type and translates its values back into the domain instances (updating existing instances, creating new instances, or whatever is required.)
The example model has a class named "Template" which has only a "string Name" property. It is an aggregate root so it owns multiple TemplateProperty instances. TemplateProperty is an abstract class with two concrete descendants; TemplateStringProperty and TemplateBooleanProperty.

When I create a DTO I want a TemplateDto and added to its Properties I want TemplateStringPropertyDto and TemplateBooleanPropertyDto. When I translate TemplateDto I want to update the existing object.

To register a factory
container.RegisterType<IDtoFactory<Template, TemplateDto>, TemplateDtoFactory>(
    new ContainerControlledLifetimeManager()
    );


The structure is IDtoFactory<TDomainClass, TDataTransferObject> to identify the domain class and desired DTO class, followed by the type that implements the interface to perform this DTO creation. This code registers a factory that takes a Template domain class and creates a TemplateDto data transfer object.

To register a translater
container.RegisterType<IDtoTranslater<TemplateDto>, TemplateDtoTranslater>(
    new ContainerControlledLifetimeManager()
    );


The structure is more simple. A DTO can only be translated in one way, so the generic IDtoTranslater interface only requires a single type, TDataTransferObject. This code registers a translater that takes a data transfer object and maps it to the domain.

Once registered the services are used like so:
//Create a template
Template template1 = new Template();

//Create a DTO from the template
TemplateDto template1Dto = container.Resolve<IDtoFactory<Template, TemplateDto>>().CreateDto(template1);

//Update the template from the DTO
container.Resolve<IDtoTranslater<TemplateDto>>().UpdateBusinessObjects(null, null, template1Dto);


Note that the "container.Resolve" code wouldn't really be there, you would use dependency injection. I have used it in this example to avoid turning it into a dependency-injection-container blog :-)

The "null, null" here are
  • The object space that the app layer has created and is using for your domain instances to work inside. Also known as your unit of work, transaction, or other.
  • An addition context. For example when updating a Template the TemplateDtoTranslater will resolve services to translate each PropertyDto it encounters, and pass the Template as the context so that we know which aggregate root we are working with.
For now I will link to the full source code for the example. If I get time I will blog some more explaining how the code works.

2009-01-20

How often should I test?

I am lazy.  I don't mean that I don't work, I mean that I like to get my work done with as little effort as possible.  Writing tests before my code used to look like too much extra work, but I've realised just how much time they actually save me.

When you make a small change to something it's very easy to think to yourself "That's such a small change, I can't see how it can possibly fail", what I have also realised is this really means "Despite this being a small change, it will fail and I can't possibly see how".

I recently observed a change to some code that introduced a simple if statement, and all existing tests passed.  The problem is that the existing tests only checked the expected behaviour worked (which it still did), but by introducing the "if" statement (and an additional parameter on the method) the developer had changed the expected behaviour under certain circumstances.  Thinking it was so simple it couldn't possibly fail he checked in his changes.  I happened to be changing something in the same code and spotted the changes, and realised immediately that his changes would actually result in files being deleted that are still required.

So, how often should you write tests?  I think this site sums it up very well
http://howoftenshoulditest.com

2009-01-09

Domain Driven Design by Eric Evans - my book review

To me this book has been a huge disappointment. Someone told me "Pete, there's a name for what you do!" and pointed me to this book.

Now personally I prefer technical books, as I read the Ubiquitous Language part at the start I thought to myself "Not technical, but fair enough some people will get value from being taught how to ask questions" and I stuck with it.

The first thing I must say that I cannot stand and which happens a lot in this book is over emphasis. When you want to emphasise something it needs to stand out. This book not only emphasises whole paragraphs but does it far too often too. Being an Internet user for some time now when I read upper case letters the imagined vocalisation actually SHOUTS at me, when I read bold my brain vocalises it as a loud and punctuated word, so when I read a whole paragraph in bold I, READ, EACH, WORD, LIKE, THIS; it makes it difficult to read.

Another thing I don't like when reading something is reading it for the Nth time. I don't mind a bit of reiteration in the way of reading something and then at the end telling me it is another example of "X" but only if the example is so different that it probably didn't occur to me. When I am on page 400+ I really don't want to be reading more examples of what I was reading in the first chapter. It really switches my brain off when so far into the book I am reading yet another example of "The Ubiquitous Language" that was covered at the start of the book. To be honest I am finding it very difficult to motivate myself to read the remainder of the book.

So, what have I learned from the book? I would say I have learned 1 valuable thing. Many times in the past I have modeled a parent/child association such as PurchaseOrder, and then modeled a kin-like parent/child such as Invoice/InvoiceLine, where the invoice is always for a single order and each invoice line is for a specific order line. In these circumstances I would have both Invoice.Order and InvoiceLine.OrderLine, everytime I did this I would cringe, it just felt "wrong" or "messy". Enforcing the idea that I should have no direct associations to the aggregated parts of the Order means that now I merely have Invoice.Order, it's easy to see which order line the invoice line is for because they are ordered the same and both the order and invoice are immutible. Now, I don't agree with the idea of never referencing an aggregated part, but at least now I consider the option. It certainly cleaned up a 3 kin-like aggregate part of the model I am currently working on.

For someone who doesn't know how to talk the "language of the current domain" with a customer I can see that this book could be useful, and also for people who need some pointers on how to segment their apps a bit.

When I read about people mentioning the "map of the world" example being such an eye opener (or whatever other way they express their positive experience) it honestly amazes me. The idea that a "Customer" to company A is completely different from how company B sees one as a break through just makes me shake my head in disbelief. In some businesses a customer is a company, in others a person, in others it could be either, and in one domain I worked a customer could have been either

A: A company
B: A department
C: An individual
D: A non physical entity such as a business process

All of which could also be a "Supplier". This is because they saw their Customers and Suppliers as things that consume and things that produce.

On the whole I personally found the book to be "a whole lot of nothing much at all", some of the personal stories were interesting but I also mainly found it repetitive and boring; a very difficult read. Unless the last 100 pages or so have something knock-out in them I expect I will remain very disappointed with it, if I ever manage to read the end that is.

Some people seem to be quite religious about this book, referring to it as "The book" and I feel by posting this negative review I might be opening myself up to attacks from DDD-extremists :-)

The fact is that I use parts of the DDD approach (now I at least know by what name to refer to it), it's just the book...