Enums Evolved

February 19th, 2010

Keying on a particular value is one of the first things we learn in programming.  As time goes on and we learn more advanced concepts, sometimes the little things tend to get lost in the dust and we keep doing things the same way we learned them in grade one.  I recently experienced a little of this pain in a bin packing project I’d been working one.  It all stared with enums, but for the sake of completeness I’m going to start all the way back with strings because that is probably what we all cut our teeth on.

The scenario is this. In a cuboid (box) that is axis aligned we will only ever have six surfaces. In writing code to deal with the cuboid we will be working with these surfaces and we need to know which way that surface is pointing.  Using a simple string approach we might represent it like this…

public class Surface : Rectangle
{
	public static string OrientationBack = "Back";
	public static string OrientationFront = "Front";
	public static string OrientationLeft = "Left";
	public static string OrientationRight = "Right";
	public static string OrientationUp = "Up";
	public static string OrientationDown = "Down";
 
	public string Orientation { get; set; }
}

Now we have a string that tells us the direction that the surface we are working on is pointing. A better approach to the string method would be to put the strings in their own class.

public class Orientation
{
	public static string Back = "Back";
	public static string Front = "Front";
	public static string Left = "Left";
	public static string Right = "Right";
	public static string Up = "Up";
	public static string Down = "Down";	
}
 
public class Surface : Rectangle
{
	public string Orientation { get; set; }
}

The string approach is not optimal for several reasons. 1) We know that the types of orientation are never going to change and so representing orientation as a string is dangerous because if a bad string is used then our logic will not be able to account for it. 2) String comparison while not exactly slow, could be improved by another type. This type of problem would be much better served by an enum instead.

public enum Orientation
{
	Back,
	Front,
	Left,
	Right,
	Up,
	Down	
}
 
public class Surface : Rectangle
{
	public Orientation Orientation { get; set; }
}

This is better because we can guarantee that only our six types will ever be used as an orientation. Plus because enum types are based on integers, comparison operations are fast.

Now we need to do something based on which direction our surface is pointing. This situation appears because our surface is anchored in 3d space by a point which represents its upper left hand corner. We also have its width and height. However in order to do faster collision detection, rendering and ordering we need to translate those values into absolute coordinates for the axis that our surface is sitting on. This means that if we have a surface that is facing left, our depth is going to be on the X axis, our height will be on Z axis, and our width will be Y axis of the 3d container space. This will change depending on which side we are working with. Don’t worry if this doesn’t make sense, it’s simply an example to help illustrate our problem. We are going add these properties to our surface class.

/// <summary>
/// The depth of this plane on the Axis it is aligned to 
/// </summary>
public decimal Z { get; private set; }
 
/// <summary>
/// Top of this surface on the axis it is aligned to
/// </summary>
public decimal Top { get; private set; }
 
/// <summary>
/// Bottom of this surface on the axis it is aligned to
/// </summary>
public decimal Bottom { get; private set; }
 
/// <summary>
/// Left side of this surface on the axis it is aligned to
/// </summary>
public decimal Left { get; private set; }
 
/// <summary>
/// Right side of this surface on the axis it is aligned to
/// </summary>
public decimal Right { get; private set; }

We need to populate those values if our orientation changes or if our point changes. Using the string, or enum method we would end up with something like this.

private void TranslatePoint(Point point)
{
	switch(Orientation)
	{
		case Orientation.Back:
			Z = point.Y;
			Left = point.X;
			Top = point.Z;
			Right = Left - Width;
			Bottom = Top - Height;
			break;
		case Orientation.Front:
			Z = point.Y;
			Left = point.X;
			Top = point.Z;
			Right = Left + Width;
			Bottom = Top - Height;
			break;
		case Orientation.Left:
			Z = point.X;
			Left = point.Y;
			Top = point.Z;
			Right = Left + Width;
			Bottom = Top - Height;
			break;
		case Orientation.Right:
			Z = point.X;
			Left = point.Y;
			Top = point.Z;
			Right = Left - Width;
			Bottom = Top - Height;
			break;
		case Orientation.Up:
			Z = point.Z;
			Left = point.X;
			Top = point.Y;
			Right = Left + Width;
			Bottom = Top + Height;
			break;
		case Orientation.Down:
			Z = point.Z;
			Left = point.X;
			Top = point.Y;
			Right = Left + Width;
			Bottom = Top - Height;
			break;		
	}
}

Wow, that’s a lot of bulk. Now there are probably certain things that could be done to trim that method, but it would still be bulky and hard to read. Plus I am sure that I will be running into the same problem in other places. When you see a method like this you know that it is time to look for refactoring options. There must be a way to move the logic out of this method into the Orientation where it belongs.

There is, and it is called the strategy pattern. Using the strategy pattern we can move the logic into an Orientation class. However because we only want a set amount of values we are going to make some modifications to make it more “enum” like.

Let’s create a new class called Orientation. It will be used both to represent the orientation and to translate global points to that orientation or perform operations that pertain to that orientation.

public class Orientation
{
	private readonly Func<Point, Point> _translator;
	private readonly MathOp _increaseX;
	private readonly MathOp _increaseY;
	private readonly MathOp _increaseZ;
	private readonly Func<Orientation> _flipside;
 
	/// <summary>
	/// Creates a new orientation
	/// </summary>
	/// <param name="translator">Method to translate a global point into a local point</param>
	/// <param name="increaseX">Math operation necessary increase X values</param>
	/// <param name="increaseY">Math operation necessary increase X values</param>
	/// <param name="increaseZ">Math operation necessary increase X values</param>
	/// <param name="flipside">The flipside of this orientation</param>
	private Orientation(Func<Point, Point> translator, 
		MathOp increaseX, 
		MathOp increaseY, 
		MathOp increaseZ,
		Func<Orientation> flipside)
	{
		if (translator == null) throw new ArgumentNullException("translator");
		if (increaseX == null) throw new ArgumentNullException("increaseX");
		if (increaseY == null) throw new ArgumentNullException("increaseY");
		if (increaseZ == null) throw new ArgumentNullException("increaseZ");
		if (flipside == null) throw new ArgumentNullException("flipside");
		_translator = translator;
		_increaseX = increaseX;
		_increaseY = increaseY;
		_increaseZ = increaseZ;
		_flipside = flipside;
	}
 
	/// <summary>
	/// The flipside of this orientation
	/// </summary>
	public Orientation FlipSide
	{
		get { return _flipside(); }
	}
 
	/// <summary>
	/// Translates a global point to this orientation
	/// </summary>
	/// <param name="point"></param>
	/// <returns></returns>
	public Point Translate(Point point)
	{
		return _translator(point);
	}
 
	public MathOp IncreaseX
	{
		get { return _increaseX; }
	}
 
	public MathOp IncreaseY
	{
		get { return _increaseY; }
	}
 
	public MathOp IncreaseZ
	{
		get { return _increaseZ; }
	}
}

Notice how the constructor is private so that we can control its instantiation. We are also making use of delegates in the constructor so we can easily create logic in the constructor without having to resort to making a subclass for each different orientation. If you notice that we havn’t defined the MathOp class anywhere, that’s because it’s simply this exact same pattern repeated except for a math operation.

Next we are going to infuse the strategy pattern with enum like functionality through the use of static fields.

public class Orientation
{
	public static Orientation Back = new Orientation(
		p => new Point(p.X, p.Z, p.Y), 
		MathOp.Subtract, 
		MathOp.Subtract, 
		MathOp.Subtract, 
		() => Front);
	public static Orientation Front = new Orientation(
		p => new Point(p.X, p.Z, p.Y), 
		MathOp.Add, 
		MathOp.Subtract, 
		MathOp.Add, 
		() => Back);
	public static Orientation Left = new Orientation(
		p => new Point(p.Y, p.Z, p.X), 
		MathOp.Add, 
		MathOp.Subtract, 
		MathOp.Subtract, 
		() => Right);
	public static Orientation Right = new Orientation(
		p => new Point(p.Y, p.Z, p.X), 
		MathOp.Subtract, 
		MathOp.Subtract, 
		MathOp.Add, 
		() => Left);
	public static Orientation Up = new Orientation(
		p => new Point(p.X, p.Y, p.Z), 
		MathOp.Add, 
		MathOp.Add, 
		MathOp.Add, 
		() => Down);
	public static Orientation Down = new Orientation(
		p => new Point(p.X, p.Y, p.Z), 
		MathOp.Add, 
		MathOp.Subtract, 
		MathOp.Subtract, 
		() => Up);

We have now ended up with an enum-like class that incorporates so much more functionality. Assigning an orientation to a variable is as simple as…

surface.Orientation = Orientation.Up;

Comparison works the same way.

if(Orientation == Orientation.Up)
	//do something

The only thing that we are lacking is the ability to switch on our Orientation class, but with the new functionality we shouldn’t need to. Just look at what our bulky “TranslatePoint” method has turned into.

private void TranslatePoint(Point point)
{
	Point translated = Orientation.Translate(point);
	Z = translated.Z;
	Left = translated.X;
	Top = translated.Y;
	Right = Orientation.IncreaseX.Calculate(Left, Width);
	Bottom = Orientation.IncreaseY.Calculate(Top, Height);
}

By applying an appropriate pattern we have made our code more readable, less bulky and insured that it has a stable growth plan.

Remember when refactoring don’t forget the simple things.

Rusty spikes

July 15th, 2009

NHibernate.Remote was one of my favorite projects.  Please note the word “was”.  The initial concept was exciting and early forays into coding provided positive results, however as with all concepts the devil is in the details.  In the end it was the lack of being able to extend the NetDataContractSerializer that really killed the project.  Not being able to analyze objects as they came over the wire led to a large amount of brittle reflection.  This led to problems synchronizing objects bidirectionally.  NHibernate.Remote was in reality a leaky abstraction on top of another not quite as leaky abstraction.  As I don’t have infinite time at work I have shifted focus to other ways of getting data out to clients.  I will probably leave the source online in case someone else wants to check out the concept but as far as I am concerned the project is dead.

Have you ever wanted to code something that wasn’t exactly best practices, but would make for a neat concept?  I know that I have.  I seem to be constantly pushing against the edges of best practices hoping to find the next “Dependency Injection” concept that makes everyones lives just a little bit easier.  While my current spike project is not of that caliber, it is pushing the boundaries in a weird sort of way.  So instead of just laughing at myself, I thought that I’d open up access to it and let you guys laugh at me as well.  So what is this spike that I’m talking about?  This is a database driver for NHibernate that works accross the network, or across WCF specifically.

The concept is very simple.  NHibernate, at its very base relies on an IDbConnection to go out and fetch the data from the database.  Normally this connects rather directly to the db in a low latency connection.  Being an intensely curious programmer I wondered if it would be possible to route this raw db connection over top of a WCF connection.  The cool things is that it works, although introducing more latency than is optimal of course.  It works by opening up the actual db connection on the server and then reading the data associated with a command into a dataset which is transmitted accross WCF.  On the client side a datareader is created from the dataset thus allowing the client to read the database and perform other operations.

How reliable is this concept.  Well I haven’t had the chance to use it in any production apps.  (Not sure that I’d want to) but it does pass all of NHibernate 2.0.1GA’s test save one that deals with schemas. Let’s say that this piques your interest a little bit and you would like to try it out.  I’m not going to be releasing binaries and a big how to, but here’s the SVN url and you can give it a try for yourselves.

http://slagd.com/svn/NHibernate.WCFDriver/Trunk

There is a project in the source called “TestServer” which is simply a console project that will host the server.  The server is the only part that has a custom configuration element in the app.config.  Both the server and the client rely on standard WCF configuration to create a connection.  You can find examples of this configuration in both the app.config of the NHibernate.Test-2.0 project and the app.config of the TestServer project.  It’s also important to note that when you are using the WCFDbDriver on the client, the NHibernate connection string setting is ignored.  You can put whatever you want there but you will have to give it a value or NHibernate will complain.  Actual client-server connection information is located in the WCF configuration elements.

This is definitely not in keeping with best-practices but who says you can’t have fun with programming sometimes.

It’s been a while since I’ve done anything with the GenericMessaging project which is too bad since I consider it to be the most useful of the projects that I have been working on lately. Last week I ran into a painful brick wall regarding the security system I’ve been working on, so I decided to do some reworking on GenericMessaging while my brain sorts itself out and develops new neural pathways to replace the fried ones. There have been several comments on the forum about GenericMessaging, mostly regarding its dependence on PostSharp. While I think that PostSharp is great, it’s probably not something that needs to be intimately linked with the GenericMessaging layer. I’ve abstracted PostSharp support out into its own separate library. I’ve also added a new library that contains a class that will dynamically create a proxy for you using the Castle Dynamic Proxy Generator. This should give users more flexibility. I’ve uploaded these changes to the svn repositories but I won’t update the binaries quite yet as there is some more refactoring that needs to take place. So go grab the latest version from svn and give it a whirl.

Oh and a big thanks to those people who have posted on the forum with suggestions.

I have had the very bad fortune to be working with some very old database structures at the moment. Upgrading those structures is not possible, however there are times when it would be nice to map against them.  Recently I have been banging my head against a scenario where an entity may exist in one database at “X” location and in an entirely different database at “Y” location.  This works fine as long as this database is the only one that you are connecting and mapping too.  You can simply change the database name in the connection string and life is good.  However there are situations – mine in particular – where you have to map relations between your entities across databases, ouch.  In this situation a person needs to prefix the names of their table mappings with the database name as well.  This seems to work at least until you need to change the name of the database that you are connecting to.

So is this situation even possible with NHiberante(2.0.1GA)?  It turns out that yes it is, but first you have to get NHibernate to perform some gymnastics.  This seems to work fine for me but that is not a guarantee that your experience will be similar.  There is an additional caveat as well, that is that this only works for specifying the db names before you start an NH session factory.  Once you start the session the names are finalized and this method will not work to change them.   This method actually works by putting placholder values in your mapping files instead of actually database names.  What we need to do then is to strip out the placeholders and replace them with real db names when the NH session factory is being created.  We do this by looking through the configuration file that is generated by NH and replacing our values before the session factory is created.  In theory this would also work with table names as well as db names, but that is not something that I have tested with.

Lets start out with a very simple mapping.  Remember that we are not exactly sure of the database name that this will be residing in.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MemX.Data.Entities" namespace="MemX.Data.Entities.RMS">
  <class name="Item" table="$RmsDB.dbo.Item" lazy="false">
    <id name="ID" column="ID" type="Int32">
      <generator class="native" />
    </id>
    <property name="Description" column="Description"/>
  </class>
</hibernate-mapping>

What you can see, when you look at the attribute containing the table name, is that we’ve put a placeholder there instead of the actual table name.

Now that we have a placeholder there instead of a database name we need a class that can help us to easily modify NH’s configuration.  Lets start out with a dictionary to contain our placholder to value mappings.

/// <summary>
/// Helps to map table symbols in the NH mappings to actual table/database names
/// </summary>
public class NHTableMappings
{
    /// <summary>
    /// Maps from the placeholder string to the real table/database name
    /// </summary>
    public IDictionary<string, string> Mappings { get; protected set; }
 
    /// <summary>
    /// Creates a set of table/database mappings
    /// </summary>
    public NHTableMappings()
    {
        Mappings = new Dictionary<string, string>();
    }
}

And to push those mappings into the NH configuration we would need to do something like this inside our NHTableMappings class.

/// <summary>
/// maps table symbols to actual table/database names
/// </summary>
/// <param name="configuration"></param>
/// <returns></returns>
public void MapTables(Configuration configuration)
{
    if (configuration == null) throw new ArgumentNullException("configuration");
 
    //get the tables using reflection
    FieldInfo tablesField = typeof (Configuration).GetField("tables", BindingFlags.Instance | BindingFlags.NonPublic);
    IDictionary<string, Table> tables = tablesField.GetValue(configuration) as IDictionary<string, Table>;
 
    if(tables == null)
        throw new InvalidOperationException("Couldn't retrieve table information from NHibernate configuration.");
 
    //look through NHTableMappings
    foreach (KeyValuePair<string, string> key_tableName in Mappings)
    {
        string tableKey = key_tableName.Key;
        string tableName = key_tableName.Value;
 
        IEnumerable<Table> tablesToChange = tables.Where(p => p.Key.Contains(tableKey)).Select(p => p.Value);
        foreach (Table table in tablesToChange)
        {
            table.Name = table.Name.Replace(tableKey, tableName);
        }
    }
}

It’s pretty simple really.  We use reflection to get the tables field from the NH configuration because it is not public.  We scan through the table names looking for keys that are in our mapping and we do the old switcheroo.  Once this has been done we can start up a session factory and our entity will now be mapped against the correct database.

//Build the NH configuration
Configuration nhConfiguration = new Configuration().Configure();
 
//add your mappings
NHTableMappings tableMappings = new NHTableMappings();
tableMappings.Mappings.Add("$RmsDB", "MyRmsDatabaseName");
 
//modify the NH configuration
tableMappings.MapTables(nhConfiguration);
 
//build your session factory
ISessionFactory sessionFactory = nhConfiguration.BuildSessionFactory();

I hope this helps someone who is trying solve the same problem that I was.

I’ve included some complete classes here in case you just want to copy and paste (plus some includes).

The main class.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Xml;
using log4net;
using NHibernate.Mapping;
using Configuration=NHibernate.Cfg.Configuration;
 
namespace MemX.Data
{
    /// <summary>
    /// Helps to map table symbols in the NH mappings to actual table/database names
    /// </summary>
    public class NHTableMappings
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(NHTableMappings));
        public static readonly string ConfigSection = "nh-table-mappings";
        public static readonly string ConfigKey = "mapping";
        public static readonly string KeyAttribute = "table-key";
        public static readonly string NameAttribute = "table-name";
 
        /// <summary>
        /// Maps from the placeholder string to the real table/database name
        /// </summary>
        public IDictionary<string, string> Mappings { get; protected set; }
 
        /// <summary>
        /// Creates a set of table/database mappings
        /// </summary>
        public NHTableMappings()
        {
            Mappings = new Dictionary<string, string>();
        }
 
        /// <summary>
        /// Adds a mapping from a key to an actual name
        /// <para>Can be used for table names or DB names</para>
        /// </summary>
        /// <param name="tableKey"></param>
        /// <param name="tableName"></param>
        /// <param name="overwrite">Do we want to overwrite an existing value</param>
        public void AddMapping(string tableKey, string tableName, bool overwrite)
        {
            if (String.IsNullOrEmpty(tableKey)) throw new ArgumentNullException("tableKey");
            if (String.IsNullOrEmpty(tableName)) throw new ArgumentNullException("tableName");
 
            if (!Mappings.ContainsKey(tableKey))
                Mappings.Add(tableKey, tableName);
            else if(overwrite)
                Mappings[tableKey] = tableName;
        }
 
        /// <summary>
        /// maps table symbols to actual table/database names
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public void MapTables(Configuration configuration)
        {
            if (configuration == null) throw new ArgumentNullException("configuration");
 
            //get the tables using reflection
            FieldInfo tablesField = typeof (Configuration).GetField("tables", BindingFlags.Instance | BindingFlags.NonPublic);
            IDictionary<string, Table> tables = tablesField.GetValue(configuration) as IDictionary<string, Table>;
 
            if(tables == null)
                throw new InvalidOperationException("Couldn't retrieve table information from NHibernate configuration.");
 
            //look through NHTableMappings
            foreach (KeyValuePair<string, string> key_tableName in Mappings)
            {
                string tableKey = key_tableName.Key;
                string tableName = key_tableName.Value;
 
                IEnumerable<Table> tablesToChange = tables.Where(p => p.Key.Contains(tableKey)).Select(p => p.Value);
                foreach (Table table in tablesToChange)
                {
                    table.Name = table.Name.Replace(tableKey, tableName);
                }
            }
        }
 
        /// <summary>
        /// Reads the configuration from xml
        /// </summary>
        /// <param name="section"></param>
        /// <param name="overwrite">Do we want to overwrite existing configuration</param>
        public void ReadFromXml(XmlNode section, bool overwrite)
        {
            log.Debug("Reading table mappings from xml");
            if (section == null) throw new ArgumentNullException("section");
 
            if(section.LocalName != ConfigSection)
                throw new ConfigurationErrorsException(String.Format("Invalid section {0} in NHTableMappings configuration", section.LocalName));
 
            foreach (XmlNode node in section.ChildNodes)
            {
                if(node.LocalName != ConfigKey)
                    throw new ConfigurationErrorsException(String.Format("Invalid section {0} in NHTableMappings configuration", node.LocalName));
 
                string tableKey = node.Attributes[KeyAttribute].Value;
                string tableName = node.Attributes[NameAttribute].Value;
 
                AddMapping(tableKey, tableName, overwrite);
            }
        }
 
        /// <summary>
        /// Creates the mappings from an xml section
        /// </summary>
        /// <param name="section"></param>
        /// <param name="overwrite">Do we want to overwrite existing configuration</param>
        /// <returns></returns>
        public static NHTableMappings CreateFromXml(XmlNode section, bool overwrite)
        {
            NHTableMappings tableMappings = new NHTableMappings();
            tableMappings.ReadFromXml(section, overwrite);
 
            return tableMappings;
        }
 
        /// <summary>
        /// Creates the mappings from a config section
        /// </summary>
        /// <returns></returns>
        public static NHTableMappings CreateFromConfig()
        {
            NHTableMappings tableMappings = ConfigurationManager.GetSection(ConfigSection) as NHTableMappings;
            if(tableMappings == null)
                throw new ConfigurationErrorsException("Could not load table mappings confugration from app/web.config");
 
            return tableMappings;
        }
 
        /// <summary>
        /// Creates the mappings from a config section if it exists, or defaults to an empty mappings file
        /// </summary>
        /// <returns></returns>
        public static NHTableMappings CreateFromConfigOrDefault()
        {
            NHTableMappings mappings;
 
            try
            {
                mappings = CreateFromConfig();
            }
            catch (ConfigurationErrorsException)
            {
                mappings = new NHTableMappings();
            }
 
            return mappings;
        }
    }
}

A configuration section handler.

using System.Configuration;
using System.Xml;
 
namespace MemX.Data
{
    public class NHTableMappingsConfigurationSectionHandler : IConfigurationSectionHandler
    {
        #region IConfigurationSectionHandler Members
 
        public object Create(object parent, object configContext, XmlNode section)
        {
            return NHTableMappings.CreateFromXml(section, true);
        }
 
        #endregion
    }
}

The usage looks something like this.

<configuration>
  <configSections>
    <section name="nh-table-mappings" type="MemX.Data.NHTableMappingsConfigurationSectionHandler, MemX.Data"/>
  </configSections>
  <nh-table-mappings>
    <mapping table-key="$RmsDB" table-name="RMSCal3"/>
  </nh-table-mappings>
</configruation>

And even an extension method

    public static class NHTableMappingsExtension
    {
        public static Configuration MapTables(this Configuration configuration)
        {
            NHTableMappings tableMappings = NHTableMappings.CreateFromConfig();
 
            tableMappings.MapTables(configuration);
 
            return configuration;
        }
    }

Using the configuration and the extension it would looking something like this.

            ISessionFactory sessionFactory = new Configuration()
                .Configure()
                .MapTables()
                .BuildSessionFactory();

You could also include some default mappings and include them as a resource along with your mappings and only override when needed as well.

Posted in NHibernate | 1 Comment »