Having spent far too much time working on TypograFix, I now have a few moments to recount my experiences – in particular, the useful things I’ve learned.

AOP and Cross-Thread Calls

First, I finally added AOP support to the project. I’m not using AOP for validation, since there’s very little, but I am using two AOP features to drive the app. The first is a [WorkerThread] attribute, which causes a function to be called in a separate thread. It’s probably the simplest, most brainless aspect you can think of:

/// <summary>
/// Makes the method run async.
/// </summary>
[Serializable]
public class WorkerThreadAttribute : OnMethodInvocationAspect
{
  public override void OnInvocation(MethodInvocationEventArgs eventArgs)
  {
    ThreadPool.QueueUserWorkItem(state => eventArgs.Proceed());
  }
}

What surprised me was that this attribute worked surprisingly well – I just put it in front of the DoUpdate() function, and it started running async, fired every 5 seconds by a timer. The only thing that annoys me is that the WinForms WebBrowser control makes a clicking sound whenever I update and, at the moment, I don’t have a clue how to remove it.

My application uses both WPF and WinForms controls (you’ve guessed it – the WebBrowser control), so having this attribute implies that I have to do those ugly cross-thread calls. One ‘gotcha’ I got from this is that not only does setting a WPF control property require the use of a Dispatcher, but getting the property requires one too (which makes sense in retrospect, I guess). This led me to write the following, slightly bizarre, piece of code:

string text = (string)tbOut.Dispatcher.Invoke((Func<string>) delegate
{
  ConversionStatus cs;
  string msg;
  tbOut.Text = Generator.Generate(
    tbIn.Text,
    App.ConversionOptions,
    5000,
    true,
    out cs,
    out msg);
  ConversionMessage = msg;
  Status = cs;
  return tbOut.Text;
});

This is the first time I’ve done a return from an Invoke() on a delegate – and is probably the last time, since I don’t like the notation. I think this piece of code is somewhat hard to read, and is confusing to anyone but me.

The second AOP attribute I used is [INotifyPropertyChanged], which adds support for change notifications to a class in just one line of code (instead of all that event and firing stuff). Annoyingly enough, the PostSharp sample had a bug which took me some time to track down, but I got it working in the end. The attribute implementation itself weighs in at 226 lines of code, which is quite a bit – but then the functionality is so useful – it works on auto-properties just fine!

The only real snag I had (again, due to inexperience) was a question – how do I cast an object to an INotifyPropertyChanged interface if it doesn’t implement this interface at compile-time? Luckily, the solution is really simple – a double cast via object:

INotifyPropertyChanged npc = (INotifyPropertyChanged)(object)App.ConversionOptions;

Incidentally, PostSharp does provide a generic method Post.Cast<> to do this, but I had some trouble with it, so I’m sticking to the double cast for now. You wouldn’t beleive the kinds of options I tried though! For example, I tried to do a GetInterfaces() at runtime to find the object having an INotifyPropertyChanged interface, but to my amazement, it didn’t, probably because it was extended by PostSharp’s own interface wrapper.

Strong Names

Rule of thumb for library makers: provide a strong name. This is something that was missing from AOP-based validation package (which I later decided not to use). Basically, if you make a reusable library and don’t provide a strong name, I can’t use it in strongly-named assemblies myself. And even if I have your source code, I’m a bit too lazy to provide a strong name myself.

Why? Because, apart from having to generate the snk or pfx file, I also have to get the public key and update all the [InternalsVisibleTo] attributes – not in my solution, but in the 3rd party library one! How crazy is that?

This is definitely something to remember for the future.

Maintainability

I finally had a change to take a look at the metrics that VSTS gives me for the transformation function. Needless to say, the situation is dire:

  • 195 lines of code

  • Class coupling of 15

  • Cyclomatic complexity of 192 (!!!)

  • Maintainability index of 0 (zero)

If I was managing a project and someone wrote this, I’d ask them to refactor it. Clearly, having a massive state machine in one function is not the best way to go, especially seeing how I have conditionals everywhere – that’s right, I’m using the evil goto statement all over the place, because within switch statements, the goto instruction is capable of jumping to the default label – a situation that happens far too often when a match against an expected condition fails.

Although I cannot refactor the method manually, it might be possible to do it with programmatic means – some sort of static transformation can turn this huge switch monstrosity into a series of separate functions (perhaps in a nested class) or even a WF or some sort of DSL. At the moment, I’m happy with the code, so I’m not bothered that much. But it’s something I might do later.

Cross-Platform Plans

Since I spend a small amount of time on a Mac, I’m thinking of transforming this application into something that can run on either Mono, ASP.NET (via AJAX, of course), or Silverlight. (I wish I could consider AIR, too, but I doubt it can understand C#.) The idea is that anyone can use my script to prepare documents for publication.

On a side note, I finally managed to do a screencast for the program, so anyone who wants to get some web-based typographic goodness can take a look at the program in action. Admittedly, it’s not very exciting, but then again, what excites me is the fact that I’m using my own program for pretty much all the HTML publication I do. Including this blog post.