Friday, July 20, 2007

Rain

So there was a bit of rain today, almost enough to flood our house but not quite. And our roof leaked. But the shed is intact. Then as quickly as it arrived, it stopped. And a few hours later, all the evidence had gone. Here are some pictures.IMAG0150 IMAG0155

Wednesday, July 18, 2007

How rich are you?

I've got a theory, not a particularly original theory admittedly, that we all think we're poorer than we actually are (something to do with our celebrity obsessed culture). It only takes a few seconds to plug in some numbers to the Channel 4 Rich-o-meter or The Institute for Fiscal Studies' 'Where do you fit in?' page to see how rich, or otherwise, you are. The Channel 4 one is interesting since it allows you to compare yourself to the rest of the world, which shows even a very modest UK salary is pretty damn good when compared globally. The Institute for Fiscal Studies' version is probably more accurate since it is based on household income rather than personal income.

Tuesday, July 17, 2007

Adding services to the Windows Workflow runtime and a simple activity implementation

There are two groups of Windows Workflow service that you'll come across. The first group are the well-known services that are used by the runtime itself (well-known because they are well-known to the runtime not necessarily to the developer using the runtime...). These are things like the persistence service, tracking service, data exchange service etc. You can use these services out of the box or you can inherit from them and modify them as required. Fortunately a lot of the methods in these services are virtual so you can quite easily hook in new functionality (and quite possibly get yourself in a whole heap of trouble as well).

The second group of services are services that can be used by your own custom activities. At this point it's worth considering when using your own service makes sense. For instance I downloaded an email sender activity that required me to configure the SMTP host address and port as properties on the activity. Since it was a standalone activity, this was probably the sensible option, since it simplified usage. But if I were to use the activity in many different workflows and the SMTP host changed I'd need to update every workflow to work with the new SMTP server. So if I was to write the activity myself it may well make more sense to handle all this kind of configuration in an email sender service. This also has the advantage of being able to pull the plug on emails being sent out if a poorly written workflow was sending out too many emails. So it depends on what you're trying to achieve whether services make sense or not.

To actually add your own service to the runtime is pretty straightforward. Define an interface and mark it with the ExternalDataExchange attribute.

    [ExternalDataExchange]
    public interface ISendEmail
    {
      void Send(string toAddress, string message);
    }

Next write a class that implements the interface.

    public class EmailSenderService : ISendEmail
    {
      public void Send(string toAddress, string message)  
      {
        // send it...
      }
    }

I'm not entirely sure whether you have to use an interface or if you can just use a class straight off but I've only used interfaces myself and there are at least a couple of good reasons why this is the best way to go. First, it decouples your service implementation from the activity that is calling it. For the email sender example, this means you could replace the SMTP sender with a new implementation using Exchange (or whatever) to send the email without needing to change your activity implementation. Second, if you want to use the CallExternalMethod activity to call into the service, this only accepts an interface for the InterfaceType property.

After that, all you need to do is add the service to the runtime.

    // external data exchange service
    ExternalDataExchangeService dataService = new ExternalDataExchangeService();
    runtime.AddService(dataService);
    
    // email sender service
    EmailSenderService emailService = new EmailSenderService();
    dataService.AddService(emailService);

To call the ISendEmail methods, you have two choices, hook up a CallExternalMethod activity or write a custom activity to call the method. Since I've not yet shown an activity that does anything useful, I'm going down the latter route. Create a new activity via the Add/Activity... popup menu item and add some code as follows.

    protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
    {
      // generate alerts
      ISendEmail sendEmail = (ISendEmail)executionContext.GetService(typeof(ISendEmail));
      if (sendEmail != null)
      {
        sendEmail.Send("doogal@doogal.co.uk", "blah");
      }

      return ActivityExecutionStatus.Closed;
    }

This is the simplest activity that you can implement, it executes some code then returns saying "I'm done". When I work out how to implement some more complex activities, I'll write about it.

Monday, July 09, 2007

Blogging is like the lottery

The lottery people Camelot used to say "You've got to be in it to win it". Of course the chances of a big win are tiny but if you never buy a ticket you'll never win anything at all. So it is with blogging, you're pretty unlikely to ever get a big crowd of people to your blog, but occasionally you might get that £10 win. Every post is another ticket in the blogging lottery and every so often you'll get a few hits from one.

Which is what happened with my little post about SonicWall on Vista, if only because nobody else has bothered to post about it. And if anybody wants to know, the latest beta still has the same problems for me, Vista complains that two computers with the same IP address are connected to the network. But I'm coming to expect these kind of issues with Vista. Bring on SP1...

Sunday, July 08, 2007

Annoying Vista UI

In Vista, Media Player and Photo Gallery have very similar user interfaces. The toolbar thingy at the bottom of their windows looks almost exactly the same.

wmp This is Media Player
photo_gallery This is Photo Gallery

But the big button in the middle works differently. If I'm watching a video in Media Player, the biggest button on the toolbar pauses the video. In Photo Gallery, it switches to slide-show mode, an operation that takes several seconds and I never want to do. If I'm not thinking about what application I'm in, I'll hit that big button to pause the video and see my computer grind to a halt whilst it does something I don't want it to do. Why have very similar UIs if the buttons do different things??? Consistent UIs are only any use if they behave consistently.

Thursday, July 05, 2007

The Complicators

I was under the impression that computing was meant to make our life easier, but it seems there's a bunch of people out there who want to make my life more difficult through poorly thought out APIs or badly designed user interfaces. I call them the complicators.

There are three types of complicators.

Dumb Complicators - These are the developers who aren't really too hot at programming. They copy and paste and generally fumble around in the dark until they have a solution that seems to work, then quickly move onto the next problem, not thinking too much about how the UI or API they've just produced will be used in the outside world. This may be down to inexperience, the need to get something out there ASAP or just a lack of interest in producing quality software.

Evil Complicators - The second group of complicators are a cynical bunch who complicate things to make themselves indispensable to their company. Depending on how cynical I'm feeling, I may confuse either of the other two groups as being members of this lot. 

Clever Complicators - The third group are generally incredibly intelligent but have no way of empathising with the poor people who are going to have to use their software. They understand the complexity and can't understand why anybody else wouldn't be able to. I worked with a very clever guy whose API consisted of a programming language using XML to build the function calls, parameters and the graph used to join all these bits together. Yes, he was a big fan of XSLT. Yes, what he produced was incredibly powerful and clever. Actually trying to use his API from another programming language was an absolute nightmare. On the other hand, I worked with another very bright chap whose API was also based on XML. The difference being that his API simply described data and a few parameters. The actual implementation details of how it all worked under the hood was completely hidden from the API, except where necessary. The wonderful thing about that API was that the simplicity of it made me look good, since I was able to write my code on top of it in super quick time.

This third group of complicators interest me. It seems like there are plenty of clever people in the IT industry but a very select few who can actually take complicated problems and abstract them into something simple for the rest of us to understand. And doing that is the only thing that can drive technology forward. As Einstein said "Make everything as simple as possible, but not simpler."

Wednesday, July 04, 2007

Something for the ladies

Or more specifically any mothers who've stumbled across this site. My other half has set up a website dedicated to providing tips for mothers and parents in general. There are other sites out there providing similar resources (Mumsnet being the obvious example if only due to their legal problems with Gina Ford) but Mums Guide is providing a different angle on things.

She was after a link from the Random Pub Finder (due to it getting many more hits than this site) but I couldn't for the life of me think of any kind of link between pubs and parenting.

Tuesday, July 03, 2007

Aren't web services meant to solve interoperability problems?

Somebody has written a web service using JBoss. I'm trying to call it from .NET 1.1 or, heaven forbid, the MS SOAP toolkit. And neither of them can call any operations that have parameters, which kind of restricts what we can do with it. I guess one solution might be to have methods called method1(), method2(), method3() etc all the way up to MAXINT. Doesn't seem a great idea. Or perhaps an ASP.NET 2 web service could call the JBoss web service and expose the functionality as another web service? Yeh it's daft, but it might just work.

So could it be the folks telling us web services were the panacea for all our interoperability problems were actually just snake oil salesmen? Surely not...