Wednesday, October 16, 2013

C# Isn't Java - Learning via Katas - Part 1

CSharpKatas is a new GitHub project and training tool I put together.  It teaches C# newcommers how to apply advanced language features, how to write idiomatic C#, and most importantly how to avoid Java idioms.


C# Isn't Java


C# is at least a decade ahead of Java, and that's being generous.  Sadly many junior, ex-Java, and even some seasoned C# developers continue to use Java idioms in C# and think of the two as equivalent.  I've overheard "C# is just like Java" more times than I care to recall, and it makes me angry every time.

If you too become frustrated hearing these similes and need a resource, or you find yourself on a C# project with Java coders, or you could just use a refresher on writing idiomatic C#, then CSharpKatas is for you and/or your team.  I hope you enjoy and that it becomes a valuable resource for you and the C# community.

Java is Blub


Why do people confuse Java with C# to begin with?  Partly this is Paul Graham's Blub Paradox at work:

Blub is a hypothetical programming language … As long as our hypothetical Blub programmer is looking down the power continuum, he knows he's looking down. Languages less powerful than Blub are obviously less powerful, because they're missing some feature he's used to. But when our hypothetical Blub programmer looks in the other direction, up the power continuum, he doesn't realize he's looking up. What he sees are merely weird languages. He probably considers them about equivalent in power to Blub, but with all this other hairy stuff thrown in as well. Blub is good enough for him, because he thinks in Blub.

Java is Blub and C# the more powerful language.  C#'s power is derived from the huge array of language features it has that Java lacks (and that Java won't have for at least a decade if ever).  Some of these features include:


Those that equate C# and Java are likely unfamiliar with many of the features listed above.  Should they happen to run into code that, for example, uses a method missing catch-all (aka TryInvokeMember) they just see weird constructs and "hairy stuff" and assume incorrectly that C# is equivalent with Java.

C#'s Beauty Revealed


My lofty goal is first, to put a stop to the misconception that "C# is just like Java" and second, to encourage C# newcomers to write idiomatic C#.  To accomplish this I put together a set of Code Katas, or mind exercises that I published in a github project.

Each Kata consists of a set of failing unit tests and some to do's.  The problems are generally extracted from real problems I've had to solve and are designed to introduce new concepts gradually.  Developers are asked to turn the tests green using any means necessary, then refactor using C# idioms (such as not writing loops or if statements without good reason).  The exercises assume a solid working knowledge of an OO language such as Java and an ability to look stuff up in the documentation.

Perhaps along the way developers will become convinced of how wonderful TDD and Red-Green-Refactor is, but that's incidental.

Now if you're more of a book learner, or just want more depth, I would highly encourage you to read Jon Skeet's awesome book C# In Depth.

Or if, like me, you're more a hands-on learner I would encourage you to follow along at home by branching or pulling my CSharpKatas project and trying to solve the problems in your own branch.  If solving a Kata takes more than a few minutes I recommend you delete your solution and do it again until solving it is second-nature.

Finally, there are no solutions published.  If there is demand I may publish my solutions, but the "to do"'s should be sufficient.

Kata #1


The objectives of the first Kata:

  • Learn to run C# unit tests
  • Learn basic alternatives to loops and foreach statements
  • Learn how to use lambdas and some LINQ to Objects

Without further ado here is a copy of first Kata:

using NUnit.Framework;

namespace CSharpKatas
{
    public class Calculator
    {
        public int SumNumbers(int start, int count)
        {
            // todo #1: Get all the tests passing
            // todo #2: Refactor so there are no loops or if statements (this
            
//    is the functional approach and is idiomatic for C#)
            // todo #3: Refactor to use the Aggregate() LINQ method            
            //    see 101 Linq Samples)
            return 0;
        }
    }

    [TestFixture]
    [Ignore]
    public class Test
    {
        [Test]
        public void SumNumbers_StartAt100SumNext1_TotalIs100()
        {
            var kata = new Calculator();
            Assert.AreEqual(100, kata.SumNumbers(100, 1));
        }

        [Test]
        public void SumNumbers_StartAt100SumNext2_TotalIs201()
        {
            var kata = new Calculator();
            Assert.AreEqual(201, kata.SumNumbers(100, 2));
        }
        [Test]
        public void SumNumbers_StartAt100SumNext0_TotalIs0()
        {
            var kata = new Calculator();
            Assert.AreEqual(0, kata.SumNumbers(100, 0));
        }

        [Test]
        public void SumNumbers_StartAt0SumNext0_TotalIs0()
        {
            var kata = new Calculator();
            Assert.AreEqual(0, kata.SumNumbers(0, 0));
        }

        [Test]
        public void SumNumbers_StartAt0SumNext3_TotalIs3()
        {
            var kata = new Calculator();
            Assert.AreEqual(3, kata.SumNumbers(0, 3));
        }

        [Test]
        public void SumNumbers_StartAt0SumNext100_TotalIs5050()
        {
            var kata = new Calculator();
            Assert.AreEqual(5050, kata.SumNumbers(1, 100));
        }
    }
}


Conclusion


I hope you find these Kata's fun and enlightening and that you find my enthusiasm for the C# language contagious.  Enjoy!  And feel free to ask questions in the comments here or @lprichar on twitter.

3 comments:

john gates said...
This comment has been removed by a blog administrator.
Valério Farias said...

I'm just put a unique line inside of the SumNumbers method to solve the problem:

return start + count;

Every test pass now.

How can I do the other TODOs if I don't have "if or while" statements inside the code.

Wait your reply.


savitha singh said...
This comment has been removed by a blog administrator.