October 04, 2007

A New Combination of Flavours

Well, my time off has given me back my leisure time and I have been pursuing a number of projects. All of which will be blogged here some time soon. The first and simplest one is a new combination of flavours that I have found that works really, really well.
  • Fennel Seed
  • Szechuan Pepper
  • Garlic (smoked if available)
  • Avocado Oil
  • Lime Juice
It work brilliantly well either as a marinade for fish, poultry or quorn or as a salad dressing.

First grind about a teaspoons worth of fennel seed with the same amount of the pepper in a pestle and mortar Then chop a large clove of the garlic roughly and grind together with the fennel seeds and pepper. Scrape the micture out in a bowl and add the juice of one lime before pouring in about three times as much avocado oil.

If you're going to use it as a marinade; it can be a good to add a tablespoon of corn flour (corn starch as the USA has it) and beat thoroughly to help it coat better.

As a salad dressing use sparingly as it packs a punch.

July 31, 2007

The TT has landed.

Well, my car arrived last Friday and in between the fun of running it in I've taken the time to take a couple of photos...

July 11, 2007

Is Writing Software an Engineering Discipline?

The answer is a very and extremely definite - no.

There have been many learned and wise discussions on this topic. Some people believing that it is an art and other people people believing that it is engineering. I vociferously straddle the fence and state clearly that we are all artisans. We, like the medieval cathedral builders, partake equally of art and science to build our towering edifices.

The simple fact is that for the majority of projects we still can't properly predict the time and effort required to complete them. We are not methodical enough and have yet to build up the corpus of knowledge and expertise to bring true science to our discipline. We are at the most creative phase, where new problems and new solutions are being devised all the time. We are slowly going the engineering path, using patterns and other tools to start to define best practices, but we are not there yet.

There is one major thing that I believe that people working in software can learn from engineers: The fact that all true engineering is a methodical approach to compromise.

Too many people fail to understand and manage the fact that every piece of software is a balance between competing technical, business and personal concerns. We are still artisans because personal opinion still is the best tool in determining the compromise that is reached and so many of the so called 'methodologies' are nothing more than snake oil.

June 29, 2007

Twice Cooked Lamb

I decided to cook up some leg of lamb the other day and inspired by the way that hams are made I did a two part cooking process: Poaching the lamb before roasting it.

I poached the leg of lamb for about 2 hours in a liquor made up of:
  • Enough lamb and vegetable stock to cover the leg.
  • 2 cloves of garlic, crushed.
  • A cup of good quality red wine vinegar
  • A bouquet garni, made up of thyme, bay, marjoram and rosemary
  • 10 or so whole black peppercorns
I turned the lamb over about half way.

I then took the lamb out of the poaching liquor and placed it in a baking tray. I poured a little teriyaki and sunflower oil over the lamb before putting it in an hot oven (200c) for about half an hour.

Skim and boil the poaching liquor down to about a third to one half of it's original volume, allow to cool a little before tossing in some chopped mint.

Serve sliced with steamed vegetables and the starch of your choice - I like brown rice or quinoa - pouring the liquor and mint combination over.

The lamb will not be 'pink' in the modern idiom, but will be tender and very delicious.

June 27, 2007

Binary Manipulation in a String Friendly Language

Well, it's been a while since I blogged; and there's been a good reason since I had nothing worthwhile to say.

I've now got two things that I want to talk about; one is technical and the other is about cooking.

On to the technical. I'll blog the cooking in another entry.

Just recently at work I had cause to revisit an old technique that I hadn't used in years and I thought that it would be worth recording here.

We've been working with small binary fields in the database containing information that needs to be parsed. So far within the system we have kept much of the data-centric heavy lifting within the database but we were having difficulty with the binary information. The database provided a set of procedures for manipulating the binary information, but they were not very efficient. They were designed to work with extremely large pieces of binary information and tended to keep the binary information out of memory and in the database.

In general the database was far more designed to work with strings.

The work around was one that had been used when binary information needed to be manipulated by string-centric languages in the past. We converted the binary into a hexadecimal string. This allowed us to make use of in-memory string datatypes, and all the very efficient string manipulation tools that the database made available to us (but with the offsets doubled!). In this case we were fortunate as the database was able to do direct conversions from hex into numbers and then perform AND operations on the numbers as needed.

If that capability hadn't been there we could have used a further technique: to do a fast AND from hex you just build a look up table. The table provides a look up between the two hex values that you want to AND. For example a look up table that does just one hex digit at at time would look like:
A hexadecimal AND lookup table
HEX - AND0123456789ABCDEF
00000000000000000
10101010101010101
20022002200220022
30123012301230123
40004000400040004
50101454501014545
60022446600224466
70123456701234567
80000000088888888
90101010189898989
A0022002288AA88AA
B0123012389AB89AB
C00040004888C888C
D010145458989CDCD
E0022446688AACCEE
F0123456789ABCDEF


If you don't mind sacrificing more memory a 2 hex digit or greater lookup table can be created and of course a lot of the time you can distill the lookup further as you only need to do a single bit mask operation and so you would only need on one axis 1,2,4,8 etcetera.

By turning the binary manipulation into a hexadecimal one, we managed to increase the performance by 500%. Of course for really heavy binary manipulation you can't beat a binary friendly language but this technique can be an useful 'good enough' solution.

April 18, 2007

Software Mass Production

Every few years I come across a company where some managers come up with the idea of a 'software factory'. The thinking is that mass production techniques and their economies of scale could bring some major cost savings.

Let us look in detail at the mass production of cars. Immediately a vision of a production line comes to mind. Cars being bolted together from thousands of mass produced pieces for very little money.

Unfortunately this vision is where most people's understanding of mass production begins and ends. The reality is far more complex. Reality uses prototyping.

When a manufacturer decides on a new line of cars, many prototypes are produced. Each prototype serving a different purpose. Some are mechanical prototypes used to design and test key new components. Some are aerodynamic prototypes. Others are ergonomic and styling prototypes.

There is one final prototype - the culmination of all that has gone before. This prototype costs tens or hundreds of millions as this has specific jigs, robots, templates and all kinds of other machines made expressly for it.

This prototype is the 'Production Prototype'. Once the millions have been spent and the prototype is complete and tested, you suddenly find that you have a production line ready to make thousands of copies of it for very little money.

Most people when thinking about applying mass production techniques to software do not understand the production prototype.

Every new piece of software is a production prototype. Software's production lines are the scripts and the disk copier.

We have already learnt most of the lessons we need from mass production in industry. In the car industry the production prototype often saves money by using an established platform and reusing existing components. In mass production every effort is made to reduce the cost of the production prototype, in software production we do the same.

Anyone who thinks that they can revolutionise software production by copying the mass production in industry are about twenty years too late. It has already happened.

March 27, 2007

The Boothby Fogcutter

My Boothby grandfather was an interesting man aside from his exotic pets he was a bit of an inventor. He came up with all kind of things, mainly aeronautic despite being a naval man.

His one invention that has directly impacted my life was the 'Boothby Fogcutter'. Described as a 'catch-up drink', he invented it so that when he arrived at parties late where everyone was several drinks merrier, he could be as merry as them within 10 minutes.

The recipe is as simple as it is fiendish:
  • Take a half pint glass.
  • Add 1-4 shots of dark naval rum depending on how much catching up you need to do.
  • Fill the rest of the glass with cider. I preferred dry but with a sweet cider it is described as tasting like an inferior Tokay.
The real problem with this drink is gauging how much to catch up. It is all too easy to overshoot. It is also worth noting that under no circumstances should this be drunk at any time other than at the start of a session of drinking as I have learnt to my cost.

I introduced the 'Boothby Fogcutter' to my college at Cambridge in my second year and I don't think that Corpus Christi ever recovered. A number of deplorable incidents ensued, usually because the drinkers did not judge the shots of rum correctly or drank it later in the evening after already getting merry.

The incident that sticks most in my memory was at one of Corpus' annual Rugby Club dinners. These were alway boozy affairs.

The routine of the evening was extremely well defined. The club members would meet up in the college bar for a few pints at six o'clock. At around half past seven we would head up to a reception room to make a start on the sherry. At 8 o'clock we would be seated to eat, accompanied by the mandatory fellow of the college who would have to sit in on any function making use of the college facilities. There were invariably three courses, each accompanied by a different wine. The main course was alway a posh variant on steak and chips. After dessert we would start in on the port and after that was finished various people would be sent to the college bar for further supplies of alcohol. At about 10:30 we would pour ourselves out and adjourn to the bar for a few more convivial drinks and, if any of us were still standing, we would see what else would happen.

The year that I introduced the 'Boothby Fogcutter' proceeded along the lines of any other I was pretty well lubricated by the time that the port was finished and when volunteered to get further supplies I decided that this was an opportune moment to introduce the rugby club to a new drink.

I staggered into the bar and somehow managed to convince the bar manager that what I really wanted was 22 'level 2' Boothby Fogcutters. I felt that 2 shots of rum each would be sufficient. Carrying a heavily laden tray I made my way back to the dinner.

Looking back, the major warning sign came when I tried to mount a flight of steps carrying the tray and lost my footing. I fell, but was in that peculiar elevated state that the very drunk have that allows them to keep their containers of alcohol intact. There was a little sloshing but I managed to keep all 22 glasses on the tray and largely full.

Arriving back at the table of drunken rugby players I dispensed my largesse. A couple of people declined and despite my suggestions to the contrary the responsible, senior fellow decided to have two. My last recollections of the evening were of the start of a round of the 'I have never' game where you stand up and drink if you have.

I woke up the following day in a terrible state. I had mixed grain and grape and had had a 'Boothby Fogcutter' halfway through a nights drinking. I had lost my glasses, I was pretty sure that I had been sick given the state of my mouth and chin and had an enormous bruise on my left shoulder.

Over the course of the next couple of days I reconstructed what I had done. I had made it back down to the bar and then gone into the JCR (Junior Combination Room - basically a common room with seating) where I had decided to join in a game of rugby using a rolled up newspaper. My fellow prop forward Tom and a guy named Ed had tackled me and I had gone shoulder first through the closed double doors of the neighbouring television room, taking one of them off their hinges. I then staggered forwards through the assembled viewers to the front of the television room and stood being sick out of the window behind the television for about 5 minutes. At the time I had not realised that there was a bicyle under the window and with uncanny accuracy I had targeted the seat.

After that night I never drank heavily again. The 'Boothby Fogcutter' continued to cause mischief around college and I'm pretty sure continues to cause havoc wherever Corpus people go.

I leave my final thoughts with the fellow of the college who became the first to be up before the Dean for discipline in several decades. I still don't know what he got up to after the second fogcutter.

March 23, 2007

Smoked Cod and Chips

When I lived in Ireland one of the great pleasures in life was to adjourn to a local chippy called Caffola's and devour a beatifully cooked smoked cod and chips. The cod was only lightly smoked, more to give flavour than preserve and added a delightful high note to a wonderful dish. It was a truly great way to prepare for an evening out at Rocky's followed by Badger Brown's.

I've always loved smoked fish; salmon, mackerel, haddock etc.

I've recently found smoked cod becoming available more widely in the UK so I decided to attempt to recreate the experience.

In consulting various cookery books and looking online I discovered an argumentative group of people who either create or collect frying batter recipes and my goodness there are a lot of them.

In the end I settled on a batter recipe that was a synthesis of several of the others and so here it is:
  • 2/3 cup of strong flour
  • 1/3 cup of cornflour (For Americans that is cornstarch)
  • 1 generous pinch of salt
  • 1 spoonful of castor sugar
  • 1 cup of good water (mineral or filtered)
  • 2 egg whites whipped to soft peaks
Sift the dry ingredient together in a mixing bowl and add the water gradually, mixing until a smooth paste is formed - I would normally expect to have some water left over. Fold a little of the egg whites into the paste to loosen it, fold about half the remaining egg whites in and finally fold the remaining egg whites in.

To batter and cook the smoked cod I cut it into nice fillets, dried them with kitchen towel and coated in a little flour.

I had a wok with combined sunflower and avocado oil ready heated - I tested the temperature by dropping a small piece of batter in and checking that it puffed and crisped within a few seconds.

I passed the prepared cod through the batter and slowly lowered it into the wok so that the batter in the oil had a chance to seal and puff before it came into contact with the base or sides of the wok or other cooking pieces. For a large piece of cod I allowed 12 minutes cooking time and for a smaller one I allowed 9 minutes. The cod floated as it cooked so I turned it over every few minutes to ensure that both sides cooked evenly.

For a first pass I didn't do any chips, I just served it with a herb salad and a large piece of lemon.

It was really quite good. In fact it was bloody delicious.

I'm going to take a little more time on the batter to get it absolutely perfect but so far, so good.

March 14, 2007

Techniques for working with Temporal Databases.

I've been working recently with a temporal database and have gone back over my blog as a result to see what I've written on the subject.

All that I've written so far is a simple diatribe on temporal modelling.

I think that it is about time that I share a hard won lesson about working with temporal databases in multi-user environments: It is alarming how frequently concurrency can be messed up.

The problem begins with the fact that classical key based uniqueness checks just don't work. In a temporal database you must be able to support many rows referring to the same entity, each row covering a period in the entity's life. This means that any time that you wish to retrieve a view of an entity you either retrieve a set of rows defining the whole life of the entity or you choose a point in time and use a BETWEEN ... AND clause to select a single row indicating the state of the entity at that point in time. Effectively any key has a temporal element. The full key being the identity of the entity, a start date and an end date for the period of time for which the attached information was/is/will be correct.

So far so good, however databases are just not set up for checking this kind of key. They can trivially check the uniqueness of a key - the fact that a given row representing an entity does not have the same combination of identity key and start and end dates. Can you sport the flaw though? What is needed is the ability to check that the row does not have start and end dates that OVERLAP with those of another row for the same identity key. If they do overlap then we end up with two valid sets of data for an entity on a given day - obviously no good.

Keeping up? Then on with the complexity! The first pass attempt at fixing this is to add application or database level programmatic checks that check whether there exists a row that overlaps. That seems fine as far as it goes, however there is a problem - if two users are performing an update at the same time then standard 'transaction isolation' causes a problem. In most databases the default behaviour is that a user can only see committed work done by other users this means that if both users are updating the same entity then the programmatic checks will not see the changes being done by the other user until they commit it and the overlapping rows can still occur.

I've seen a number of bizarre solutions that attempt to solve this, two of the least satisfactory were to either relax transaction isolation so that each user can see what the other is working on (doesn't work in the end) or to have processes that find overlaps and manually resolve them (oh the work!).

The proven solution is to use a sensible locking strategy. The locking strategy can be used to ensure that the programmatic checks are run correctly despite multiple users maintaining the data. You can't use the temporal rows to do this useful locking. Typically I would analyse the data model and either identify non-temporal entities that can be used to lock sets of temporal entities or create my own non-temporal entities for the locking. This kind of non-temporal entity used to lock temporal entities can be referred to as a lifeline/timeline lock. When the lock is obtained you are locking out the entire lifeline of the entity being maintained and preventing other users/processes working on it simultaneously.

January 19, 2007

A New Car

A couple of weekends ago I finally bit the bullet and put the deposit down on a new car - an Audi TT. I went with the 3.2 litre quattro in Ibis White with a Mineral Grey interior. The salesman (the third that I had dealt with - the other two had left the industry soon after I saw them) was quite enthusiastic as he had been trying to convince his boss that the TT in white would make a nice show car and he would finally have the chance to show him.

I went moderately wild on the extras. iPod attachment, decent stereo, Audi magnetic ride etc. As this is my first ever brand new car I have to admit to lessened self-control. I did avoid things like the electric seats and the self-dipping xenon headlights though. I'm still torn as to which was the most useless option that I chose though: The luggage nets or the extended leather trim.

I'm still debating whether to get the car debadged as I'm not particularly interested in advertising the fact that I've gone for the most expensive model to all and sundry.

What I'm most irritated about is the fact that I may have a fight on my hands when it comes to getting the licence plate that I want BO07 HBY. I checked the DVLA website and it is up for auction 'soon'. I'm not absolutely desperate to get it, but I would be upset if it ended up not with a Boothby but with some obsessed Star Trek fan.

January 11, 2007

Balancing Ease of Use in Designs

I've long held that in software design and development that the only wrong way of solving a problem is one that does not work. I do however believe that some ways of solving problems are better than others.

In various entries I've talked about the ways I approach trying to arrive at better solutions, some of them were quite abstract. Most of them are ways of evaluating whether one solution is better than another.

In conversation yesterday with Neil, one evaluation came up that I have found very useful: which solution makes the everyday usage easiest?

This evaluation is probably quite familar to consumers of Application Programming Interfaces (APIs) but often does not seem to be familiar to producers of APIs.

When designing something always consider adding a bit of complexity to doing the unusual things in order to make it easier to do the usual things.

January 05, 2007

Albert the Mongoose

Time for another family history blog entry. Today I want to tell some stories about Albert the mongoose.

Albert was ridiculously tame, he was a particular pet of my father's who had a poachers pocket sewn into many of his coats so that Albert could travel with him. Often, when my father was having a chat with an acquaintance or talking to a shopkeeper, the conversation would grind to a sudden, staring halt as Albert stuck his head out of the coat to see what was going on.

My grandfather was aware that Albert needed plenty of exercise. The favoured form was to tie a brick to a piece of rope and swing it around. Albert would bounce over the brick on each pass with evident enjoyment.

Albert loved people as they were always doing something interesting and would often wander off to see what they were up to. Once shrieking was heard from one of the neighbouring houses and on investigation it was found that Albert had introduced himself to a new cook. The cook did not appreciate the introduction and proceeded to defend herself with what was to hand: A basket of eggs. Albert thought this was wonderful as he not only got to dodge each egg as it was hurled but also had a race to see how much he could eat before the next egg arrived.

Possibly Albert's finest hour was one afternoon as he rested in a sunny spot on the large back lawn. A local tom cat spotted him. This cat was well known, he had caused no end of havoc among the local feline population, had despoiled birds nest for miles around and had caused much angst to the local humans too. The tom cat went into the full stalking mode; body low to the ground, ears pointed and slow, careful movements. Apparently it was a masterpiece of stalking, no noise, barely a shiver of the grasses and always downwind.

After nearly half an hour of stalking, the cat was perfectly positioned to pounce. What the cat had failed to notice was that thoughout all his zig-zag stalking from cover to cover, Albert had managed to always keep his back square to the cat.

With a tail twitch and a wriggle the attack was launched, but when he landed on the patch of ground that was Albert's resting place, the mongoose was no longer there - he was three feet up and dropping perfectly onto the cat's back. In went all of Albert's claws and with evident satisfaction a firm bite was made to the fold of loose skin on the back of the cat's neck.

The cat took off, squalling round and around the garden. As time went by the cat got more and more tired, more and more quiet until finally, panting heavily, he slowed to a staggering walk and stopped by where Albert had been resting. The mongoose let go and daintily jumped down.

The cat staggered from the garden and was apparently never seen again.

December 20, 2006

Latin is a language....

Much of my programming is informed by my mother's career as a linguist.

She grew up part of an Anglo-Scots family in Argentina and is fluent in both Spanish and English. From an early age she worked hard to expose me to a range of languages through friends. Not just European languages but also any others (including Nepalese, Urdu and others from an old Gurkha officer).

At school I was made to study French, Latin and Ancient Greek.

I did not turn out as she expected - she taught me the analysis and understanding of languages in general but I instead focussed it on English and computer languages.

When dealing with customers it is essential to understand what they are trying to communicate. I became better at this when I fully realised that English is not just one language but a family of dialects and jargons. The way that different groups of people use English can lead to all kinds of misunderstandings. Just think of the different uses of the word 'Monitor':- A computer display, a thread monitor, a school prefect/official, the verb etc.

In many cases I have found that disagreements arise not because of differences about how a system should work but instead because of differences in how the words describing the system are used.

When it comes to computer languages the awareness of language can be very revealing. One of my favourite examples of this is a brilliant speech by Guy Steele: Growing a Language.

I'd recommend that any software developer, designer or architect pay a little more attention to linguistics.

December 14, 2006

The Quantum Boolean Anti-Pattern in XML

One of my pet peeves is the Quantum Boolean anti-pattern.

'What the heck is that?' I hear you cry!

Well it is where some bright spark defines an element or attribute as boolean (true or false) but it may or may not be present (minOccurs="0").

What then happens is that you never get to see false. Either the element or attribute is present and set to true or it is absent and you have to guess that it is implicitly false.

Please decide to set it to boolean and make it mandatory or make it an optional marker element with no sub-elements or attributes.

December 08, 2006

George the Rock Python.

After some positive responses to the family anecdotes about Dulce de Leche, I though that I might share another one.

My father's family certainly accumulated a fair share of these anecdotes. My grandfather kept some quite interesting pets: George an Indian Rock Python and his old friend Albert the Mongoose.

Albert and George were good friends despite their natural instincts. Many was the time that George would be seen asleep in a sunlit place with Albert asleep on top of him.

Next door to my grandfather lived a retired British India Army colonel (my father always referred to him as a 'Boom-Puna' British India Army Colonel). He and his wife had returned to England and had settled into a contented if liverish life filled mainly by complaining how much worse off they were in England. He was a bit of a drinker; my father at the age of 12 delivered a message to him and was offered a gin and tonic.

Soon after moving in, my grandfather (who had an evil sense of humour) bribed my father to take George and deposit him on the colonel's front lawn. He was told to hide in the hedge to keep an eye on George and to report the reaction back faithfully.

With a certain amount of effort (as my father was only a boy at the time and George was a big snake - 12 feet or so), George was deposited on the lawn. My father retired to the nearby privet hedge and, having made himself comfortable, awaited the colonel's arrival with interest.

Soon after the colonel strode out of his front door to take his morning constitutional and found himself confronted by George who was just stirring sluggishly in the morning sun.

He froze for nearly a minute and paled dramatically before rushing back into the house crying 'Maud! Maud draw a cold bath! I've got the DTs again!'

December 06, 2006

One Way to Reduce the Risk of Social Engineering Attacks

In my day to day job I work with a number of secure systems. A number of them are entirely internal, but the others are customer facing. There are also certain operational procedures which are instigated at a customer's behest (the customer phones up and asks - I've been taken to task for my sesquipedalian posts...).

The problem comes when the customer is asked to provide identification. The classical approach is via some form of shared secret - you know the kind of thing - a maiden name or some other personal piece of information.

I've never been comfortable with this kind of security scheme as it relies on security through obscurity in the first instance and on the honesty of the company staff in the second. Anyone can now trawl through public records to find out the kind of personal information used for this security scheme and increasing numbers of cases of personal information being stolen at call centers are coming to light.

Many of the systems I work with have dual channels for customer interaction:
  • A secure online channel - for day to day customer use of the system.
  • A phone number - for out of the ordinary requests.
To reduce the risk of Social Engineering attacks I advocate using a scheme that provides authentication for the phone calls through the secure online channel.

The steps of the scheme work like this:
  1. The customer decides that he or she needs to make a call.
  2. The customer accesses a function on the secure online channel to enter a password for that call.
  3. The customer enters the password.
  4. The system digests the password and stores it.
  5. The customer makes a phone call.
  6. The customer representative requests the password and enters it on his system.
  7. The system digests this password and compares it with the stored one.
  8. If they do not match then the customer has not been authenticated and the representative politely handles this.
  9. If they do match then the customer is authenticated and the call proceeds.
  10. The system clears the digest preparatory for a new support call.
This scheme does rely on a couple of things:
  • The presence of the online channel
  • The fact that the customer does not mind the added complexity versus the increased security (this can be handled by clear public relations explaining how this scheme reduces the risk of identity theft etc.)
We are building a chain of trust here. We base the authentication of the customer over the phone on the authentication of the customer over the online channel.

The security of this system can be fine tuned in a number of ways:
  • A more complex password (length, character types etc.) can increase security but at the cost of increasing the complexity of the customer interaction with the system and the representative - try explaining !B00thbY over the phone. The fact that the password is intended to be only used once should allow for a simpler password.
  • Store the digests of previous passwords and introduce a clear reuse policy. This introduces a marginal increase in customer complexity for a good increase in security.
  • Allow (limited) reuse of passwords. This reduces the security but can be very useful in a scenario where support is needed when the online channel is down. The user can generate a password in advance for, say, 5 uses after which time one would hope that the online channel is back and a new password can be generated. Further modifications can come in the event of an extended outage where the password use could be extended.
This security scheme produces a limited shared secret in a relatively simple and secure way and neatly eliminates the use of most personal information from customer interactions. I hope that I have illustrated not only the scheme but the compromises involved.

November 24, 2006

Mock Gravy

I think that it's time for another culinary discussion.

I love gravy. To me gravy is one of the great culinary delights and adds immeasurably to the right dishes.

The trouble is that I hate all instant gravies and have never felt that gravy recipes that did not involve the juices from roasting were really gravy.

In the end I resolved to come up with a way of making a good 'mock' gravy. It turns out that with the right tweaks it can make a really superior vegetarian gravy.

The fundamental idea is simple. To emulate the roasting process and produce the same flavours.

To do this I put oil (as a substitute for fat) in the bottom of a pan. Depending on whether I am trying to make a chickem, pork or beef 'mock' gravy, I use more or less oil.

To the oil I add a tablespoon of vegetable bouillon and two tablespoons of the appropriate other bouillon. I add a tablespoon of soy sauce, a drop of mushroom ketchup and a couple of tablespoons of lemon or lime juice.

You can optionally add some of the herbs that you would use for roasting, a little garlic and/or onion powder. If I'm making a beef gravy I will often also add a teaspoon of beef Bovril.

The next job is to heat the ingredients in the pan over a medium heat, stirring frequently. The intent is to recreate the process that in the bottom of a roasting tin.

The oil will stay somewhat separate from the other ingredients. You are looking to end up with the oil separated from a thick, glutinous liquor after cooking the ingredients. This should take a few minutes only. If you end up with a gritty mixture that will generally mean that the ingredients have been overcooked.

Now add enough flour to absorb the oil, mixing thoroughly.

Cook the flour and oil mixture for a minute or two. You want the flour cooked but not burnt so stir it continuously. The pan should now look to contain very dark brown bread crumbs.

Add 100-150 ml of cold water to the pan and stir hard. The flour will absorb the water and start to come together.

Now start adding the stock to the mixture a 50 ml or so at a time. Each time stir until the mixture (roux) has become smooth again and there are no more large lumps. The pan remains on the heat throughout this process.

When enough stock has been added the roux will have become runny and the rest of the stock can be addded.

Bring the pan back to the boil and taste. Season if desired. One can either add gravy granules/cubes or boil the gravy down (stirring frequently) until the desired intensity of flavour is achieved. Other flavours such as redcurrant jelly can be added at this time.

The gravy is now ready for serving. Pour it over a large helping of bangers & mash, a bowl of couscous or anything else that takes your fancy.

To make the vegetarian version simply use all vegetable bouillon and stock. This recipe scales up very well.

Ingredients
  • Oil (vegetable, olive or something similar)
  • Bouillon (I tend to use the Knorr 'Touch of Taste' bouillons)
  • Soy Sauce
  • Mushroom Ketchup
  • Lemon or Lime Juice
  • Roasting Herbs (Optional - Rosemary, sage, thyme etc.)
  • Garlic Powder (Optional)
  • Onion Powder (Optional)
  • Beef Bovril (Optional)
  • Flour
  • 100 - 150 ml Cold Water
  • 1 Litre of Good Stock
  • Salt and Pepper

November 17, 2006

Good Threaded Code 2

I've been writing concurrent code in Java for some years now and like to believe that I've learnt a few things in the process.

In Java all objects have a mutex and monitor associated with them and so any object can be used to provide concurrency control and signalling. Java allows code to synchronize on any objects to which it has access, this includes the object declaring the code. In fact Java positively encourages you to synchronize on the declaring object by providing synchronized methods and allowing synchronized(this).
For example:
public class ConcurrentClass
{
public void doSomething()
{
//do something thread safe...
...
//do something not thread safe...
synchronized(this)
{
...
}
}

public synchronized void doSomethingElse()
{
//do something not thread safe...
...
}
}
When you call doSomething() or doSomethingElse() the mutex of the ConcurrentClass instance is only held for the duration of the synchronized block or the synchronized method.

I believe that this approach violates encapsulation. The mutex used to control the internal concurrency issues of the ConcurrentClass instance is available to other classes and so other classes can participate in the internal concurrency concerns of the ConcurrentClass instance. At first sight this might not seem a bad thing but just stop and think for a second. This means that concurrency control for a specific resource can be spread across several classes. Rather than debugging one class you may have to debug many.

I would far rather write something like:
public class ConcurrentClass 
{
private Object mutex = new Object();
...

public void doSomething()
{
//do something thread safe...
...
//do something not thread safe...
synchronized(mutex)
{
...
}
}

public void doSomethingElse()
{
//do something not thread safe...
synchronized(mutex)
{
...
}
}

}
This means that the mutex and thus the concurrency control is fully encapsulated within the class.

An example where the lack of encapsulation can cause a problem is in java.lang.Thread. I have seen application code that sub-classes java.lang.Thread and uses synchronized methods or synchronize on the thread object. If the application code deadlocks it becomes impossible to use any of the normal methods to control the thread as they are all synchronized on the thread themselves.

November 03, 2006

Idempotence? What's that?

When I'm architecting enterprise systems I often get that response when I talk about my preferred alternative to using 2 phase commits and XA.

Idempotence is not a particularly difficult concept. I define it as a behaviour that has the same outcome on the second, third, fourth etc. time of trying as it had on the first.

A lot of things in our day to day life are idempotent. Say you are going to the car with some bags. On reaching the car you put the bags down and go to unlock the car; you are then interrupted by a friend calling to you and you have a chat. When you turn back to the car you can't remember if you unlocked it or not so you go to unlock it again. If you had actually already unlocked the car, it will remain unlocked. Unlocking a car is normally idempotent - I'm not answerable for odd car designs or for people that actually lock their cars again when they do this.

This can be extremely useful when you are trying to integrate two disparate transactional systems. Lets call one system A and the other B. If we are doing something in A that needs a change to be applied in B we can make the change to B idempotent.

The process would often work like this.
  1. Open a transaction in A.
  2. Do the work in A.
  3. Open a transaction in B.
  4. Do the work in B. Idempotent
  5. Close the transaction in B.
  6. Close the transaction in A.
If a problem occurred in steps 1 to 5, systems A and B would be in a consistent state as both transactions would be rolled back. If a problem occurs at stage 6 then B would have the change while A doesn't.

When the process is re-run successfully A and B will end up in a consistent state as long as the work done at B is idempotent.

This is a much lighter weight mechanism that the 2 phase commit / XA one but it does mean that there is a window in which A and B can be inconsistent. For many systems this window may not be a problem in which case I'd recommend the use of idempotence.

November 02, 2006

Another month between posts.

A lot has happened to me in the past month. My cousin James came to visit, I faced eviction due to my landlord's non-payment of mortgage, I moved to a lovely new place in a converted chapel, I went speed dating and have spent an awful lot of time trying to get broadband into my new place so that I can work from home.

This morning I had a good breakthrough with JOGL - working out how to initiate an offscreen pixel buffer without needing a full blown AWT or Swing GL canvas.

With my life calming down a little (off to see the Two Gallants tomorrow in Brighton), I'll hopefully blog a little more.