Extension Cords, Tea Kettle Whistling, and the Contractor’s Wrap for Your Code

A few weekends ago, I found myself standing in my garage, regretting my ambitions of yard work and struggling to unwind the pile of orange spaghetti that was, at one point, a tidily wrapped fifty-foot extension cord.

Then I took a deep breath and reminded myself that things were going to be different this time.

See, the blog Art of Manliness had just run a post on how to wrap your extension cords like a contractor, using a technique that enables you to quickly uncoil whatever length of cord you need, without it ever becoming a tangled mess. The post was mostly pictures, so I managed to get through it. And things did, in fact, turn out differently this time.

cord
[via]

Well. The orange garage-spaghetti department of things, at least.

Cool Story, Bro

So what, you may well ask, does my high-voltage gardening adventure have to do with building software?

Here’s the thing about code: it gets inscrutably balled up just like this all the time. And while I’m sure that you, dear reader, have never yourself been responsible for such a mess, I have borne witness as this recurring nightmare slowly unfolded on many an unsuspecting software venture.

In the beginning of the project, there’s the familiar big talk about how This Time, we’re going to keep things organized. This Time, we’re going to write REUSABLE code. This Time, we’re going to work harder and do it right. Things are going to be different This Time.

reusable

So, development hops along at a decent pace at first–like winding the first few coils in that orange extension cord. But soon, it gets harder and harder to actually reuse the REUSABLE components. Changes take longer to implement, you swear that you can hear the faint whistle of a tea kettle that is perpetually beginning to boil, and your source has seemingly contorted itself into shapes that would make a sailor cry. And when the new devs (that management has hurled at the problem) climb aboard and try to unravel a piece of the code for what they’re working on, those kinks just get twisted tighter. Soon, everyone involved sinks into their chair with the same question burning in their brain.

How did this happen to our code again?

We get it, Fazzaro. Code bad, team sad. But what exactly can a young person like myself do to invoke the beneficence of the programming gods that they may no longer smite us in this way?

Glad you asked. Let’s get specific.

In my travels, the most common cause of egregious code fluster in the modern business app is a poorly scoped Entity Framework DbContext1. What might one of those look like? Stop me if you’ve heard this one: I’ve updated these entities, added two new ones over here, deleted that ugly one, and our REUSABLE code just called SaveChanges three times in the course of doing its business. So, I’m going to jiggle the handle and call it one more time over here for this case. You know, just to be sure.

Sure, the EF implements the Unit of Work and Repository patterns right out of the box. But this only helps if we’re using them correctly–which really comes down to understanding where the context belongs. Should a new context be created to persist each change to an entity? Should we create a new one for every method that alters data? Or should we just keep a global singleton context instance, and call SaveChanges on it when it feels right?

That’d be no, no, and hand over your keys, dude, respectively. Paths to the spaghetti side, those are. Instead, to keep the unit of work thing straight, I just keep two simple rules in mind:

  1. The unit of work does not go inside the reusable code, the reusable code goes inside of the unit of work.
  2. As soon as you create a new context or call SaveChanges, you are no longer writing the reusable code.

Some of your code will never be reusable, and that’s okay; that’s where the context goes. As for the rest of your code, here’s a way to make it truly and sustainably reusable.

I’m going to illustrate this by generally being abusive to a particularly troubling snippet of sample code from the Wingtip Toys tutorial on MSDN. In the the application that the tutorial guides you through building, the ShoppingCartActions class houses the domain logic around adding, updating, and removing items from a shopping cart. I’ve abbreviated the class here to just show the salient bits:

public class ShoppingCartActions {
    public string ShoppingCartId { get; set; }

    private ProductContext _db = new ProductContext();
 
    public const string CartSessionKey = "CartId";

    public void AddToCart(int id) {
        // Retrieve the product from the database. 
        ShoppingCartId = GetCartId();

        var cartItem = _db.ShoppingCartItems.SingleOrDefault(
            c => c.CartId == ShoppingCartId
            && c.ProductId == id);
        if (cartItem == null) {
        // Create a new cart item if no cart item exists. 
            cartItem = new CartItem {
                ItemId = Guid.NewGuid().ToString(),
                ProductId = id,
                CartId = ShoppingCartId,
                Product = _db.Products.SingleOrDefault(
                    p => p.ProductID == id),
                Quantity = 1,
                DateCreated = DateTime.Now
            };

            _db.ShoppingCartItems.Add(cartItem);
        } else {
            // If the item does exist in the cart, 
            // then add one to the quantity. 
            cartItem.Quantity++;
        }
        _db.SaveChanges();
    }

    public void UpdateShoppingCartDatabase(String cartId, ShoppingCartUpdates[] CartItemUpdates) {
        using (var db = new ProductContext()) {
            int CartItemCount = CartItemUpdates.Count();
            List<CartItem> myCart = GetCartItems();
            foreach (var cartItem in myCart) {
                // Iterate through all rows within shopping cart list 
                for (int i = 0; i < CartItemCount; i++) {
                    if (cartItem.Product.ProductID == CartItemUpdates[i].ProductId) {
                        if (CartItemUpdates[i].PurchaseQuantity < 1 || CartItemUpdates[i].RemoveItem == true) {
                            RemoveItem(cartId, cartItem.ProductId);
                        } else {
                            UpdateItem(cartId, cartItem.ProductId, CartItemUpdates[i].PurchaseQuantity);
                        }
                    }
                }
            }
        }
    }

    public void RemoveItem(string removeCartID, int removeProductID) {
        using (var db = new ProductContext()) {
            var myItem = (from c in db.ShoppingCartItems where c.CartId == removeCartID && c.Product.ProductID == removeProductID select c).FirstOrDefault();
            if (myItem != null) {
                db.ShoppingCartItems.Remove(myItem);
                db.SaveChanges();
            }
        }
    }

    public void UpdateItem(string updateCartID, int updateProductID, int quantity) {
        using (var db = new ProductContext()) {
            var myItem = (from c in db.ShoppingCartItems where c.CartId == updateCartID && c.Product.ProductID == updateProductID select c).FirstOrDefault();
            if (myItem != null) {
                myItem.Quantity = quantity;
                db.SaveChanges();
            }
        }
    }
}

And here are a few lines from a nearby code-behind class that consumes ShoppingCartActions:

ShoppingCartActions usersShoppingCart = new ShoppingCartActions();
usersShoppingCart.AddToCart(Convert.ToInt16(rawId));

Oh, it looks innocent enough, all right. Until you notice that not only does each instance of ShoppingCartActions get its very own private ProductContext, but that when it’s time to call RemoveItem, UpdateItem, or (Robert Cecil Martin help you) UpdateShoppingCartDatabase, we’re whipping off new context instances like they are going out of style. Gross.

Why is that gross? Well, suppose that we had another page in our application that needed to perform similar actions on a shopping cart, in a slightly alternate combination:

ShoppingCartActions usersShoppingCart = new ShoppingCartActions();
usersShoppingCart.AddToCart(Convert.ToInt16(rawId1));
usersShoppingCart.AddToCart(Convert.ToInt16(rawId2));

var changes = GetShoppingCartChanges();
usersShoppingCart.UpdateShoppingCartDatabase(cartId, changes);

I count no fewer than four new ProductContext instances created here–and easily many more, depending on how many changes were in that list we passed in to UpdateShoppingCartDatabase. And if we needed this particular set of operations to be transactional, so that if one failed, no changes were sent to the database at all? Forget it. Yes, gross.

And yet, with a simple, subtle refactoring, we can turn this heinous double sheetbend into a nimble little slipknot. All we have to do is get it to let go of control of the context:

public class ShoppingCartActions {
    public string ShoppingCartId { get; set; }

    private ProductContext _db;

    public ShoppingCartActions(ProductContext db) {
        _db = db;
    }

    public void AddToCart(int id) {
        // Retrieve the product from the database. 
        ShoppingCartId = GetCartId();

        var cartItem = _db.ShoppingCartItems.SingleOrDefault(
            c => c.CartId == ShoppingCartId
            && c.ProductId == id);
        if (cartItem == null) {
            // Create a new cart item if no cart item exists. 
            cartItem = new CartItem {
                ItemId = Guid.NewGuid().ToString(),
                ProductId = id,
                CartId = ShoppingCartId,
                Product = _db.Products.SingleOrDefault(
                p => p.ProductID == id),
                Quantity = 1,
                DateCreated = DateTime.Now
            };

            _db.ShoppingCartItems.Add(cartItem);
        } else {
            // If the item does exist in the cart, 
            // then add one to the quantity. 
            cartItem.Quantity++;
        }
    }

    public void UpdateShoppingCartDatabase(String cartId, ShoppingCartUpdates[] CartItemUpdates) {
        int CartItemCount = CartItemUpdates.Count();
        List<CartItem> myCart = GetCartItems();
        foreach (var cartItem in myCart) {
            // Iterate through all rows within shopping cart list 
            for (int i = 0; i < CartItemCount; i++) {
                if (cartItem.Product.ProductID == CartItemUpdates[i].ProductId) {
                    if (CartItemUpdates[i].PurchaseQuantity < 1 || CartItemUpdates[i].RemoveItem == true) {
                        RemoveItem(cartId, cartItem.ProductId);
                    } else {
                        UpdateItem(cartId, cartItem.ProductId, CartItemUpdates[i].PurchaseQuantity);
                    }
                }
            }
        }
    }

    public void RemoveItem(string removeCartID, int removeProductID) {
        var myItem = (from c in _db.ShoppingCartItems
            where c.CartId == removeCartID && c.Product.ProductID == removeProductID
            select c).FirstOrDefault();
        if (myItem != null)
            _db.ShoppingCartItems.Remove(myItem);
    }

    public void UpdateItem(string updateCartID, int updateProductID, int quantity) {
        var myItem = (from c in _db.ShoppingCartItems
            where c.CartId == updateCartID && c.Product.ProductID == updateProductID
            select c).FirstOrDefault();
        if (myItem != null)
            myItem.Quantity = quantity;
    }
}

You almost can’t see the difference–but note the complete lack of context instantiation, and that nowhere in there do we even consider calling SaveChanges. This is our rule number two in action; ShoppingCartActions just isn’t in the business of owning the ProductContext anymore.

Here’s how we can leverage this class in our code-behind now:

using (var db = new ProductContext()) {

    ShoppingCartActions usersShoppingCart = new ShoppingCartActions(db);
    usersShoppingCart.AddToCart(Convert.ToInt16(rawId1));
    usersShoppingCart.AddToCart(Convert.ToInt16(rawId2));
    var changes = GetShoppingCartChanges();
    usersShoppingCart.UpdateShoppingCartDatabase(cartId, changes);

    db.SaveChanges(); 
}

And that illustrates rule number one. We instantiate one ProductContext, we do our business with it, and we send a single set of changes to the database. Not only can the new ShoppingCartActions be applied to many different situations throughout the app, but it will scale like a mother to boot.

Dependency Injection is the Contractor’s Wrap for Code

By now, the sharper nerds in my readership will be calling out that I have simply invoked the Dependency Injection technique here, and they would be correct. We took a component that the logic was dependent upon and made sure that it came from somewhere else, outside of the logic’s implementation. Dependencies like context instances are really just input for the logic to use in its calculations. What’s really going to knock your socks off later on is that this pattern of threading dependencies through class constructors applies to any number of types that have nothing at all to do with the Entity Framework, or even data storage, for that matter. HttpContext, FileStream, SPWeb, RouteCollection, you name it. They are all just input for our code to operate upon.

With just a minor tweak to the way we weave our classes together, our source can become tangle-free and flexible, and the next developer to lay hands on our app doesn’t have to worry about it curling up into an untenable heap of sad. It’s a shot in the arm for the sustainability and success of the app, and for the happiness of the team. And things are totally going to be different this time.

Well. The weeping-sailor heinous-code-fluster department of things, at least.


  1. Okay, so maybe you’re not using the Entity Framework (or its newer DbContext API), but don’t check out on me just yet–you might well be rocking a similarly steaming pile with some other ORM/unit-of-work-type implementation. Keep playing along at home, mentally adjusting my terminology to whatever busted situation you’re holding onto over there. I’ll make it worth your while.
Advertisements

Get Your LEGOs Right With Fluent Query Extensions

Get Your LEGOs Right With Fluent Query Extensions

 
If I was going to build a little plastic house out of Legos, I would probably start by finding a nice, flat baseplate piece. A green one, in a solid school district. My next step would not be, however, to start building the walls out of horse blocks.

Having the right Legos on your table (as the belabored metaphor goes) can go a long way when you’re trying to build software. Even with modern tools and frameworks, there is an entropy we battle in this process. The right pieces don’t just happen, especially if you’re sauntering through the designer and stuffing VB into whatever event handler Studio is holding open for you at the moment. I’m just guessing about the VB.

So here’s a pattern that I picked up that will make your code at once more readable, reusable, and maintainable.

Ladies.

LINQ to Awkward

Let’s say we have some business code that looks like this. Because you maybe probably do.

using (var db = new AdventureWorksEntities()) {
 
    // get orders from the last week
    // that were made online
    // and that have a tax amount greater than half of the subtotal
    var orders = from p in db.SalesOrderHeaders
                 where p.OrderDate >= DateTime.Today.AddDays(-7)
                    && p.OrderDate <= DateTime.Today
                    && p.OnlineOrderFlag
                    && p.TaxAmt > (p.SubTotal / 2)
                 select p;
 
    foreach (var order in orders) {
 
        // if they're related to me,
        if (order.Contact.LastName == "Fazzaro") {
 
            // give them a fifty percent discount
            order.SubTotal *= (decimal)0.5;
        }
    }
 
    db.SaveChanges();
}

Not too shabby. Most developers would have no issue taking this snippet under their wing and showing it a nice afternoon in a text editor.

But look closer. Those comments unveil four or five distinct aspects of SalesOrderHeader data that are being tested before any action is taken, all crammed together into one awkwardly equine block of functionality. It’s terribly specific in nature, and probably not really reusable at all.

Don’t see it yet? Watch this.

You Have FAIL

Ding. There’s a new message in your Inbox. It’s the oh-by-the-way requirement that we also need to do something just like this, but with all orders (not just online orders) and also only orders from two weeks ago oh and also not made on a Thursday because Thursdays are when Dianne has her meeting with the supply chain something something can you speak to when we can expect to maybe talk about having that this afternoon?

So, of course, it’s copy-and-paste inheritance all the way to the check-in button, and now you just want to go wash, and maybe look at some Ruby code. Which, I hear, is lovely this time of year. And so are the mangoes.

Meanwhile, your not-really-reusable-at-all horse block of code is now two nearly-identical not-really-reusable-at-all horse blocks of code:

public void DoitOneWayForOnlineOrdersFromLastWeek() {
    using (var db = new AdventureWorksEntities()) {
        // get orders from the last week
        // that were made online
        // and that have a tax amount greater than half of the subtotal
        var orders = from p in db.SalesOrderHeaders
                        where p.OrderDate >= DateTime.Today.AddDays(-7)
                        && p.OrderDate <= DateTime.Today
                        && p.OnlineOrderFlag
                        && p.TaxAmt > (p.SubTotal / 2)
                        select p;
        foreach (var order in orders) {
            // if they're related to me,
            if (order.Contact.LastName == "Fazzaro") {
                // give them a fifty percent discount
                order.SubTotal *= (decimal)0.5;
            }
        }
 
        db.SaveChanges();
    }
}
 
public void DoitAnotherWayForAnyOrderFromTheWeekBeforeLastButNotOnThursdaysBecauseDianneHasThatThingYouKnow() {
    using (var db = new AdventureWorksEntities()) {
        // get orders from two weeks ago
        // not made on a Thursday 
        // and that have a tax amount greater than half of the subtotal
        var orders = from p in db.SalesOrderHeaders
                        where p.OrderDate >= DateTime.Today.AddDays(-14)
                        && p.OrderDate <= DateTime.Today.AddDays(-7)
                        && p.OrderDate.DayOfWeek != DayOfWeek.Thursday
                        && p.TaxAmt > (p.SubTotal / 2)
                        select p;
 
        foreach (var order in orders) {
            // if they're related to me,
            if (order.Contact.LastName == "Fazzaro") {
                // give them a fifty percent discount
                order.SubTotal *= (decimal)0.5;
            }
        }
 
        db.SaveChanges();
    }
}

You can see how this gets out of hand quickly. We can do better.

.OkayLetsDoBetterThenAndGetOnWithItBecause(this Article isAlreadyHalfwayOver)

How can we do better? By annotating our data types to expose discrete parts of queries as methods. Duh.

In reviewing our smelly old code, we find that the following five conditions of Orders are tested:

  • Whether the order date is within a given range
  • Whether the order was made online
  • Whether the order has a tax amount greater than half of the order’s subtotal
  • Whether the order was made on a certain day of the week
  • Whether the order was placed by somebody perhaps related to your humble narrator

Wouldn’t it be loverly if we could just ask a steaming pile of SalesOrderHeaders for these things, one at a time, in plain English? Picture it. Seriously, see it first—great APIs start by envisioning the consuming code up front:

var myOrders = db.SalesOrderHeaders
                .From(DateTime.Today.AddDays(-7))
                .To(DateTime.Today)
                .FromOnline()
                .ThatAreHighlyTaxed()
                .ThatWereMadeOnA(DayOfWeek.Thursday)
                .OrderedByARelative();

What’s killer about what we’re about to pull off here is that we can make this happen without ever sullying our data access code. We can keep the logic in a totally separate layer. This is made possible by the modern .NET miracle of Extension Methods, a feature introduced in .NET 3.0, largely to make LINQ possible at all. And in the same way NASA indirectly gave us a really pretty nice pen because Neil and Buzz and pals needed to scratch chickens whilst being floaty and disoriented, the benefits of the necessity extend beyond the mother of their invention. See what I did there? Extend. Moving on.

Where were we? Right. Adding a file in our logic layer that defines a set of extension methods to (in this case) IQueryable<SalesOrderHeader>:

public static class SalesOrderHeaderQueryExtensionsYo
{
    public static IQueryable<SalesOrderHeader> From(this IQueryable<SalesOrderHeader> orders, DateTime from)
    {
        return orders.Where(p => p.OrderDate >= from);
    }

    public static IQueryable<SalesOrderHeader> To(this IQueryable<SalesOrderHeader> orders, DateTime to)
    {
        return orders.Where(p => p.OrderDate <= to);
    }

    public static IQueryable<SalesOrderHeader> FromOnline(this IQueryable<SalesOrderHeader> orders)
    {
        return orders.Where(p => p.OnlineOrderFlag);
    }

    public static IQueryable<SalesOrderHeader> ThatAreHighlyTaxed(this IQueryable<SalesOrderHeader> orders)
    {
        return orders.Where(p => p.TaxAmt > (p.SubTotal / 2));
    }

    public static IQueryable<SalesOrderHeader> ThatWerePlacedOnA(this IQueryable<SalesOrderHeader> orders, DayOfWeek dow)
    {
        return orders.Where(p => p.OrderDate.DayOfWeek == dow);
    }

    public static IQueryable<SalesOrderHeader> OrderedByARelative(this IQueryable<SalesOrderHeader> orders)
    {
        return orders.Where(p => p.Contact.LastName == "Fazzaro");
    }
}

Each of these extension methods alters the given IQueryable<SalesOrderHeader> by a single condition and returns it. This lets us stack them together helter-skelter pell-mell all day long. By virtue of the IQueryable bit, the full query only actually executes when you access the results (say, in a foreach loop) so there is no performance drag incurred by building our LINQ piecemeal. It’s as if we were still writing one solid query, like before—only now we’re writing it by snapping bits together in whatever combination tickles our toes.

Sort of like building a small plastic house with the right Legos.

So, using this new fluent API, a full re-creation of the original consuming code from above would look something like

using (var db = new AdventureWorksEntities())   // for online orders, etc.
{
    db.SalesOrderHeaders
        .From(DateTime.Today.AddDays(-7))
        .To(DateTime.Today)
        .FromOnline()
        .ThatAreHighlyTaxed()
        .OrderedByARelative()
        .ToList()
        .ForEach(p => {
            p.SubTotal *= (decimal)0.5;
        });
    db.SaveChanges();
}

// elsewhere...

using (var db = new AdventureWorksEntities())   // not thursdays, etc.
{
    db.SalesOrderHeaders
        .From(DateTime.Today.AddDays(-14))
        .To(DateTime.Today.AddDays(-7))
        .Except(db.SalesOrderHeaders.ThatWerePlacedOnA(DayOfWeek.Thursday))
        .ThatAreHighlyTaxed()
        .OrderedByARelative()
        .ToList()
        .ForEach(p => {
            p.SubTotal *= (decimal)0.5;
        });

    db.SaveChanges();
}

And if the definition of that somewhat-contrived ‘highly-taxed’ condition needed to change, we wouldn’t spend an anxiety-stricken morning hoping to find it in everywhere the code, with all its subtle variations, to get it updated. We could just waltz on into that beautiful DRY extension method, and tweak it once.

public static IQueryable<SalesOrderHeader> ThatAreHighlyTaxed(this IQueryable<SalesOrderHeader> orders)
{
    // Fred in finance says this should be 1/3, not 1/2. 
    // Also: totally waltzing right now.
    return orders.Where(p => p.TaxAmt > (p.SubTotal / 3));    
}

And if eventually the logic is altered so much that the method’s name no longer makes sense? We’ll just change the name, and take Visual Studio up on it when we are offered the auto-renaming Smart Tag. Boom.

Now imagine the rest of our code behaving itself like this and being all composable and readable. Say, while loading up a grid control with Monday orders within a date range?

var db = new AdventureWorksEntities();
mondayOrdersGridView.DataSource = db.SalesOrderHeaders.From(fromDate).To(toDate).ThatWerePlacedOnA(DayOfWeek.Monday);
mondayOrdersGridView.DataBind();

Go Forth And Extend

More so than its debatably breathtaking user interface, or its over-clever ORM plumbing, your app’s domain logic is what really gives it any value at all. Building and maintaining that logic code should be more of a flowy, compositional experience, and not so much of a making minimum payments on your technical debt sort of thing that you do to kill time between weekends.

It’s also worth noting that a writability and readability gain with a zero performance hit is a rare thing in our line of work, so you should probably quit making those two horse blocks kiss and get on that.