2011-08-22

Goodbye _, Hello R# Color Identifiers

I've been prefixing my C# class members with _ (underscore) since the first version of C#. I really do like to be able to distinguish between instance and function scope.

I've also obeyed the larger part of the classic IDesign Coding Standard for who knows how long.

Therein, rule #67 states: "Do not use the this reference unless invoking another constructor from within a constructor." Usually, you'll use the same name for your fields and constructor arguments, why a this reference is needed if the fields aren't prefixed.

While re-reading the great book Clean Code authored by Uncle Bob today, I came across the following statement on page 24: "You […] don't need to prefix member variables […] anymore. […] you should be using an editing environment that highlights or colorizes members to make them distinct.".

The argument appealed to me, but how should I follow that advise? As a C# programmer, you're more or less forced to use Visual Studio. I knew, despite using ReSharper (R#) since its first version, that I've never come across field/member highlightning in the Fonts and Colors section.

After some googling, I finally found what I was looking for in R#; you need to enable Color Identifiers. Once I'd done that, the "ReSharper Field Identifier" (and more) show up among the display items in the aforementioned Fonts and Colors section.

Goodbye _, hello color identifiers!

Now I need to write a refactoring regex that refactors old, prefixed code…


UPDATE 2011-08-24: I've now refactored two C# solutions where I got rid of the prefixes by using VS' find and replace with regex and capture groups like so:
find what: private {.*} _{.*}
replace with: private \1 \2
and similar expressions.

2011-05-02

Project Euler: 1 Down. 335 To Go!

I signed up at Project Euler today in order to give myself some brain teasers.

I set up a Mercurial account at Google Code, and solved the first, very basic, problem tonight.

It was good fun, and now that I have the Visual Studio solution set up, I hope to solve more of these in my spare time.

Spoiler alert!

The C# implementation can be found here: http://code.google.com/p/project-euler-csharp/source/browse/ProjectEuler/Problem001_Find_the_sum_of_all_the_multiples_of_3_or_5_below_1000.cs

And the tests can be found here: http://code.google.com/p/project-euler-csharp/source/browse/ProjectEulerTests/Problem001_Find_the_sum_of_all_the_multiples_of_3_or_5_below_1000_Tests.cs

2011-03-16

Er tidens digitale teknologier en af årsagene til den øgede fascisme?

Baggrunden til denne min første danske blogpost, er at jeg studerer dansk hos Bente Hahne ved Sprogcentrum. Hver gang vi mødes får jeg lektier, og herunder en skriveopgave. Denne gang er min opgave at skrive om Kresten Schultz-Jørgensen's debatartikel i Politiken som fik rubrikken "Den sproglige fascisme breder sig" i Politiken 19. februar 2011. Da "tidens digitale teknologier" spiller en stor rolle i denne, synes jeg at det giver god mening at benytte lige den slags til at lave denne lektie.

Kresten ser med rædsel at det sproglige niveau er på nedtur bland de studerende ved CBS og andre universiteter, hvor han underviser og har været censor de seneste ti år. Dette på trods af at han mener at de samtidig er mere flittige og fokuserede end tidligere generationer.

Personligt mangler jeg selvfølgelig Kresten's empiriske grundlag, men jeg har samme erfaringer (dog hovedsagelig i en svensk kontekst). Disse kommer fra at lytte til P3, unge i fjernsynet og i byen, snakke med min elleve år yngre søster og hendes venner, etcetera.

Lige præcis som Kresten, frygter jeg at denne nedtur leder til flere fordomme og at der bliver flere synes, og færre af logisk underbyggede argumenter. "Færre ord, mindre råderum, flere fordomme. Dét er, som bekendt, fascisme." Det er med andre ord en utrolig alvorlig sag, som samfundet må bekæmpe! Hvis man er i tvivl om sprogets indflydelse på tanken, kan man bare læse Morten Things anmeldelse af Victor Klemperers Det Tredje Riges sprog.

Kresten anerkender dannelsekrisen i familien og skolen, men ønsker derefter at udpege "tidens digitale teknologier" som en stor grund til den gældende nedtur mht. sprogbrug og logisk argumentation. Af alle ydelser man kan tilgå i mobilnettet/på internettet, fokuserer Kresten kun på SMS, Facebook og Twitter. Disse er jo alle lige designede for hurtige, korte beskeder. Facebook er jo desuden et stort socialt netværk hvor idéen er at man skal hygge sig, dele feriefotos, musikvideoer, og tilsvarende. Dette er selvfølgelig ikke arenaen for dyb, sokratisk argumentation eller diskussion! Kresten, hvad mener du egentlig? (Man kan jo for søren også finde Sprogpolitiet på Facebook!)

Hvad med blogrevolutionen hvor jeg selv læser mange blogs med meget god logisk opbygning og argumentation (især tekniske, men også politiske)? ... og hvad med alle fora på nettet hvor du ikke kommer ret langt ved kun at synes ting uden argumenter? Jeg mener at den digitale revolution vi er midt i, giver os mange flere muligheder for god, klassisk debat og udveksling af ideer, end nogensinde før. Lige denne post er jo et eksempel på det.

I stedet for at gå i denne faldgrube, synes jeg at Kresten skal adlyde opfordringen fra Lars Friis Farsøe, en af Krestens tidligere studenter, når han siger at Kresten burde "vende blikket indad" og fokusere på sin egen rolle i egenskab af, blandt andet, lektor på et universitet med den slags store problemer.

Jeg vil slutte med at citere Tanja Juul Christiansen som både blogger med klogskab og undrer sig over hvem der egentlig har aben: "At skyde skylden på digitale teknologier som sådan er en uholdbar generalisering, der fordrejer sagen, og forringer debatten om, hvordan vi kan gøre noget ved problemet."

2011-01-28

Conway's Game of Life Code Kata #2

After yesterday's code retreat, I've refined, refactored, and added some IEnumerable plumbing to the solution I implemented in preparation for the retreat.

It would be a really fun exercise to visualize the generations with WPF, Silverlight or something else. I'd also like to finish the attempts made at the retreat to implement this solution with JavaScript. As one of my pairing partners pointed out, visualization could be done by manipulating the DOM of an ordinary web page.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using SharpTestsEx;

namespace ConwaysGameOfLifeKatas.Generations.UnitTests {
    [Description("en.wikipedia.org/wiki/Conway's_Game_of_Life")]
    public class GenerationsUnitTests {
        [Test]
        public void new_generation_should_kill_alive_cell_with_fewer_than_two_live_neighbours() {
            var generations = new Generations(new Cell(1, 1), new Cell(0, 1));

            generations.First().Contains(new Cell(1, 1)).Should().Be.False();
        }

        [Test]
        public void new_generation_should_keep_alive_cell_with_two_live_neighbours_alive() {
            var generations = new Generations(new Cell(1, 1), new Cell(0, 1), new Cell(2, 1));

            generations.First().Contains(new Cell(1, 1)).Should().Be.True();
        }

        [Test]
        public void new_generation_should_keep_alive_cell_with_three_alive_neighbours_alive() {
            var generations = new Generations(new Cell(1, 1), new Cell(0, 1), new Cell(2, 1), new Cell(0, 0));

            generations.First().Contains(new Cell(1, 1)).Should().Be.True();
        }

        [Test]
        public void new_generation_should_kill_alive_cell_with_more_than_three_alive_neighbours() {
            var generations = new Generations(new Cell(0, 0), new Cell(1, 0), new Cell(2, 0),
                                              new Cell(0, 1), new Cell(1, 1));

            generations.First().Contains(new Cell(1, 1)).Should().Be.False();
        }

        [Test]
        public void new_generation_should_revive_dead_cell_with_three_alive_neighbours() {
            var generation = new Generations(new Cell(0, 0), new Cell(1, 0), new Cell(2, 0));

            generation.First().Contains(new Cell(1, 1)).Should().Be.True();
        }

        [TestCase(0,0,0,false)]
        [TestCase(1,0,0,true)]
        [TestCase(2,0,0,false)]
        [TestCase(0,1,0,false)]
        [TestCase(1,1,0,true)]
        [TestCase(2,1,0,false)]
        [TestCase(0,2,0,false)]
        [TestCase(1,2,0,true)]
        [TestCase(2,2,0,false)]
        [TestCase(0,0,1,false)]
        [TestCase(1,0,1,false)]
        [TestCase(2,0,1,false)]
        [TestCase(0,1,1,true)]
        [TestCase(1,1,1,true)]
        [TestCase(2,1,1,true)]
        [TestCase(0,2,1,false)]
        [TestCase(1,2,1,false)]
        [TestCase(2,2,1,false)]
        public void blinker_oscillator_should_oscillate_according_to_wikipedia(int x, int y, int generationIndex, bool isAlive) {
            var generations = new Generations(new Cell(0, 1), new Cell(1, 1), new Cell(2, 1));

            generations[generationIndex].Contains(new Cell(x, y)).Should().Be.EqualTo(isAlive);
        }
    }

    public class Generations : IEnumerable<Generation> {
        private readonly Generation _seedGeneration;

        public Generations(params Cell[] seed) {
            _seedGeneration= new Generation(seed);
        }

        public IEnumerator<Generation> GetEnumerator() {
            return new GenerationEnumerator(_seedGeneration);
        }

        public Generation this[int index] { 
            get {
                return this.ElementAt(index);
            }
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }

        public class GenerationEnumerator : IEnumerator<Generation> {
            public GenerationEnumerator(Generation generation) {
                Current = generation;
            }

            public void Dispose() {}

            public bool MoveNext() {
                Current = Current.Tick();

                return true;
            }

            public void Reset() {}

            public Generation Current { get; private set; }

            object IEnumerator.Current {
                get { return Current; }
            }
        }
    }

    public class Generation {
        private readonly ISet<Cell> _aliveCells;

        public Generation(params Cell[] aliveCellsSeed) {
            _aliveCells = new HashSet<Cell>(aliveCellsSeed);
        }

        private IEnumerable<Cell> KeepAlives {
            get {
                return _aliveCells
                    .Where(c => GetNumberOfAliveNeighboursOf(c) == 2
                                || GetNumberOfAliveNeighboursOf(c) == 3);
            }
        }

        private IEnumerable<Cell> Revives {
            get {
                return _aliveCells
                    .SelectMany(GetDeadNeighboursOf)
                    .Where(c => GetNumberOfAliveNeighboursOf(c) == 3);
            }
        }

        public Generation Tick() {
            return new Generation(KeepAlives.Union(Revives).ToArray());
        }

        private IEnumerable<Cell> GetDeadNeighboursOf(Cell cell) {
            return GetNeighboursOf(cell).Where(c => !Contains(c));
        }

        private static IEnumerable<Cell> GetNeighboursOf(Cell cell) {
            return Enumerable.Range(-1, 3)
                .SelectMany(x => Enumerable.Range(-1, 3)
                                     .Select(y => new Cell(cell.X + x, cell.Y + y)))
                .Except(cell);
        }

        private int GetNumberOfAliveNeighboursOf(Cell cell) {
            return GetNeighboursOf(cell).Count(Contains);
        }

        public bool Contains(Cell cell) {
            return _aliveCells.Contains(cell);
        }
    }

    public struct Cell : IEquatable<Cell> {
        private readonly int _x;
        private readonly int _y;

        public Cell(int x, int y) {
            _x = x;
            _y = y;
        }

        public int Y {
            get { return _y; }
        }

        public int X {
            get { return _x; }
        }

        public bool Equals(Cell other) {
            return other._x == _x && other._y == _y;
        }

        public override bool Equals(object obj) {
            if (ReferenceEquals(null, obj)) return false;
            if (obj.GetType() != typeof (Cell)) return false;
            return Equals((Cell) obj);
        }

        public override int GetHashCode() {
            unchecked {
                return (_x*397) ^ _y;
            }
        }
    }

    public static class Extensions {
        public static IEnumerable<T> Except<T>(this IEnumerable<T> @this, T element) {
            return @this.Except(new[] {element});
        }
    }
}

2011-01-27

Conway's Game of Life Code Kata

In preparation for my first code retreat later today, we were asked to study the problem at hand - Conway's Game of Life. Wikipedia has an excellent article describing the rules.

At my first attempt; I focused on the cell and tried to use a state machine. It didn't take too long before it felt cumbersome, so I stopped (although the state machine tests passed ;-)).

Then I tried to mimic "the real world" (oh, what a fallacy...) again, but this time I implemented a Grid<Coordinate> with an internal List<List<Coordinate>>. This was also a mistake... Imagine keeping a reference for all empty cells as well as making the grid infinite.

Third time's the charm, right? Why not just let a logical Grid instance keep a set of live cells? And why not remove all state changes, hence making both the Coordinate and the Grid types immutable? That way the Grid is asked to create a new immutable Grid for each generation.

By using these ideas, I quickly arrived at the solution below which I really like. It'll be very interesting to see what other solutions we'll come up with at the retreat.

using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using SharpTestsEx;

namespace ConwaysGameOfLifeKatas.GridAsListOfAliveCells.UnitTests
{
    public class GridAsListOfAliveCellsTests {
        [Test]
        public void new_generation_should_kill_alive_cell_with_fewer_than_two_live_neighbours() {
            var grid = new Grid(new Coordinate(1, 1), new Coordinate(0, 1));

            grid = grid.CreateNextGeneration();

            grid.IsAlive(new Coordinate(1, 1)).Should().Be.False();
        }

        [Test]
        public void new_generation_should_keep_alive_cell_with_two_live_neighbours_alive() {
            var grid = new Grid(new Coordinate(1, 1), new Coordinate(0, 1), new Coordinate(2, 1));

            grid = grid.CreateNextGeneration();

            grid.IsAlive(new Coordinate(1, 1)).Should().Be.True();
        }

        [Test]
        public void new_generation_should_keep_alive_cell_with_three_alive_neighbours_alive() {
            var grid = new Grid(new Coordinate(1, 1), new Coordinate(0, 1), new Coordinate(2, 1), new Coordinate(0, 0));

            grid = grid.CreateNextGeneration();

            grid.IsAlive(new Coordinate(1, 1)).Should().Be.True();
        }

        [Test]
        public void new_generation_should_kill_alive_cell_with_more_than_three_alive_neighbours() {
            var grid = new Grid(new Coordinate(0, 0), new Coordinate(1, 0), new Coordinate(2, 0), 
                new Coordinate(0, 1), new Coordinate(1, 1));

            grid = grid.CreateNextGeneration();

            grid.IsAlive(new Coordinate(1, 1)).Should().Be.False();
        }

        [Test]
        public void new_generation_should_revive_dead_cell_with_three_alive_neighbours() {
            var grid = new Grid(new Coordinate(0, 0), new Coordinate(1, 0), new Coordinate(2, 0));

            grid = grid.CreateNextGeneration();

            grid.IsAlive(new Coordinate(1, 1)).Should().Be.True();
        }

        [Test]
        public void blinker_oscillator_should_oscillate_according_to_wikipedia() {
            var grid = new Grid(new Coordinate(0, 1), new Coordinate(1, 1), new Coordinate(2, 1));

            grid = grid.CreateNextGeneration();

            grid.IsAlive(new Coordinate(0, 0)).Should().Be.False();
            grid.IsAlive(new Coordinate(1, 0)).Should().Be.True();
            grid.IsAlive(new Coordinate(2, 0)).Should().Be.False();
            grid.IsAlive(new Coordinate(0, 1)).Should().Be.False();
            grid.IsAlive(new Coordinate(1, 1)).Should().Be.True();
            grid.IsAlive(new Coordinate(2, 1)).Should().Be.False();
            grid.IsAlive(new Coordinate(0, 2)).Should().Be.False();
            grid.IsAlive(new Coordinate(1, 2)).Should().Be.True();
            grid.IsAlive(new Coordinate(2, 2)).Should().Be.False();
        }
    }

    public class Grid {
        private readonly ISet<Coordinate> _aliveCoordinates;

        public Grid(params Coordinate[] aliveCoordinatesSeed) {
            _aliveCoordinates = new HashSet<Coordinate>(aliveCoordinatesSeed);
        }

        public Grid CreateNextGeneration() {
            var keepAliveCoordinates = _aliveCoordinates
                .Where(c => GetNumberOfAliveNeighboursOf(c) == 2 || GetNumberOfAliveNeighboursOf(c) == 3);

            var reviveCoordinates = _aliveCoordinates
                .SelectMany(GetDeadNeighboursOf)
                .Where(c => GetNumberOfAliveNeighboursOf(c) == 3);

            return new Grid(keepAliveCoordinates.Union(reviveCoordinates).ToArray());
        }

        private IEnumerable<Coordinate> GetDeadNeighboursOf(Coordinate coordinate) {
            return GetNeighboursOf(coordinate).Where(c => !IsAlive(c)); 
        }

        private static IEnumerable<Coordinate> GetNeighboursOf(Coordinate coordinate) {
            return Enumerable.Range(-1, 3).SelectMany(
                    x => Enumerable.Range(-1, 3).Select(y => new Coordinate(coordinate.X + x, coordinate.Y + y)))
                    .Except(new []{coordinate});
        }

        private int GetNumberOfAliveNeighboursOf(Coordinate coordinate) {
            return GetNeighboursOf(coordinate).Count(IsAlive); 
        }

        public bool IsAlive(Coordinate coordinate) {
            return _aliveCoordinates.Contains(coordinate);
        }
    }

    public struct Coordinate : IEquatable<Coordinate> {
        private readonly int _x;
        private readonly int _y;

        public Coordinate(int x, int y) {
            _x = x;
            _y = y;
        }

        public int Y { get { return _y; } }

        public int X { get { return _x; } }

        public bool Equals(Coordinate other) {
            return other._x == _x && other._y == _y;
        }

        public override bool Equals(object obj) {
            if (ReferenceEquals(null, obj)) return false;
            if (obj.GetType() != typeof (Coordinate)) return false;
            return Equals((Coordinate) obj);
        }

        public override int GetHashCode() {
            unchecked {
                return (_x*397) ^ _y;
            }
        }
    }
}