Price In Nonsense was originally posted on December 17th, 2007.


Some years ago, Pete, a clever coder, developed an application that tracked commissions for futures trading. Pete had long since left the company, his role now filled by Andy M.

Andy didn't have much exposure to Pete's code, aside from the occasional bug fix. Fixing bugs in Pete's code always left Andy feeling uneasy, however, as the problems were almost always a result of logic errors.

When Andy learned that he and his team would be porting some of Pete's code to a new application, they fought tooth and nail for permission to do a total rewrite. Logic errors are the worst kind of errors, they argued. Problems can go unnoticed for weeks, then everyone has to scramble to fix the data. Still, management wouldn't budge — Andy was ordered to port the code.

Pete was famous for his workarounds. Often, this meant solving a problem that didn't exist with the worst possible solution. In this case, it was a workaround for SQL Server's MONEY datatype. And DECIMAL. And SMALLMONEY.

This application had to store dollars and cents in the database. To do this, Pete created an INT column on the Commissions table called "price_in_cents." Fortunately, he had the foresight to create a custom class ("Money") to make working with price_in_cents a little easier, and it served as an adapter for all inserts and updates.

Money myMoney = new Money(0.10); // $.10
return myMoney.DBValue; // returns 10

Andy opened Money.cs and saw a brief history of changes in precision:

public int DBValue
{
    // Pete 01/05- precision is cents:
    // get { return Convert.ToInt32(_value * 100.0); }

    // Pete 01/20- precision is 1/10 cents:
    // get { return Convert.ToInt32(_value * 1000.0); }

    // Pete 02/13- precision is 1/100 cents:
    get { return Convert.ToInt32(_value * 10000.0); }
}

Two (imaginary) decimal places wasn't sufficient to track commissions; they needed a precision of tenths of a cent. Fortunately for Pete, any time price_in_cents was written to, it had first been passed through his Money class and pulled from its DBValue property, which would contain the actual value to be written to the database. Formerly, $.10 would be stored as 10 in the database. Now, 10 cents was 100.

A later update added another zero to the conversion for even more precision, so now Money(0.10)'s DBValue would be 1,000.

It was then that Andy found several tables whose data had wildly different values in their price_in_cents columns, which now should've been named "prices_in_hundredths_of_cents," anyway. Furthermore, the values were meaningless. A value of 500,000 could mean $5,000.00, $500.00, or $50.00, depending on which version of the class library was in use at the time.

As much as he wanted to, Andy was in no position to rid the system of Money. Management's directive was clear: Adapt, but don't Change. Despite that, he was able to sneak in a little change – er, adaptation. price_in_cents became a DECIMAL and the system became a little saner.

 

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!