Naming is Hard

Icon

Written by Bruce Boughton

Assembly versioning: How to include the Subversion revision number

When you build a C# project in Visual Studio, the version of the generated assembly comes from the AssemblyVersion attribute applied to the assembly. Often you want to update this version number when your code changes.

In the default project setup, this attribute is specified in AssemblyInfo.cs in the Properties directory. The version number consists of four parts, nominally: major version, minor version, build, revision. If you specify an asterisk for the build or build & revision parts, the compiler will update the version number at each build (based on the build time).

If your project is under source control, it can make more sense to link your version numbers to the version of your code at the time it was built. If you’re using Subversion, you can use the subwcrev tool from TortoiseSVN to generate the version number:

  1. Remove the AssemblyVersion attribute from the AssemblyInfo.cs file:
    [assembly: AssemblyVersion("1.0.0.0")]
    .

    Note: if you want AssemblyVersion and AssemblyFileVersion to be the same, you do not need to specify AssemblyFileVersion at all.

  2. Create a new VersionInfo.cs.tmpl code file in the Properties folder. (Try adding in the project root, and dragging it into the Properties folder). Put the AssemblyVersion attribute in the file. For example:[assembly: AssemblyVersion("1.0.0.$WCREV$")]

    $WCREV$ will be replaced with the highest Subversion revision number of all files in the project at each build.

  3. Add a pre-build event to the project (all on one line):subwcrev "$(ProjectDir)." "$(ProjectDir)\Properties\VersionInfo.cs.tmpl" "$(ProjectDir)\Properties\VersionInfo.cs"

    Make sure that C:\Program Files\TortoiseSVN\bin is on your PATH.

  4. Edit the csproj file. Look for: <None Include="Properties\VersionInfo.cs.tmpl"/>Add the following after it: <Compile Include="Properties\VersionInfo.cs"/>
  5. Build the project. The VersionInfo.cs file will have been generated. Add it to the Subversion ignore list, as you do not want it to exist in the repository.

If you want the version number to change with each build, try: [assembly: AssemblyVersion("1.0.$WCREV$.*")].

Build servers

For this to work on a build server, you need to make sure that your code is being built inside a working copy. For example, in TeamCity you need to set the VCS checkout mode to Automatically on agent in the version control settings. (Thanks, Eugene Petrenko)

Update 8 Feb 2010: Added section about build servers. Also, updated pre-build command as per Tricky Dicky’s comment below)

Skillswap went Portable

About two months ago James Box asked Glenn and I whether we’d talk about OAuth and data portability at an upcoming Skillswap—an invitation we could not refuse. A few weeks passed, and the talk was forgotten about. We were then asked to provide abstracts and bios. After throwing together an abstract and an embarrassingly brief bio, work on the talk languished until just a few days before the event.

Although this was my first proper speaking gig and in spite of my procrastination, the night went well. The audience, although modest, was enthusiastic about the subject and only one of our two laptops refused to co-operate (the MacBook Pro is still the best Windows laptop!). I was on first with an introduction to OAuth, looking at the motivation for OAuth before some less-than-flawless demos and a relatively top-level explanation of how OAuth works. After an interesting Q&A session and a break for beers, Glenn delivered a fascinating presentation about the work he has done exploring data portability using open stack technologies. If you only have time for one talk, read Glenn’s!

For posterity, I’ve embedded my presentation below. Glenn has also posted his talk on his blog and James has promised to post the audio from the event as a podcast.


Finally, I’d like to thank James for organizing this Skillswap. It was an enjoyable and interesting event, and I’ll definitely be watching out for the next one. Also, if you ever get the chance to speak at such an event, I would urge you to take it up. Speaking in front of such a passionate audience is certainly interesting and, in the words of the great Douglas Adams, mostly harmless.

Bringing OAuth to .NET developers

Over the last few months, as part of Madgex’s ongoing commitment to research and development, I have been working closely with Chris Adams to build an OAuth library for .NET, which we’ve cleverly named OAuth.net.

Today, I’m delighted to announce that Madgex is open-sourcing this library for everyone to use. To mark the occasion, we’ve put some demos up on the Madgex Lab site and loaded the source code on to Google Code!

OAuth: simple, standard and secure API authentication

OAuth is a fresh new standard that allows users to share their online data between different web, desktop and mobile applications without also having to share their passwords.

A great example of a use case is the friend import feature that all social networks seem to have. Just give them your email address and password, and they will kindly go off and find your friends for you! Oh, and they promise not to write your password down on any post-its. Honest.

Hopefully, everyone can see how this is a Bad Idea. It’s so bad, in fact, that it has a big scary name: the Password Anti-Pattern. With OAuth, however, you don’t have to give the social network your password; instead they simply send you to your webmail site where you log in and issue them a special token. The token, like a valet car key, gives access to your contacts but is useless for any other purpose.

Of course, OAuth isn’t just for sharing address books. OAuth can (and should) be used wherever a user’s private data is to be shared between a website and a third-party web, desktop or mobile application. Other examples include location-aware applications that fetch your location from Fire Eagle, and photo printing sites that turn your online photos into lovely printed albums.

Find out more

If I’ve piqued your interest (and I hope I have), here’s how to find out more. First, I will be talking about OAuth at Barcamp Brighton 3 this weekend, so if you’re lucky enough to have a ticket, pop along to my session and ask me lots of tough questions! Madgex also have a stand at dConstruct today, so feel free to pop along and grab Chris, Glenn or me for a chat. We’ll also be at ReMix UK 08 in a few weeks time, if you’re not around this weekend.

Next, download the source code and peruse the examples on the Madgex Lab site. For a more in-depth discussion, I’ve written a getting started guide where I show how to build a Fire Eagle mashup with Google Maps.

Finally, we’d love to hear from you, so email us at oauth-dot-net@madgex.com or tweet me, Glenn or Chris.

Update: Barcamp Brighton 3 presentation slides

I’ve uploaded the presentation slides here. (Although the slides are quite sparse, pretty much everything I said is in the notes for the slides)

On Lambdas

Someone at work complained today that she didn’t like the code she’d written to find an element in a collection:

public class SingletonSomething
{
	public void DoSomething()
	{
		IList list;
		// ..
		this.Host = GetHost();
		Uri item = list.Find(FindUriByHost);
	}

	public bool FindUriByHost(Uri uri)
	{
		return uri.Host == this.Host;
	}
}

On the one hand, she was using IList<T>.Find(Predicate<T> predicate) which is a neat abstraction for iterating a list to find an item. However, she was having to store some state in her singleton class about the condition to apply, which she wasn’t happy about (it’s clearly not thread-safe for a start).

First of all, thinking it was a .NET 2.0 project, I suggested she use an anonymous delegate as the predicate instead of a named method. We tried this but couldn’t convince the compiler that it satisfied the Predicate<T> type:

string host = GetHost();
Uri item = list.Find(delegate(Uri uri) { return uri.Host == host; });

(I thought this would work but it didn’t–I need to look into why.)

When I realised this was a .NET 3.5 project, I suggested a lambda instead. My colleague’s first reaction was one of skepticism–she’d not really heard good things about lambdas. But after changing the code to use a lambda, and once she’d got past the funny syntax, she was quite happy with the lambda:

string host = GetUri();
Uri item = list.Find(uri => uri.Host == host);

I think we can all agree that this is much more readable, once you realise => should be read as ’such that’ or ‘goes to’:

Find a URI in the list such that uri.Host equals host

And once you’ve seen the syntax and used it a couple of times, it’s really not that complicated: much simpler than dealing with thread safety or declaring a new method. Yet, lambdas seem to have attracted a bad name. I’m not sure why.

Perhaps it’s that they seem type-less, like var (C# developers see any attack on strong typing as tantamount to sleeping with the vicar). In fact, lambdas aren’t typeless, just as var isn’t variant: the compiler simple infers the type at compile time. Once compiled, it’s as if you’d typed it in yourself. Or perhaps it’s the funny syntax, which can take several different forms.

Either way, it’s a shame. Lambdas in C# are an extremely powerful construct. I hope C# developers can come to love lambdas just as much as they love, say, type safety.

Debugging IEnumerable.GetEnumerator

I’ve been working a lot recently with IEnumarable objects as generators. I think it’s a really nice pattern, which allows you to defer processing until it is needed. For example,

foreach (LogEntry entry in logreader)
    /* Do something with the log entry */

(LogReader does not need to read all lines in advance; instead it can read each line as it is requested)

One irritant I’ve encountered with GetEnumerator is that it can be quite hard to debug if you access class fields. The compiler transforms the GetEnumerator method body into a nested class. In the Locals window in visual studio you can’t access your class’s fields and when hovering over variables you don’t get pop-up introspection.

It is possible, however, to access your class’s fields and properties via reflection. The generated GetEnumerator class stores a reference to your class in a private field which is not exposed to the Locals window. In my experience, this is the only field in the generated class so you can access its value using the Immediate window like so:

this.GetType().GetFields()[0].GetValue(this)

If this isn’t what you’re expecting, look at the array of fields returned and find the one that holds the reference to your class (usually named something like <>4__this).

Update: If you want to access the member fields, properties and methods of your class you need to cast it to your type. To avoid doing this repetitively, you can create a variable holding the cast reference in the Immediate window:

Foo me = (Foo)this.GetType().GetFields()[0].GetValue(this);
me.Bar;
me.SomeMethod();

Emulating Java 5 enums in .NET: Part 2

Last time, I looked at how to emulate Java 5 enums on the .NET 2 runtime. This time I’m going to allow myself to take advantage of the new features supported in the .NET 3.5 runtime.

Reminder: what we’re trying to emulate

Java 5 enums allow you to enhance your enums with data and behaviour. We’re trying to recreate the Planet example in .NET:

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7),
    PLUTO   (1.27e+22,  1.137e6);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    public double mass()   { return mass; }
    public double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
}

Extension Methods

One important new .NET feature is extension methods. Extension methods allow you to augment existing classes with new member methods. For example, the following code adds a method to DateTime instances to convert them to the Unix time format (the number of seconds since the Unix epoch, 1970-01-01 0:00:0.000):

using System;

namespace MyExtensionMethods
{
    public static class DateTimeExtensions
    {
        private static readonly DateTime UnixEpoch
            = new DateTime(1970, 1, 1, 0, 0, 0, 0, 0);

        public static long ToUnixTime(this DateTime date)
        {
            return (long)(date.ToUniversalTime() - UnixEpoch).TotalSeconds;
        }
    }
}

The extension method is then visible on any instance of a DateTime object once you have imported the namespace:

using MyExtensionMethods;

public class UnixTimeTests
{
    public void Test_UnixTimeExtensionMethod()
    {
         DateTime now = DateTime.Now;
         long unixNow = now.ToUnixTime();
    }
}

You even get Intellisense!

Planet enum with Extension Methods

The plan is very simple: attach extension methods to our raw Planet enum type. Ironically, the Mass and Radius properties have to be implemented as getter methods, just as in Java, since we can’t add extension properties:

public enum Planet
{
    Mercury,
    Venus,
    Earth,
    Mars,
    Jupiter,
    Saturn,
    Uranus,
    Neptune,
    Pluto
}

public static class PlanetExtensions
{
    public static double GetMass(this Planet planet)
    {
        switch (planet)
        {
            case Planet.Mercury: return 3.303e+23;
            case Planet.Venus: return 4.869e+24;
            case Planet.Earth: return 5.976e+24;
            case Planet.Mars: return 6.421e+23;
            case Planet.Jupiter: return 1.9e+27;
            case Planet.Saturn: return 5.688e+26;
            case Planet.Uranus: return 8.686e+25;
            case Planet.Neptune: return 1.024e+26;
            case Planet.Pluto: return 1.27e+22;
            default: throw new Exception("Illegal state");
        }
    }

    public static double GetRadius(this Planet planet)
    {
        switch (planet)
        {
            case Planet.Mercury: return 2.4397e6;
            case Planet.Venus: return 6.0518e6;
            case Planet.Earth: return 6.37814e6;
            case Planet.Mars: return 3.3972e6;
            case Planet.Jupiter: return 7.1492e7;
            case Planet.Saturn: return 6.0268e7;
            case Planet.Uranus: return 2.5559e7;
            case Planet.Neptune: return 2.4746e7;
            case Planet.Pluto: return 1.137e6;
            default: throw new Exception("Illegal state");
        }
    }

    public const double G = 6.67300E-11;

    public static double GetSurfaceGravity(this Planet planet)
    {
        return G * planet.GetMass() / (planet.GetRadius() * planet.GetRadius());
    }

    public static double SurfaceWeight(this Planet planet, double otherMass)
    {
        return otherMass * planet.GetSurfaceGravity();
    }
}

This comes pretty close to being a perfect solution. We haven’t changed the enum itself so you can use it just as if there were no extra functionality; there’s no funky switch syntax, for example. There’s still room for improvement; I don’t like having the data so far from the enum member declaration. Yet, we’ve implemented the full functionality from the Java 5 example, and I think that’s testament to the flexibility of C#.

What do you think?

The source code for this experiment is available at Google Code as a Visual Studio 2008 project, licensed under a MIT license.

Emulating Java 5 enums in .NET

In the C#—Java shootout, Java edges it in my opinion when it comes to support for enums. C# enums are pretty vanilla: a set of named values, with support for flags via the Flags attribute. I’m often frustrated that I can’t add functionality and extra data to my enums. For example, here’s the canonical Java 5 example:

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7),
    PLUTO   (1.27e+22,  1.137e6);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    public double mass()   { return mass; }
    public double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
}

Each planet has a mass and radius associated with it directly in the enum definition. For example, Mercury’s mass is 3.303e+23 kg and its radius is 2.4397e6 m. The enum has a constant, G, and public methods to calculate the surface gravity of the planet and surface weight of a mass on the planet.

Emulating this in .NET 2.0

Let’s try to emulate this in .NET 2.0. We want a Planet enum with 9 entries, each with a mass and radius. From these, we want to be able to calculate the surface gravity of the planet and surface weight of a mass.

How should we express this in C#? Our Planet can’t be an enum since we can’t poke around with them (System.Enum is a very special type), so it’ll have to be a struct or a class. Enums are value types so let’s go with a struct. We still want the compiler conveniences afforded to enums so let’s keep the planets as a nested enum:

public struct Planet
{
        public enum _
        {
            Mercury,
            Venus,
            Earth,
            Mars,
            Jupiter,
            Saturn,
            Uranus,
            Neptune,
            Pluto
        }

        private Planet._ enumValue;

        public Planet(Planet._ enumValue)
        {
            this.Value = enumValue;
        }

        public Planet._ Value
        {
            get { return this.enumValue; }
            private set { this.enumValue= value; }
        }

        public double Mass
        {
            get
            {
                /* TODO */
            }
        }

        public double Radius
        {
            get
            {
                /* TODO */
            }
        }

        public const double G = 6.67300E-11;

        public double SurfaceGravity
        {
            get { return G * this.Mass / (this.Radius * this.Radius); }
        }

        public double SurfaceWeight(double otherMass)
        {
            return otherMass * this.SurfaceGravity;
        }
}

So this is a good starting point. We can construct a Planet like so:

Planet myplanet = new Planet(Planet._.Mercury);

We can switch on its value:

switch (myplanet.Value)
{
        case Planet._.Mercury:
                /* ... */
                break;

        case Planet._.Venus:
                /* ... */
}

Adding the data

However, we’ve yet to add the data, so let’s do that. We’ll change the Mass and Radius properties like so:

        public double Mass
        {
            get
            {
                switch (this.Value)
                {
                    case _.Mercury: return 3.303e+23;
                    case _.Venus: return 4.869e+24;
                    case _.Earth: return 5.976e+24;
                    case _.Mars: return 6.421e+23;
                    case _.Jupiter: return 1.9e+27;
                    case _.Saturn: return 5.688e+26;
                    case _.Uranus: return 8.686e+25;
                    case _.Neptune: return 1.024e+26;
                    case _.Pluto: return 1.27e+22;
                    default: throw new Exception("Illegal state");
                }
            }
        }

        public double Radius
        {
            get
            {
                switch (this.Value)
                {
                    case _.Mercury: return 2.4397e6;
                    case _.Venus: return 6.0518e6;
                    case _.Earth: return 6.37814e6;
                    case _.Mars: return 3.3972e6;
                    case _.Jupiter: return 7.1492e7;
                    case _.Saturn: return 6.0268e7;
                    case _.Uranus: return 2.5559e7;
                    case _.Neptune: return 2.4746e7;
                    case _.Pluto: return 1.137e6;
                    default: throw new Exception("Illegal state");
                }
            }
        }

Finally we have a complete implementation of the Java 5 Planet enum that we can use. Two things bug me at this point:

  1. It’s a lot less terse than the Java 5 definition. Surely we can move some of this out into a base class? Also, we’ve not overridden Equals and operator == which we really should do for a struct, or implemented IComparable, IFormattable or IConvertible like System.Enum. The full enum would be quite a bit longer
  2. To get at the actual enum value, we have to type myplanet.Value which is less intuitive and clean than just typing myplanet.

Adding Syntactic Sugar

Let’s create a base class, ExtendedEnum<T>, to be the base class for all our data enums. We’ll have to change our Planet struct into a sealed class that extends our base class.

public abstract class ExtendedEnum
    : IComparable, IFormattable, IConvertible
    where T : struct, IComparable, IFormattable, IConvertible
{
    private T enumValue;

    public ExtendedEnum(T enumValue)
    {
        this.Value = enumValue;
    }

    public ExtendedEnum(string enumName)
    {
        this.Value = (T)Enum.Parse(typeof(T), enumName);
    }

    public T Value
    {
        get { return this.enumValue; }
        private set { this.enumValue = value; }
    }

    // Overloads the unary + operator to convert the ExtendedEnum to
    // its enum value. This is a shorthand for extendedEnum.Value
    public static T operator +(ExtendedEnum extendedEnum)
    {
        return extendedEnum.Value;
    }

    // Implicit conversion from ExtendedEnum to the enum value.
    public static implicit operator T(ExtendedEnum extendedEnum)
    {
        return extendedEnum.Value;
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        if (object.ReferenceEquals(this, obj))
            return true;

        if (obj is T)
            return this.Equals((T)obj);
        else if (obj is ExtendedEnum)
            return this.Equals((ExtendedEnum)obj);
        else
            return false;
    }

    public static bool operator ==(ExtendedEnum left,
        ExtendedEnum right)
    {
        return left.Equals(right);
    }

    // public static bool operator != ...

    public bool Equals(T otherValue)
    {
        return this.Value.Equals(otherValue);
    }

    public bool Equals(ExtendedEnum other)
    {
        return this.Value.Equals(other.Value);
    }

    // public override int GetHashCode() ...
    // public override string ToString() ...
    // IComparable, IFormattable, IConvertible Members ...
}

Note that the type parameter, T, is constrained to a value type, and not to System.Enum, since certain special types cannot be used in type constraints.

Now our enum looks like this:

public sealed class Planet
    : ExtendedEnum

{
    public enum _
    {
        Mercury,
        Venus,
        Earth,
        Mars,
        Jupiter,
        Saturn,
        Uranus,
        Neptune,
        Pluto
    }

    public Planet(Planet._ enumValue)
        : base(enumValue)
    {
    }

    public Planet(string enumValue)
        : base(enumValue)
    {
    }

    public double Mass
    {
        get
        {
            switch (+this)
            {
                case _.Mercury: return 3.303e+23;
                case _.Venus: return 4.869e+24;
                case _.Earth: return 5.976e+24;
                case _.Mars: return 6.421e+23;
                case _.Jupiter: return 1.9e+27;
                case _.Saturn: return 5.688e+26;
                case _.Uranus: return 8.686e+25;
                case _.Neptune: return 1.024e+26;
                case _.Pluto: return 1.27e+22;
                default: throw new Exception("Illegal state");
            }
        }
    }

    public double Radius
    {
        get
        {
            switch (+this)
            {
                case _.Mercury: return 2.4397e6;
                case _.Venus: return 6.0518e6;
                case _.Earth: return 6.37814e6;
                case _.Mars: return 3.3972e6;
                case _.Jupiter: return 7.1492e7;
                case _.Saturn: return 6.0268e7;
                case _.Uranus: return 2.5559e7;
                case _.Neptune: return 2.4746e7;
                case _.Pluto: return 1.137e6;
                default: throw new Exception("Illegal state");
            }
        }
    }

    public const double G = 6.67300E-11;

    public double SurfaceGravity
    {
        get { return G * this.Mass / (this.Radius * this.Radius);
    }

    public double SurfaceWeight(double otherMass)
    {
        return otherMass * this.SurfaceGravity;
    }
}

That looks pretty good; our “enum” class now only contains code relevant to the enumeration (plus two constructors), but it’s still not that concise. This is as far as I went with the .NET 2 implementation.

Let’s take a look at what we managed to do:

  • Enumerations with data (properties) and “behaviour” (methods)
  • Syntactic sugar for accessing the enum value and casting, though the + operator is not very intuitive
  • Can still use the enum in a switch statement
  • Reasonably terse code

All in all, not bad. I’ll be looking at a .NET 3.5 solution in the next post, and possibly some more outlandish solutions after that. Until then, how would you improve the .NET 2.0 solution?

The source code for this experiment is available at Google Code as a Visual Studio 2008 project, licensed under a MIT license.

[dbo].[Fruit Salad]

Every now and then we have a Hack Day at Madgex. We’ve just had our third one (the second one during my Madgex tenure), appropriately named Madgex Hack Day III (photos, tweets) and accompanied by some brilliant t-shirts. While Andrew, Graham, Nick and I spent the day dicking around with a table football table, an Arduino board, LINQ, ASP.NET and WinForms, Jane and Chris worked on a keyword search engine built in T-SQL called Banana which uses configurable field weightings.

You see, at Madgex, we’re a bit fond of tropical fruit. Last hack day, a group of us worked on Mango, a .NET implementation of the Django templating language, which we’ll soon be using in our production websites.

Perhaps it’s a subconscious effort to offset all the cake we eat, or perhaps we’ve just taken the five-a-day campaign to heart, but now Jane and I are working on Papaya.

Another perk of working at Madgex is that we are allowed to spend up to 15% of our time working on our own projects and learning, and this is in addition to any training required for our jobs. This scheme is called Ideas and Learnings Projects (ILP) (photos, tweets).

On the learnings side, fellow Madgexians have been running sessions on areas they are knowledgeable about (ranging from unit testing to time management to neuro-linguistic programming). We’ve also had external speakers. Dan Webb spoke about Metaprogramming JavaScript and Simon Willison introduced us to Comet (and he’s coming back soon to talk about OpenID). Equally, people can spend time on traditional learning courses such as professional accreditation.

There are a plethora of projects being worked on too. Some people are assessing new technologies (for example, Adobe AIR). Others are working on internal tools. Still others are working on projects which may see the light of day in our Job Boards. The projects are the part of ILP that excite me the most. I’ve got several on the go at the moment, which I will be blogging about, and one coming up that I’m especially excited about.

So, what’s all this Papaya business?

Papaya will be a tool which allows us to version our databases and to ensure that they remain in a consistent state across schema and procedure changes. This comes out of the investigation Jane and I did into DBVerse. When writing change scripts, you will add information about the changes to a XML file. This file will group sets of changes into releases with version identifiers and single change scripts with version identifiers. Each change or release will state the previous versions it depends on so that the tool can ensure change scripts are only applied to the database when it is safe to do so.

While the premise of Papaya doesn’t sound that exciting, it will hopefully be a really useful tool and it’s a great opportunity to polish my SQL skills.

Snow in April?

If you haven’t heard by now, Brighton woke up this morning to quilt of snow. We went down to the beach to marvel:

Climate change is not all bad…

Homes & Gardens features O’Fabulous

I recently designed a website for O’Fabulous, a wonderful boutique hotel in County Donegal, Ireland, created by my friends at Swell Group. Now, the May issue of Homes & Gardens has featured O’Fabulous in its Destinations section:

This is everything that a boutique hotel should be: small, perfectly formed and oozing personality. O’Fabulous indeed.

Click below to see the full article [jpg]:
We love………… O’Fabulous – Homes & Gardens

 

July 2010
M T W T F S S
« Dec    
 1234
567891011
12131415161718
19202122232425
262728293031