2009-06-05

Embarcadero should revive Bold for Delphi

I've recently been doing some work on a Bold for Delphi application. I am really quite surprised how much I am still impressed with this framework, it really was (and still is) so much ahead of its time.

Embarcadero really should revive this product and put it back into Delphi. They could make it a free addition to Delphi, or maybe even ship it with Delphi as an open source project.

Embarcadero! You have a great tool here, don't hide it away, use it!

2009-06-02

Bing

I searched for "mrpmorris" on bing.com recently.  Now on Google it would show the address of my blog as the first result, which is very relevant.  On Bing it showed a page from a web chat from over 3 years ago, not very impressive.

Not sure how long this photo will remain on the web for, but I found it quite interesting...




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.

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!