Thursday, 8 October 2009

On Duct Tape Programmers

To: Duct tape programmers

Enjoy, your skin-of-your teeth deliveries, your fingers-crossed deployments, your days lost fire fighting the same issues over and over again. Have fun, wading through incomprehensible spaghetti code, and cut 'n' pasting your "one off" solutions all the shop. Smile sweetly as you work late into the night figuring out the latest screw up.

By all means, cling onto you outdated methods like its still 1988. But please, allow me to work the way I want to work. And, do me a favour, stay outta my codebase.

Wednesday, 7 October 2009

Mind The Gap

Agile, in whatever form, has a set of core practices - iterative development, unit testing, continuous integration, etc. You can, by all means, choose not to include one or more of these core practices; but you better make damn sure you fill the gap with something else or you're headed for big trouble.

For instance, one core practice is the creation of acceptance tests for each story (use case) at the same time, or before, the story is being worked on. These acceptance tests are often created by test professionals who form part of the team. If you don't do this but instead see testing as seperate to development, then you need to do something to plug the knowledge gap. The testers are not going to know what to test. How can they? They're not involved in planning or daily stand ups. The usual response then is that "Agile doesn't work for testing because it is document-lite." Wrong, agile is document-lite because everyone is involved in the development process. Take that away and you have a gap. A gap you must fill. In this case by writing up your stories in detail for the testers to test against.

You see, the agile core practices work together, so that the whole is greater than the sum of the parts. Take one of the parts away and you may very well find the whole is broken. At this point you may decide agile doesn't work. Not true, you broke it!

Thursday, 17 September 2009

Waiting for Visual Studio

I find this funny and ironic......

Tuesday, 14 July 2009

Collapsing foreach Loops using LINQ

Much of the business logic we have traditionally written has been buried in a heap of nested foreach loops and if statements. All this additional cermoney obfiscates the meaning of the code making finding what a method does more difficult.

One the key strength of LINQ, as I see it, is in its ability to put your application's business logic center stage. By seperating your query from your command within each method, the clarity of those methods is greatly increased.

Time for a example I think. Take the following example of traditional business logic:

public void FulfillOrders()
foreach(Customer customers in Customers)
foreach(Order order in customer.Orders)
foreach(OrderLine line in order.Lines)
customer.Ship(order, line);
customer.BackOrder(order, line);

OK, I admit, not a great bit of DDD - but I'll live with that; its not the point of this blog. However this code, is fairly difficult to read and its going to quickly become unmaintainable as more business logic is heaped upon it. LINQ allows us to collapse down those foreach loops and if statements into a query thereby achieving command query seperation within the method.

public void FulfillOrders()
var allOrders = from customer in Customers
from order in cutomer.Orders
from line in order.Lines
where customer.CanPlaceOrders()
&& !order.IsShipped
select new {Customer = customer,
Order = order,
Line = line};

var shippable = from item in allOrders
where item.IsInStock()
select item;

var outOfStock = from item in allOrders
where !item.IsInStock()
select item;

foreach(var item in shippable)
item.Customer.Ship(item.Order, item.Line);

foreach(var item in outOfStock)
item.Customer.BackOrder(item.Order, item.Line);

Note, how in the allOrders query I am stacking up the "from" statements with no joins. This tells LINQ to do a cross join. But wouldn't this mean that every customer is joined to every order and every order line regardless of whether the customer owned the orders. Well, no; in the object model the Orders belong to the Customer and the OrderLines belong to the Orders. In this situation LINQ is smart enough to figure out which constraints should apply.

In this new "LINQed-up" version we have clearly defined the queries (at the top) from the commands (at the bottom). This leads to clarity in code readability which in-turn leads to an increase in maintainability. Getting to grips with the syntax of LINQ can take some time, but the increase in code maintainability is well worth the effort.

Thursday, 14 May 2009

Redundant Layers

There been an interesting difference of opinion on the blogs of Ayende and Greg Young regarding the usage of the Repository pattern. Whilst some great points were made on both sides, I tend to agree with Ayende's view that advances in tooling can render patterns, that we have become accustomed to using, redundant. In this case he argues that NHibernate has left little reason to implement Repository any more.

We segregate our applications into separate layers to help us manage the complexity of differing concerns. But we should accept that as new layers are added to an application, overall complexity of that application increases. If I was able to succinctly express my entire application in a single text file, without recourse to layers, I would. That is not (yet) possible so I use a layered approach.

As advances are made in tooling we need to constantly re-evaluate our use of layers and patterns to see it they have been superseded by technological advances. Take MVC as an example; had I been a Smalltalk programmer fifteen years ago I would have needed to create a controller for every widget. As tooling has advanced this has become unnecessary and we now have a different kind of MVC.

All too often I see applications where the architecture has been treated like a check list of layers. DTOs - check, domain - check, web services - check, repository - check; you get the idea. For me there has to be a very good reason for creating a new layer in my application. Do I really need that abstraction? If not, I don't feel compelled to include it. 90% of the applications I work with use a domain model. But that doesn't mean I always include that layer. A simple CRUD application with a few validation rules probably only requires a DAL and few DTOs and a presentation layer, for example.

We need to constantly question ourselves and the decisions we make about architecture, and should only implement layers where we feel there is a need; not because that's the way we've always done so.

Wednesday, 22 April 2009

Unity: Accessing the Creating Container

Here's something I learned today about Microsoft's Unity.

Often when an object is created through a container, you want to be able to access that container so that you can perform further resolutions. In the past my solution to this was to create a static class that held onto a single global instance of the container, essentially a Service Locator. The Service Locator could then be used by any class to access the same container.

I have never been 100% happy with this because, as we all know, static global data is a *bad* thing which introduces dependencies which are hard to test. Today I discovered that when a container resolves a class which has a parameter of type IUnityContainer, the container will pass itself to that parameter. This means that the container can be passed down the chain of constructors without resorting to any global static nonsense.

Here is my test:

public void ContainerPassesItselfToObjectsItCreates()
var container = new UnityContainer();

var objectCreatedByIoC =

public class ClassCreatedByIoC
public ClassCreatedByIoC(IUnityContainer container)
Container = container;

public IUnityContainer Container { get; private set; }

I assume this works with injection methods and properties as well, but I haven't tested it.

Thursday, 19 February 2009

Edward Woodward

Yesterday, I create a class called TheEqualizer. This has made me way more happy than should be the case.

Now I am worried that I more of geek than I thought I was.