Archive for May, 2009

Why Are Mutable Value Types Even Possible?

4 commentsWritten on May 17th, 2009 by
Categories: Software Development

A coworker of mine was recently trying to figure out why some code wouldn't compile.

Consider the following code:

            var point = new System.Windows.Point(5, 7);
            point.X = 6;
            point.Y = 8;
            Assert.AreEqual(6, point.X);
            Assert.AreEqual(8, point.Y);

This compiles and works. Now consider the following class:

    public class SomeClass
    {
        public System.Windows.Point SomePoint { get; set; }
    }

And then this small piece of code:

            var myObject = new SomeClass
            {
                SomePoint = new Point(2, 3)
            };
 
            myObject.SomePoint.X = 5;

You'd typically expect that this code would compile, right? Well it doesn't. It fails with the following compiler error:

error CS1612: Cannot modify the return value of 'SomeApp.SomeClass.SomePoint' because it is not a variable

Not exactly what you would expect, right? Well, the compiler error in this case is actually a good thing, though the message isn't as clear as it should be. See, System.Windows.Point is actually a value type instead of a reference type, and as you should know, value types behave very differently from reference types when passed around. You basically get a copy every time instead of the actual instance.

Let me just borrow the explanation of the "DO NOT define mutable value types" guideline, from Microsoft's Framework Design Guidelines:

Mutable value types have several problems. For example, when a property getter returns a value type, the caller receives a copy. Because the copy is created implicitly, developers might not be aware that they are mutating the copy, and not the original value.

Now the compiler error makes sense, right? Well, the message still sucks, but it makes sense that the compiler would protect you from making this mistake.

It won't protect you from the following mistake though:

            var myObject = new SomeClass
            {
                SomePoint = new Point(2, 3)
            };
 
            var point = myObject.SomePoint;
            point.X = 5;

This code will compile, though if you expect that myObject.SomePoint.X will return 5, you're in for a treat. Hopefully nobody writes code like this, but imagine having to debug something like this in some legacy code that was never properly tested.

But really, why are mutable value types even possible? In what situation does a mutable value type make sense? I'd really like to know, so please point out those situations in the comments if you know of one. The only reason i can think of is performance but the number of situations where a mutable value type is going to give you a significant performance boost is probably so small that it would've made more sense to enable mutability for value types with a language keyword or something like that. Unless there is another benefit that i'm not aware of yet?

Who’s In Charge Of The Time?

3 commentsWritten on May 6th, 2009 by
Categories: Software Development

I recently noticed that 2 tests were suddenly failing for no apparent reason. This was in a large codebase where we have a mix of two development approaches. The project is simply too big to convert everything at once to the latest development approach so we're using Ayende's Obsolete In Isolation approach on this. The 2 failing tests were in the old parts of the code, so i cringed and then set out to investigate.

The tests of the old part of the code aren't always easy to comprehend and they use the database all over the place. I figured i'd quickly run them on the database that we use when we run those tests on our local machines, and after that, run them on the database that the buildserver uses (which is rebuilt entirely with each build) to examine the differences between both test runs. They both passed in both cases. They were still failing on the buildserver though.

Upon first inspection of the code of those tests, it didn't seem like there was any blatantly obvious reason why those tests were failing on one machine, and not on the others. They were inserting some records with some manipulated DateTime values, and then calling some code which would execute a query which should have retrieved these values. The records inserted by the test were not retrieved for some reason, which caused the tests to fail.

DateTime values and tests can be tricky sometimes so i started looking in that direction. The queries that where executed in those tests would use the current date/time together with a margin of a couple of minutes to retrieve records where a certain date/time column's value would fall in the range of the current date/time with the given margin. The records that were inserted in the tests would use the current date/time, minus 2 minutes, or plus 2 minutes. Hmm... this could possibly be flaky depending on how the query determines the current date/time. If the query receives the current date/time from the calling code, then this wouldn't cause problems but if it uses the current date/time of the database, then this is not only a flaky test, but a real bug in the code.

I then checked the system clock of the buildserver, and as i suspected, it was about 4 minutes ahead of the system clock of the database server. Normally, all of our servers' system clocks are synchronized, but for some reason, the buildserver hadn't had its system clock synchronized since the day before. The code was inserting records in the database with modified date/time values, based on the system clock of the system the code was running on, and was then querying the database using the database's system clock. Since the time difference was big enough, the query would not return the expected rows and this made the tests fail on the buildserver.

Obviously, this never would've happened if the query would've used a parameter supplied by the caller which would've represented the current date. And that is the real bug that these flaky tests (which up until this particular incident never failed) highlighted. A situation like this could've occurred in production if the application server's clock and the database server's clock would've gotten out of synch. Can you imagine the pain you'd go through when investigating a bug report like this? :p

Date/Time values are often tricky, especially when there is more than one source which could determine the current Date/Time. So do yourself, and anyone who will maintain your code down the line, a favor by making sure that only ONE source is in charge of Date/Time values in your system. Using the database for all date/time values is definitely not always possible, so it's best to have your application server be in charge of all date/time values. If you need the current date/time in a query, simply supply it as a parameter to the query and you'll avoid problems like this.

Though this advice does leave me wondering what the best approach to deal with this is when you have multiple application servers which could assign date/time values.

On Getting Rid Of Common Libraries… What About Don’t Repeat Yourself?

6 commentsWritten on May 2nd, 2009 by
Categories: Opinions

Just wanted to post a small reaction to Ayende's dismissal of Util & Common Libraries. In his post, Ayende goes over everything that Rhino.Commons (his own library) offers and why he's not using it anymore. If you go over the list of everything in the library, i can definitely see why. As Ayende says, it's the garbage bin for anything that he came up with in the past couple of years, regardless of how many projects would actually reuse each specific part.

At work we have also have something like this, though in some ways it's smaller in scale, and in some ways it offers a bit more than Rhino Commons. A lot of it is based, or are further developed versions of, the infrastructural bits that i've posted on this blog in the last year. We also have some other interesting things in there that my coworkers wrote. We took the opposite direction however.

We started off with putting these classes in each project where we could use them. But since a lot of that stuff was still being modified or extended on a semi regular basis, we were constantly making the same changes or additions in multiple places, which violates the Don't Repeat Yourself principle. Essentially, it was duplicate code, just spread in multiple projects. Obviously, this brought along all of the same problems that duplicate code usually brings with it.

So we set out to figure out to best way to deal with this, and i even asked you guys about it. We eventually ended up moving these bits to some sort of in-house library/framework that all (or most) of our applications now use. While i was the one who was hesitant at first to go with a reusable library/framework (due to some bad experiences with it in the past), i'm now very glad we actually did do it.

We did go for multiple assemblies (ie: web, silverlight, service layer, ...) instead of putting everything in one big assembly though we did try to follow my 'one assembly per physical deployment' rule.

Bugs get fixed in one place and one place only. The only repetitiveness we have to endure when fixing a bug in the library is making sure we can merge the fix to previous versions and updating the referenced binaries in each project that uses it. That's it. New stuff only gets added when it's been proven to be useful in more than one project. We don't just add new things like that, unless it really makes sense to do so.

I think most of the problems that Ayende now sees with Rhino Commons can be avoided by splitting things up a bit more, and by being more restrictive as to what actually makes it into the library. Versioning suddenly becomes pretty important as well. These are all things that i always felt where somewhat missing with Rhino Commons. That's not to criticize the project because i do think there's a lot of valuable stuff in there, but in it's current form it's just not very well suited to be reused by other projects.

Having said all that, i'm not saying that reusable libraries/frameworks are the best thing since sliced bread either. They require a lot of discipline and it's easy to get tripped up simply by adding something or making a minor change where you didn't really think all of the consequences through. But the downsides of dealing with these libraries are usually smaller than the downsides of having the same code spread out over multiple projects.