Blog

What's Wrong with a Data-Driven Approach?

August 29, 2008

Suppose we are building yet-another-order-basket-application. We have the requirement for adding items to an order, otherwise the business of our entire company falls down and we are losing tons of money (while not overdramatizing things). The code I see popping up over and over again looks something like this:

public class DataDrivenService
{
    private Database _database;
    
    public SomeService()
    {
        // Setup database member variable
    }

    public void AddItem(Int64 orderId, Int64 productId, 
                        Int32 quantity)
    {
        String sql = " INSERT INTO ORDERITEMS " +
                     " VALUES(@OrderId, @ProductId, @Quantity) ";
        
        // Code for setting SQL parameters
        
        _database.ExecuteNonQuery(sql, parameters);    
    }
}

Besides the fact that it uses some crappy data access framework like the Data Access Application Block of the Enterprise Library, there are some things that are really wrong with this code.

For starters, this code completely neglects the concepts of our business domain. Its is all about database connections and executing SQL statements.

Secondly, it violates the Single Responsibility Principle. This code clearly has the concept of SQL and the database schema. As mentioned earlier, it also hides the concept of adding items to an order. Both of these concerns change for different reasons.

Third, this code is simply not testable without incorporating the database. It probably has not unit or integration tests at all. This is also called legacy code.

What’s a better approach then?

public class Order
{
    private IList<Item> _items = new List<Item>();

    public void AddItem(Product product, Int32 quantity)
    {
        _items.Add(new Item(product, quantity));
    }
}  

public class SomeAppService
{
    private IRepository<Order> _orderRepository;
    private IRepository<Product> _productRepository;

    ...

    public void AddItem(Int64 orderId, Int64 productId, 
                        Int32 quantity)
    {
        Order order = _orderRepository.Get(orderId);
        Product product = _productRepository.Get(productId);
        
        order.AddItem(product, quantity);
        
        Repository<Order>.SaveOrUpdate(order);
    }
}

This code nicely separates the two concerns discussed earlier. If the database schema changes, then the database code inside the repositories needs to be changed while the business logic is left untouched. What I probably like the most about this orthogonal approach, is that it enables me to forget about the database until the last responsible moment.

I’ve said this quite a number of times already: Databases are just a detail. There just another piece of software to efficiently store data on disk. That’s all! Why some people want databases to be  at the center of their application is simply beyond my intellectual capacities.

As always, there is a time and place for data-driven applications. I just don’t buy that it is well suited for applications with more complexity than vanilla ice cream. This means that it is almost always the wrong choice for any long-lived application.

Profile picture of Jan Van Ryswyck

Jan Van Ryswyck

Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.

Comments

About

Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.

Contact information

(+32) 496 38 00 82

infonull@nullprincipal-itnull.be