Författare arkiv

Øredev 2010, in retrospect

So, Øredev has come and passed. I have not been able to attend the last couple of years. This year I attended two days, Wednesday and Thursday (November 10 and 11). To summarize an event like that in a blog post is not very easy to do, but I will give it a shot. It will be a bit sprawling but, if nothing else, it can serve as memory notes for me at some point in the future.

The venue

This year Øredev was held at a venue called Slagthuset (article in Swedish). The venue is located in a very good spot, right next to the train station in Malmö, so it’s very easy to get there. The session rooms were built in larger halls with temporary walls around them. This worked fairly well, but sound travelled between the rooms. For many sessions that I attended this was not really a problem, but during some sessions the sound from neighboring session rooms became an issue.

The stage of each room (at least the ones that I saw; mainly on the .NET and Agile tracks) was arranged in the same way; a small round “bar table” at the right hand side (as seen from the audience), and with a cylinder formed loudspeaker standing next to the stage on the left-hand side. These two obstructed the view for people that were seated towards the edges of the room. Visibility would have improved greatly if these (especially the loudspeakers) were pushed back a bit towards the back wall. Perhaps there were (sound technical) reasons for keeping the speaker along the front edge of the stage though.

That is just about all negative stuff you will find in this text. From here on it’s all praise :)Everything else was a very positive experience; the food, the speakers, the attendants and the overall atmosphere all helped making this a very nice event.

The sessions

The Wednesday keynote was held by Dr. Jeffrey Norris of NASA Jet Propulsion Lab. He shared the story of how Alexander Graham Bell invented the phone, as an illustration of Agile thinking. The key message was that Bell succeeded because he had a Vision, he was willing to Risk a lot to get there, and he did not quickly commit to a specific solution, but instead kept many doors open and explored several paths. These qualities were shown to be shared by several people behind great inventions. Of course there was a touch of NASA in the talk as well; the story of how the Apollo 11 space ship came to get the design it did was told using some really cool 3D presentation technique involving printed cards that were interpreted by a camera that superimposed 3D objects on the screen.(check it out here).

The Thursday keynote was equally inspiring, and not only because there was not a [insert favorite presentation software] slide in sight. John Seddon talked about how we often focus on the wrong things, essentially indicating that when you manage something, that something tends to grow. Many organizations focus on managing cost so, well, the cost tends to go up. So focus should be on managing value instead. Suprise ;)

Apart from the keynotes I attended sessions with (amongst others) Glenn Block (twice), Jon Skeet, Ade Miller, Roy Osherove, Diana Larsen and Jim Benson.

In his first session Glenn Block shared some insight in what is coming next in WCF. I must say that I really like how the WCF team seems to manage to walk the fine line between isolating service implementation from details on the format used for sending data to the client, while at the same time allowing (but not requiring) you as a developer to have detailed control over the process.

Jim Benson talked some about the psychology of Kanban. I recognized myself in a lot of what he said. My first experience with working with Kanban was an almost physical sense how work flowed in the project, and the great satisfaction of seeing the project advancing even if I was a bit stuck on a task.

The Diana Larsen session that I attended discussed six skills needed for members in a team to collaborate efficiently (Communicate, Built Trust, Make Decisions, Hold Effective Meetings, Share Leadership and Engage Conflict). An interesting touch in her talk was the photos that illustrated the points; they were taken by Diana, showing situations and team members that she had worked with, so she could say stuff like “that guy sitting there, his name is James, he had this situation when…” and so on, which I felt added an extra feeling that she knew what she was talking about; these were real-world examples, not paper products.

Ade Miller gave a talk walking through some patterns of parallel programming using a very good mix of illuminating slides and sample code. The sample was a simple financial application that showed the effects of different kinds of parallelization (hint; speed improved). He also handed out copies the book of Parallel Programming with Microsoft .NET to the people that attended.

Glenn Block returned with a session on the Reactive Extensions framework for .NET, which in short provides an event based model for asynchronous data exchange. His talk was followed by Roy Osherove giving a talk about how to review test code, pointing out that tests should be Maintainable (reuse code, use object factories) and Readable and that you must be able to Trust your tests. He stressed that test code should contain an absolute minimum (preferably no) logic, and that it should lean on static test data.

Jon Skeet talked (or rather demonstrated) some funny corner cases in C#, showing, amongst other things, how you can “override” extension methods, something that is quite useful for diagnostic purposes.

On the Thursday evening Øredev opened the doors for various communities, under the name Øredev Open. Diversify sponsored (together with Microsoft) an event organized by Swenug. Three speakers were invited and given one 20-minute slot each. Greg Young announced Mighty Moose, a tool that runs on top of AutoTest.NET. Mighty Moose will monitor the file system to detect when you save a file. It will then build the project, perform an analysis of what tests that may be affected by the change, and then automatically run these tests. This might be a huge time saver, especially in projects with a large number of tests. Mighty Moose does not seem to have an internet home yet, but follow Greg on Twitter if you are interested.

After Greg was done, Hadi Hariri entered the stage and gave a quick peek at what is coming in ReSharper 6. Lots of nice stuff here as well (including very good tools for working with JavaScript code). Finally Roy Ashton gave a lightning talk (both in terms of length and speed) about CouchDB. The event was ended with a lottery were we (Diversify) gave out a Windows Phone 7 (or rather a gift certificate for one, once it hits the store shelves), JetBrains gave away one ReSharper license and one DotTrace license, and Microsoft tossed in a Kinect as well.

From what I understand the Friday was no worse, and I will really make sure to clear the whole Øredev week in my calendar next year.

Kudos to Michael Tiberg and his team for the great achievement of making this happen.

My value may not equal my value

I saw a question at StackOverflow that, amongst other things, asked if it could ever be that a.ReferenceEquals(b) is true, while at the same time a.SomeProperty != b.SomeProperty. The spontaneous answer to that is probably “no, if they refer to the same instance, they also refer to the same data” and, I would argue, in most practical cases that answer would (and should) also be true. But there are situations when this could happen.

Imagine that we have a type with a property that has value that changes over time, and where it also takes a small amount of time to produce the value:

class Foo
{
    public long SomeValue
    {
        get
        {
            // simulate that it takes a short while
            // to get the info
            Thread.Sleep(10);
            return DateTime.Now.Ticks;
        }
    }
}

Then consider the following program:

class Program
{
    static void Main()
    {
        Foo a = new Foo();
        Foo b = a;
        Console.WriteLine("object.ReferenceEquals(a, b) => {0}",
                           object.ReferenceEquals(a, b));
        Console.WriteLine("a.SomeValue == b.SomeValue   => {0}",
                           a.SomeValue == b.SomeValue);
    }
}

What do you think it prints?

The answer is:

object.ReferenceEquals(a, b) => True
a.SomeValue == b.SomeValue   => False

The reason is obviously that the property getter is called twice on the same instance, but returns a different value each time. So, when a property returns a value that is produced in the getter, there is a possiblity to create scenarios where two variables may reference the same instance, but where comparing the values from the same property may still return
false.

This is not very strange really, but many programmers (myself included) might find such behavior confusing, and I would use that as an argument that property access should always be extremely cheap,
preferably just reading the value from a field. If there is work required to produce the value, and especially if the value may differ between calls, it should be a method instead.

A readonly array is not exacly read-only

Every now and then I come across developers that does not quite get their heads around the meaning of the readonly keyword in C#, and perhaps especially when combined with arrays. Since I like to exemplify with code, let’s start in that end:

class Numbers
{
    public readonly List<int> OneThroughFour = new List<int>{ 1, 2, 3, 4 };
}

class Program
{
    static void Main(string[] args)
    {
        Numbers numbers = new Numbers();
        numbers.OneThroughFour[3] = 42;
        Console.WriteLine(string.Join(", ", numbers.OneThroughFour));
    }
}

This will print "1, 2, 3, 42", which seems confusing for some. If readonly does not make the list read-only, what does it do? The documentation for the readonly keyword says the following:

The readonly keyword is a modifier that you can use on fields. Whena field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.

It clearly says that assignments to the field can only occur during the construction of the class. In our code sample above we assign a value to the list (numbers[3] = 42;). Is that not an assignment to the field? No, it is an assignment to a property in the object that the field holds a reference to, it is not an assignment to the field itself. If we would try to replace the list with another list, the compiler would give us an error:

// the following line gives the compilation error "A readonly
// field cannot be assigned to (except in a static constructor
// or a variable initializer)"
numbers.OneThroughFour = new List<int> { 1, 2, 3, 42 };

OK, but what if the field is an array?

class Numbers
{
    public readonly int[] OneThroughFour = new[] { 1, 2, 3, 4 };
}

class Program
{
    static void Main(string[] args)
    {
        Numbers numbers = new Numbers();
        numbers.OneThroughFour[3] = 42;
        Console.WriteLine(string.Join(",", numbers.OneThroughFour));
    }
}

The result of this code is exactly the same as in the previous example ("1, 2, 3, 42"). Again, we are not assigning a value to the field, but to an element of the array that the field holds a reference to. Now I can hear somebody say “but hey, wait a minute… isn’t int a value type? So the field should hold a copy of the data rather than a reference to it, right?” Yes, int is a value type, but in .NET all arrays are reference types. This means that any code that obtains a reference to the array can also alter its elements. Again, the readonly keyword only prevents the array object itself from being replaced by another array object.

But what if I really want the list read-only?

The first step you should take is to make sure not to expose the field itself outside the type in which it is declared. That way you gain control over what code that can access (and thus modify) the contents of the array directly. The second step is to show intent. Expose the array in a manner that communicates that it should be regarded as being readonly, by returning it as an IEnumerable<int> rather than int[]:

class Numbers
{
    private readonly int[] oneThroughFour = new[] { 1, 2, 3, 4 };

    public IEnumerable<int> GetOneThroughFour()
    {
        return oneThroughFour;
    }
}

This will make any attempt to assign a value to an element (such as numbers.GetOneThroughFour()[3] = 42;) result in a compiler error, since IEnumerable<T> does not support accessing elements by index. This clearly tells developers writing calling code to regard the returned list as a read-only list. However, there is nothing that prevents calling code from manipulating the internal array, using a simple type cast:

((int[])numbers.GetOneThroughFour())[3] = 42;

For most common uses, I would say this is sufficient (unless the type is exposed in some commercial class library or similar); at this point we quite effectively prevent developers from accidentally writing code that modifies the list.

If it is critical that you prevent modification of the list on a technical level, there are some different approaches:

Use a ReadOnlyCollection<T> for storing the list:

class Numbers
{
    private readonly ReadOnlyCollection<int>
    oneThroughFour = new ReadOnlyCollection<int>(new[] { 1, 2, 3, 4 });

    public IEnumerable<int> GetOneThroughFour()
    {
        return oneThroughFour;
    }
}

Store the list as an array, but return a copy of the array:

class Numbers
{
    private readonly int[] oneThroughFour = new[] { 1, 2, 3, 4 };

    public IEnumerable<int> GetOneThroughFour()
    {
        return (IEnumerable<int>)oneThroughFour.Clone();
    }
}

Yet another option is to store the list as an array, but use yield return for returning the items. This might be preferable if the list is potentially large:

class Numbers
{
    private readonly int[] oneThroughFour = new[] { 1, 2, 3, 4 };

    public IEnumerable<int> GetOneThroughFour()
    {
        int index = 0;
        while (index < oneThroughFour.Length)
        {
            yield return oneThroughFour[index++];
        }
    }
}

This will throw an InvalidCastException if calling code attempts to cast the return value to int[].

/Fredrik Mörk

Tillbaka