Of Code and Me

Somewhere to write down all the stuff I'm going to forget and then need

Functional programming techniques in C# February 11, 2008

Filed under: C#,F#,Functional programming — Rupert Bates @ 9:10 pm

I’ve been reading quite a lot about functional programming recently, as well as playing around with F#, and I’ve found that it is starting to subtly change the way I write code. Recently I was working on an approach to using Linq to Sql with Asp.Net, and I found myself slightly dissatisfied with the following methods:

public static void Insert(TEntity entity)
{
    Insert(entity, false);
}
public static void Insert(TEntity entity, bool submitChanges)
{
    EntityTable.InsertOnSubmit(entity);
    if (submitChanges)
        DataContext.SubmitChanges();
}

public static void Update(TEntity entity)
{
    Update(entity, false);
}
public static void Update(TEntity entity, bool submitChanges)
{
    TEntity original = GetEntity(entity);
    UpdateOriginalFromChanged(ref original, entity);
    if (submitChanges)
        DataContext.SubmitChanges();
}

public static void Delete(TEntity entity)
{
    Delete(entity, false);
}
public static void Delete(TEntity entity, bool submitChanges)
{
    TEntity delete = GetEntity(entity);
    EntityTable.DeleteOnSubmit(delete);
    if (submitChanges)
        DataContext.SubmitChanges();
}

This is pretty straightforward stuff, we have 3 methods Insert, Update and Delete, each of which takes an entity of type TEntity (they are in a generic class) and an overload for each, which also takes a bool to allow client code to specify whether or not to call SubmitChanges on the DataContext immediately. What I dislike about this code is the repeated if statements in each of the overloads, surely there should be a way to refactor those out? This was when a post I’d been reading on Continuation Passing Style popped into my head and I realised that there is, if we use a more functional approach. What we need to do is to create a function ConditionalSubmit() that takes 3 parameters

  • Our TEntity entity
  • The boolean parameter that tells us whether to submit changes or not.
  • A function which will be one our Insert, Update or Delete operations

ConditionalSubmit() can call the function which was passed in, with the entity and then submit the changes or not, depending on the value of the submitChanges parameter. Here is what it looks like:

protected static void ConditionalSubmit(TEntity entity, bool submitChanges, Action<TEntity> operation)
{
	operation(entity);
	if(submitChanges)
		DataContext.SubmitChanges();
}

Now I need to change my implementation of the Insert, Update and Delete methods as follows (I’ve just shown Update for the sake of brevity):

public static void Update(TEntity entity, bool submitChanges)
{
    ConditionalSubmit(entity, x => Update(x), submitChanges);
}

protected static void Update(TEntity entity)
{
    TEntity original = GetEntity(entity);
    UpdateOriginalFromChanged(ref original, entity);
}

The overload without the bool parameter now becomes the version that does all the work, and the overload with the bool passes this version into the ConditionalSubmit() function, using a lambda, along with the other parameters. I think this is a really elegant solution as it abstracts the submit changes functionality away into another function and allows us to get rid of all that repeated code.

Is this really a better solution though? I’m not sure, I think it’s probably just different. In fact in the final code I went back to the original version, purely because I thought it would be easier to understand for the majority of C# developers, and this is code which will need to be used and maintained by others. Having said that I am sure there will be times when a functional approach really does produce a better solution, so I found it very useful to work this through, to get myself to start thinking about coding in a more functional style.

Advertisements
 

2 Responses to “Functional programming techniques in C#”

  1. yoric Says:

    If you’re interested, in functional programming, this is sometimes referred to as the “hole in the middle” design pattern, or “safe resource access” design pattern. This is one of the reasons why “try…finally…” doesn’t exist in OCaml, as it may easily be implemented as a function.

  2. Rupert Bates Says:

    Thanks yoric, that’s interesting.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s