KISS

Few days back, I came across this clever piece of code, an extremely simplified version. Please give it 5 seconds to see what is happening here. OK, give it 10 second and you will see what this code is doing:


namespace LaLaLambda
{
    class Program
    {
        static void Main(string[] args)
        {
            Process();
        }

        static void  Process (){
            WriteResponse(
                (writer) =>
                {
                    writer.WriteIt("write this line");
                });
        }

        static void WriteResponse ( Action  writeAction)
        {
            using (TextWriter writer = File.CreateText("C:\\temp\\test.txt"))
            {
                writeAction( new MessageWriter (writer));
            }
        }
    }

    class MessageWriter {

        TextWriter tw;

        public MessageWriter (TextWriter t){
            tw = t;
        }
        public void WriteIt (string s)
        {
            tw.WriteLine (s);
        }
    }

I am showing you a very simple code which has all the details removed, and objects are simplified. Imagine, it is a code base of hundreds of files, Process and WriteResponse is in different files and part of different complex object. So what is the problem with the above code. Here are couple of problems I see:

While looking at Process, I am scratching my head, thinking what the hell is writer? Is it a text writer, memory writer or a sand writer (a writer which writes on sand). Remember, this is simplified version, it can be named foo in real code, and you have no clue what is foo? and there is not one object but bunch more object are passed to this anonymous function in real code, and you wonder about all other parameters too.

Second, when you reach to WriteResponse function, somewhere deep in the guts you find writeAction, and then you wonder hah! what writeAction do? You cannot search it as it has come to this function as a delegate. After realizing that, you go back to Process, and you see that it is calling WriteIt on the writer. So, what exactly is writer and then you go back to WriteResponse method again. After couple of jumping back and forth you understand what the hell is happening here.

I will say this is abusing lambda and delegate. Please don’t do it. Write a clever code, appreciate it, show it to your friend, but don’t check it in.

Here is a simplified version of above code:


namespace LaLaLambda
{
    class Program
    {
        static void Main(string[] args)
        {
            Process();
        }

       static void Process()
        {
            WriteResponse("write this line");
        }

        static void WriteResponse(string val)
        {
            using (TextWriter writer = File.CreateText("C:\\temp\\test.txt"))
            {
                MessageWriter mw = new MessageWriter(writer);
                mw.WriteIt (val);
            }
        }
    }

    class MessageWriter {

        TextWriter tw;

        public MessageWriter (TextWriter t){
            tw = t;
        }
        public void WriteIt (string s)
        {
            tw.WriteLine (s);
        }
     }

Above code has all the context together. It is simple, anyone can understand it. You look at it, and immediately you understand it, your eyes will not even wonder up and down.

I know, many of you will be starting your flame thrower to throw many examples at me where we need this kind of code where anonymous calling anonymous and taking a delegate as parameter and they all are tangled together like snakes. Yes, there are legitimate use cases, and use it when you cannot simplify it. For example


  static void  Process (){
            WriteResponse(
                (writer) =>
                {
                   //lot of complicated logic is happening here, for example you are checking writer and depending on it's type you are changing the further logic
                }
             );
        }

You can have different flavor of Process with almost similar construct. Different anonymous can keep the structure of code same but adding a new behavior only in certain cases. A good example of Open/close pattern. The existing code written is not changed, it is closed for modification but using lambda you can extend certain behavior of it.

In last, Write code as Hemingway wrote his stories. keep it simple!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s