Cannot modify the return value of ‘System.Collections.Generic.List.this[int]‘ because it is not a variable

I recently stumbled upon this compile time error while trying to change the value of a structure over iteration. The Compiler throws this error when returned structure is modified. The reason is that structures are value types and immutable. The returned structure will be a copy. And any change to the copy doesn’t reflect in the original structure hence the compiler prevents from doing this which is not intended.

For instance, the following code won’t compile. The compiler will throw
Cannot modify the return value of ‘System.Collections.Generic.List.this[int]’ because it is not a variable

public struct Person
{
    public string Name;
}

public class StringUtil
{
    public void ToUpper(List<Person> persons)
    {
        for (int i = 0; i < persons.Count; i++)
	{
            persons[i].Name = persons[i].Name.ToUpper();
        }
     }
}

The solution requires not changing the value and creating a new structure with new values.

public class StringUtil
{
    public void ToUpper(List<Person> persons)
    {
        for (int i = 0; i < persons.Count; i++)
	{
            persons[i] = new Person { Name = persons[i].Name.ToUpper() };
        }
     }
}

My TDD Experience

I was introduced to TDD couple of years ago through a workshop by Naresh Jain on TDD and refactoring. Back then, I had no idea on how to write unit tests and what the heck refactoring and TDD is really about.  This is one of the best workshops I have attended. I didn’t learn the subject in five days but the workshop paved the way for continuous informal learning.

Test Driven Development (TDD) is a design technique that drives the development process through testing. It contains three simple steps:

  • Add a failing test for new feature/bug.
  • Add code to make test pass.
  • Refactor the code.

You repeat the above three steps to build the entire functionality of the system.

TDD was weird when I heard about it for the first time. My way of developing software was being challenged. I thought, “Why should I write tests first without writing any production code?” . It took me a while before I gave it a shot. I liked it for various reasons.

  1. There’s no time wasted in upfront big design. Yes, some effort goes into design when test driving a project.
  2. Encourages smallest possible feature to be tested.
  3. Fearless refactoring. Developers are empowered to make changes at any point of time. Tests act as a safety net.
  4. Better architected. Have you ever tried writing tests after developing? One has to break dependencies to write tests, probably re-architecture, eventually giving up the idea of tests.

After that workshop, I learnt how to write unit tests and refactor. I could see the difference in the way I was churning out the code. It was beautiful!

Having practiced lot of katas on TDD, I wanted to put TDD into use and see if it really works. I used Naresh’s advice on identifying a pilot project for agile transformation.

I was very slow initially when I started on this project because one requires time to get into the TDD rhythm. Tests made me to think about the design of a particular interface. It’s like eating your own dog food.  After getting the tests and code right, I was quite fast in fixing bugs and pushing big features and changing the design without any headache. I was seeing the result. Now I have a good set of tests and readable code which can be easily extended.

TDD is not a silverbullet to software development. One still needs to write good tests and apply good development skills here. Developing software is painstaking. But TDD leads to software that is maintainable and cleaner.  It gives confidence and have an updated spec(tests). It is fun to test drive.

Better way of Structuring Unit Tests

Structuring improves the readability of the code. Test code is no exception. I pretty much follow the traditional way of writing a test class for each class that needs to be tested. Sometimes, I would run into the problem of having loads of tests in a single test class.

I found a nice article on structuring unit tests by Phil. The basic structure is a test class that has test classes for each method being tested. In other words test class contains nested class for each method being tested.

One of the fundamental activities in writing good code depends on how well methods are written. They are the core of any source code. Writing them well is very important.

Let me take you through some of the important things to keep in mind while writing methods.

Consider the code given below and try understanding the code.

        public int Score()
        {
            int score = 0;
            int j = 0;
            for (int i = 0; i < 10; i++)
            {
                if (rolls[j] == 10)
                {
                    score += 10 + rolls[j + 1] + rolls[j + 2];
                    j++;
                }
                else if (rolls[j] + rolls[j + 1] == 10)
                {
                    score += 10 + rolls[j + 2];
                    j += 2;
                }
                else
                {
                    score += rolls[j] + rolls[j + 1];
                    j += 2;
                }
            }
            return score;
        }

How readable is it? Certainly, not much.

With series of renaming and extracting methods, the intent of the method is captured. Now, it is easy to understand that this method computes the score of a bowling game.

        public int Score()
        {
            int score = 0;
            int frameIndex = 0;
            for (int frame = 0; frame < 10; frame++)
            {
                if (IsStrike(frameIndex))
                {
                    score += 10 + GetStrikeBonus(frameIndex);
                    frameIndex++;
                }
                else if (IsSpare(frameIndex))
                {
                    score += 10 + GetSpareBonus(frameIndex);
                    frameIndex += 2;
                }
                else
                {
                    score += SumOfBallsInFrame(frameIndex);
                    frameIndex += 2;
                }
            }
            return score;
        }

        private bool IsStrike(int frameIndex)
        {
            return rolls[frameIndex] == 10;
        }

        private int SumOfBallsInFrame(int frameIndex)
        {
            return rolls[frameIndex] + rolls[frameIndex + 1];
        }

        private int GetSpareBonus(int frameIndex)
        {
            return rolls[frameIndex + 2];
        }

        private int GetStrikeBonus(int frameIndex)
        {
            return rolls[frameIndex + 1] + rolls[frameIndex + 2];
        }

        private bool IsSpare(int frameIndex)
        {
            return rolls[frameIndex] + rolls[frameIndex + 1] == 10;
        }

Methods should be named well. Use names that communicate what the method is trying to achieve. If you are forced to write a comment, then it’s high time you rename the method.

If you look at the refactored code, methods are small. It’s readable and maintainable. Their intent is obvious. Always strive for smaller methods.

How small should a function be? It depends on the context but not more than a page. And if you have to scroll down and up to understand the code, then it’s long enough to be refactored.

A Method should do only one thing, and it should do it well. The refactored methods do one thing. What is the one thing? A method should have one reason to change.

Methods should have not more than 3 arguments. because the more the number of arguments, the more complex it is to read the code. A long parameter list is derived from procedural paradigm because a function can get data from either global variable or function parameters. Hence all the data is passed as parameters to the function. Object oriented paradigm supports encapsulation. So make use of it.

Don’t repeat yourself. Duplication is a huge problem in software development because it bloats the code and requires hunting down all the places if there’s any change.

Writing beautiful methods

Use comments sparingly

Developers are encouraged to write comments for the code in detail right from college days. The obvious reason is, it helps in improving readability and making maintenance easier. Apparently, we end up churning more lines of comments for tricky logic, thus resulting in comments sprinkled throughout the code base.

More often, comments are used as deodorants for badly written code.  Comments, as a rule, result in the following problems:

  • Encouraging developers to write code which doesn’t communicate its intent.
  • Comments are dead documentation. How many of us update the comments when we bring in some code changes? Hence it’s outdated most of the times.
  • Along with the code, comments require maintenance.

At times, the “why” part of the code is not obvious looking at the code. If it’s really difficult to communicate the why, then comments can be used.

How then, can one read the code base without comments? Good unit tests can serve as living and updated documentation. Developers should be taught to write clean code and making comments as an exception, not a rule which would push for the developer to write intent revealing code.

Comments are helpful in certain areas:

  • Public libraries have comments for each public method or property, which is used to create documentation.
  • Explain an hack in your code. A Codebase without hacks is non-existent. This may be due to lot of various reasons, which is not my concern here.

In Clean Code Robert Martin says
“The proper use of comments is to compensate for our failure to express yourself in code. Note that I used the word failure. I meant it. Comments are always failures.”

Developers should strive to reduce such failures. And Comments should be used sparingly.

C# Generics abused

This is my first post and as a tradition in picking up any new computer language, one would start off with a “Hello, World” program but I am going to discuss about how one of the great features of C# language, Generics can be abused.

Here’s the definition of Generics from MSDN.

Generics allow you to define type-safe data structures, without committing to actual data types. This results in a significant performance boost and higher quality code, because you get to reuse data processing algorithms without duplicating type-specific code. In concept, generics are similar to C++ templates, but are drastically different in implementation and capabilities.

Let’s assume that I am trying to build a managed library for some unmanaged code. Basically wrap the unmanaged code by .net.

I have with me a set of C functions which do the same operation on different data types.

void PerformActionUInt(uint[] data);

void PerformActionByte(byte[] data);

void PerformActionUShort(short[] data);

We might think making use of a generic method, which can drastically reduce the method overload bloat.
Here’s how the .net generic method wraps the above C functions. This generic method contains logic to figure out which C function to be invoked based on the data passed.


private void PerformAction(T[] data)
{
    uint[] uintData = data as uint[];
    if (uintData != null)
    {
        PerformActionUInt(uintData);
        return;
    }

    ushort[] ushortData = data as ushort[];
    if (ushortData != null)
    {
        PerformActionUShort(ushortData);
        return;
    }

    byte[] byteData = data as byte[];
    if (byteData != null)
    {
        PerformActionByte(byteData);
        return;
    }

    throw new ArgumentException(data.GetType() + " not supported");
}

This, according to me, is a clear abuse in the usage of generics. And following are the problems with the above design:

1. Performance cost : Casting is performed on the passed data against each supported data type to figure out the data type.

2. Potential runtime exception: What if the method is passed with an unsupported data type? Yes, one can argue that documentation would be updated on the supported data types, but how many of us would read the documentation until we run into any problem?

I would prefer to have overloads for the above methods, and not use generics, which is not meant for this particular case.