Gigi Labs

Please follow Gigi Labs for the latest articles.
Showing posts with label loops. Show all posts
Showing posts with label loops. Show all posts

Wednesday, September 25, 2013

Best Practices: To Always Use Braces for Conditionals and Loops... or not

Hi everyone! :)

While following a number of Pluralsight courses by Jesse Liberty (which I highly recommend), I was reminded of the long-running debate about whether one should always use braces when control flow statements (conditionals and loops) are involved. Jesse Liberty is one of many who suggest always using braces. So let's say we have the following conditional:

            if (x == 0)
                Console.WriteLine("x is zero");
            else if (x < 0)
                Console.WriteLine("x is negative");
            else if (x > 0)
                Console.WriteLine("x is positive");

The proponents of the always-use-braces camp would have us write them like this:

            if (x == 0)
            {
                Console.WriteLine("x is zero");
            }
            else if (x < 0)
            {
                Console.WriteLine("x is negative");
            }
            else if (x > 0)
            {
                Console.WriteLine("x is positive");
            }

In this article, I'm going to discuss the advantages and disadvantages of this approach, as well as my personal opinion based on my experience. I want to say from the beginning that this article is subjective and not completely factual or objective - so take it for what it is. There is no general consensus on this matter precisely because it is a matter of personal taste.

Brace styles


Braces (or curly brackets) are a feature in just about any programming language that uses the C-style syntax, including C, C++, Java, C#, JavaScript, PHP, and many others. They define a scoped block that can be executed as a single statement as part of control flow (conditionals and loops). There are many different styles in which they can be used.

The Java folks seem to like this kind of style:

            if (x == 0) {
                Console.WriteLine("x is zero");
            }

The .NET camp, on the other hand, seems to prefer aligning braces vertically:

            if (x == 0)
            {
                Console.WriteLine("x is zero");
            }

If you have just one statement, you can technically leave out the braces, so you can write your code like this:

            if (x == 0)
                Console.WriteLine("x is zero");

...or like this.

             if (x == 0) Console.WriteLine("x is zero");

Personally, I think the first and last options aren't the best in terms of readability (especially when code becomes complex) so I'll focus on the second and third. I normally use the second option (with braces) when I have multiple statemenents, and the third option (no braces) when I have just one. Many people recommend always using braces, and dismiss the third option as bad practice. Let's take a look at the reasons why.

If you need to add statements, you'll find the braces ready


So let's take the same example as before, where you have this statement:

             if (x == 0)
                Console.WriteLine("x is zero");

If you need to add additional statements to be executed as part of the conditional, the braces will have to be added anyway. Some people recommend always using braces so that you'll find them ready when you need to add additional statements.

In that case, I suppose, we shouldn't use empty element syntax in XML:

<RowDefinition Height="30" />

...and instead always write our tags in full:

<RowDefinition Height="30"></RowDefinition>

...simply because we might need to add something inside the element at some point. I think this is a very weak argument, because it disregards a language feature that may be very convenient, and at the same time bloats code with something that adds no meaning to the code. Take a look at the first two code snippets in this article - the one that uses braces is twice as long (in terms of lines) as the other one. And for what? Because people are too lazy to type in the braces when they are eventually needed? Wat.

Adding statements can be error-prone


Another reason why omitting braces is considered bad practice is that it may be easy to introduce logical errors when maintaining such code (see this question on Programmers StackExchange and this other one on Stack Overflow). Let's say you have this:

            if (x == 0)
                Console.WriteLine("x is zero");

Then, you add an additional statement intended to be within the conditional, and you do it like this:

             if (x == 0)
                Console.WriteLine("x is zero");
                Console.WriteLine(" which means it's neither positive nor negative");

Oops! The second Console.WriteLine() isn't actually part of the conditional, so it always gets executed, no matter what. This is a valid argument. But let's dissect it a little further.

First, let's start again from our simple single-line conditional:

             if (x == 0)
                Console.WriteLine("x is zero");

Now, if you want to add code at this point, you have two courses of action. If you want to add statements as part of the conditional, you know that there's just one statement and no braces, so adding them should be a pretty automatic response:

            if (x == 0)
            {
                Console.WriteLine("x is zero");
                Console.WriteLine(" which means it's neither positive nor negative");
            }

On the other hand, if you want to add a statement that is not a part of the conditional, you add it at the same level as the if statement:

            if (x == 0)
                Console.WriteLine("x is zero");
            Console.WriteLine(" which means it's neither positive nor negative");

Even in absence of braces, the indentation shows clearly that one statement belongs to the conditional and the other does not. So actually, when seeing this kind of code:

             if (x == 0)
                Console.WriteLine("x is zero");
                Console.WriteLine(" which means it's neither positive nor negative");

...I can't help but think that the readability problem (which results in incorrect control flow) is one of indentation, not of whether to use braces or not.

I can certainly imagine beginning programmers making this kind of mistake, but I find it hard to believe that more seasoned programmers find it hard to read basic conditionals. As one of the answers to this question states:

"I even find it implausible that this should be a common mistake: blocks are a fundamental part of programming. Block level resolution and scoping is an automatic, ingrained mental process for programmers. The brain just does it (otherwise, reasoning about programming would be much harder). There is no additional mental effort required to remember putting the braces: the programmer also remembers to indent the newly added statement correctly, after all; so the programmer has already mentally processed that a block is involved." -- Konrad Rudolph

Also, one of the sections in this article states that:

"Programmers with enough discipline to always notice the braces (and put them in when needed) don't need this idiom [always using braces].
"Auto-indent editors make it obvious whether your new statement is part of the else clause, making it unlikely you'll have the bug this idiom tries to prevent."

Summary


Personally, I think that using braces when they aren't necessary is a waste of space, resulting in a lot of unnecessary lines of code. I use them when needed, and don't use them for single statements. I find nothing wrong with omitting braces when they aren't needed. This has worked for me for many years, and you may or may not agree wtih me. Different people find themselves comfortable using different approaches, and there is no general consensus on what is best.

So find out what works best for you, and don't let anyone tell you how you should write your code based on subjective arguments. While you should definitely learn from more experienced programmers and best practices based on rational and logical arguments, be practical and don't get too religious about your code.

Monday, May 13, 2013

C# Basics: Command Interpreter Using Methods

Hello! :)

Today we're going to write a program similar to the Windows command prompt, Linux shell, or DOS. It's just a program that accepts commands from the user, and if it recognises the commands, it does something particular. We'll use this program to learn how to use methods, but we'll also learn a few other things as we go along. This article is admittedly longer than usual; rather that split it into two parts, I'm simply not going to post anything new tomorrow, so you can read this over two days if you like.

Let's start with this code:


            while (true)
            {
                String command = Console.ReadLine();

                if (command == "exit")
                    break;
            }

Here, we're accepting a line of text from the user and storing it in the String variable command. Instead of keeping a boolean variable to determine when to quit the loop, as in "C#: ASCII Art Game (Part 1)", we just loop forever (since the while condition is always true). When an "exit" command is received, the break statement allows us to break out of the loop anyway. Try that now.

Next, we add a little spice to our program. First, we set the console title:

            Console.Title = "Command Interpreter";

...and then, we make the user's input show up in white, by replacing the line containing Console.ReadLine() as follows:

                Console.ForegroundColor = ConsoleColor.White;
                String command = Console.ReadLine();
                Console.ResetColor();

Now, let's test what we have so far, by supporting an "echo" command. An "echo" command simply returns whatever you write after it. For example, if you write:

echo I can has cheezburger

...then you'd get:

I can has cheezburger

The only problem here is that we need to separate the command ("echo") from the parameters ("I can has cheezburger"). One way to do this is to break the command string into an array of individual words, as follows:

                String[] words = command.Split();

The command itself is now stored in words[0], while the parameters (if they exist) are in words[1] onwards. Finally, let's change the part where the "exit" command is being handled, and change it into a switch statement. The full code so far should look like this:

            Console.Title = "Command Interpreter";

            while (true)
            {
                Console.ForegroundColor = ConsoleColor.White;
                String command = Console.ReadLine();
                Console.ResetColor();

                String[] words = command.Split();

                switch (words[0])
                {
                    case "exit":
                        return;
                    case "echo":
                        for (int i = 1; i < words.Length; i++)
                        {
                            if (i > 1)
                                Console.Write(' ');
                            Console.Write(words[i]);
                        }
                        Console.WriteLine();
                        break;
                }
            }



For the "echo" command, we used a technique similar to that used in yesterday's article, "C# Basics: Morse Code Converter Using Dictionaries". You'll notice that the break statement used by the exit command has been changed to a return statement. That's because break has a different meaning when used in a switch statement, so we can't really use it there. Instead, return allows us to leave the Main() method completely. We can now test the program:


You'll notice that the code in the Main() method is beginning to grow, and will continue growing as we add more commands. We can organise our code by using methods. Methods are also called functions or subroutines in other languages, or even prodecures if they don't return anything. Take the following code:

                Console.ForegroundColor = ConsoleColor.White;
                String command = Console.ReadLine();
                Console.ResetColor();


...and move it into a new method outside Main(), as follows:

        static String ReceiveInput()
        {
            Console.ForegroundColor = ConsoleColor.White;
            String command = Console.ReadLine();
            Console.ResetColor();
            return command;
        }


This functionality is now defined in this method called ReceiveInput() which returns a String (i.e. it returns the input from the user). In the place where this code originally was, we now need only call this method:

                String command = ReceiveInput();

You'll notice that we now have two command variables declared: one in Main(), and one in ReceiveInput(). That's actually allowed, because they are in different methods. We say they are declared in a different scope.

Now, let's organise the code for the "echo" command in a similar way. Create a new method as follows:

        static void Echo(String[] words)
        {
            for (int i = 1; i < words.Length; i++)
            {
                if (i > 1)
                    Console.Write(' ');
                Console.Write(words[i]);
            }
            Console.WriteLine();
        }

This method has a void return type: that means it doesn't return anything - it just runs the statements within its body. This method is also different from the previous one in that it takes the parameter words. Methods can take any number of parameters in order to receive input data that they will be working with.

The code for the "echo" command can now be simplified as follows:

                    case "echo":
                        Echo(words);
                        break;

If you run the program now, you'll notice it works exactly the same as before.

Now, let's support another command called "total":

        static int Total(String[] words)
        {
            int total = 0;
            try
            {
                for (int i = 1; i < words.Length; i++)
                    total += Convert.ToInt32(words[i]);
            }
            catch (Exception)
            {
                Console.WriteLine("Invalid input");
            }

            return total;
        }

...and...

                    case "total":
                        int total = Total(words);
                        Console.WriteLine(total);
                        break;

The "total" command just calculates the sum of the numbers passed as parameters. Example output:




Finally, let's now support an "average" command:

        static int Average(String[] words)
        {
            int total = Total(words);
            int average = total / (words.Length - 1);
            return average;
        }

...and...

                    case "average":
                        int average = Average(words);
                        Console.WriteLine(average);
                        break;

You'll notice we are using Total() directly to calculate the sum used by the average, instead of repeating the code in Total(). One of the great benefits of methods is that they allow code reuse and eliminate duplicate code - something that plagued my earlier article, "The ASCII Table (C#)". A best practice in programming is the Don't Repeat Yourself (DRY) principle.

Output:


You'll remember from "C# Basics: Arithmetic and Exceptions" that we aren't getting any decimal point in divisions because we are working with integers.

That's it for today! We wrote a little command interpreter, learned how to create our own methods, and learned a lot of new stuff in the process including the break statement, the return statement, and variable scoping. As I wrote earlier, since this was extra long, there will be no article tomorrow!

Here's the full code for today's article:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CsCommandInterpreter
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "Command Interpreter";

            while (true)
            {
                String command = ReceiveInput();

                String[] words = command.Split();

                switch (words[0])
                {
                    case "exit":
                        return;
                    case "echo":
                        Echo(words);
                        break;
                    case "total":
                        int total = Total(words);
                        Console.WriteLine(total);
                        break;
                    case "average":
                        int average = Average(words);
                        Console.WriteLine(average);
                        break;
                }
            }
        }

        static String ReceiveInput()
        {
            Console.ForegroundColor = ConsoleColor.White;
            String command = Console.ReadLine();
            Console.ResetColor();
            return command;
        }

        static void Echo(String[] words)
        {
            for (int i = 1; i < words.Length; i++)
            {
                if (i > 1)
                    Console.Write(' ');
                Console.Write(words[i]);
            }
            Console.WriteLine();
        }

        static int Total(String[] words)
        {
            int total = 0;
            try
            {
                for (int i = 1; i < words.Length; i++)
                    total += Convert.ToInt32(words[i]);
            }
            catch (Exception)
            {
                Console.WriteLine("Invalid input");
            }

            return total;
        }

        static int Average(String[] words)
        {
            int total = Total(words);
            int average = total / (words.Length - 1);
            return average;
        }
    }
}

As an exercise, test the program above and see if you can find any bugs (there are at least two). Solve them.

Come back on Wednesday for the next article! :)

Sunday, May 12, 2013

C# Basics: Morse Code Converter Using Dictionaries

Hi all! :)

Today's article is an easy one. We're going to learn to use dictionaries, and use them to make a program that converts text into the Morse Code equivalent.

Just for a change, today I'm going to use Visual Studio 2010 instead of SharpDevelop. If you want to try it, grab an express edition from Microsoft's website. Otherwise, you can manage just as well with SharpDevelop. Let's start off by creating a new console application. In Visual Studio, you can click on the "New Project..." link below the VS logo, or else from the menu, File -> New -> Project...:


Under Visual C# -> Windows, select "Console Application". As with SharpDevelop, specify a name for the project and where to put it. Note: I'm using the Ultimate edition, so your Express edition will be a little different (e.g. less project types).


The sample code given by Visual Studio is a bit different from that of SharpDevelop:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CsMorse
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}


In particular, there's nothing in Main(). It doesn't matter. However, if you're using SharpDevelop, you're going to need the using System.Collections.Generic; so make sure you add it.

So, now we're going to make a little program based on the Morse Code. In case you don't know, the Morse Code is something that Chuck Norris used to communicate with the aliens who built the pyramids in Egypt. Obviously, he was the one telling them how to construct them.

As you can see from the Wikipedia link in the previous paragraph, each letter of the alphabet has a corresponding representation in Morse as a series of dots and dashes. In order to speed up transmissions, more common characters (e.g. 'E') are much shorter than others.

In C#, we can use a dictionary to map keys (e.g. 'L') to values (e.g. ".-.."). In other programming languages, dictionaries are sometimes called hash tables or maps or associative arrays. The following is an example of a dictionary mapping the first two letters of the alphabet to their Morse equivalents:

            Dictionary<char, String> morse = new Dictionary<char, String>();
            morse.Add('A', ".-");
            morse.Add('B', "-...");

            Console.WriteLine(morse['A']);
            Console.WriteLine(morse['B']);

            Console.WriteLine("Press any key...");
            Console.ReadKey(false);

First, we are declaring a dictionary. A dictionary is a generic type, so we need to tell in the <> part which data types we are storing. In this case, we have a char key and a String value. We can then add various items, supplying the key and value to the Add() method. Finally, we get values just like we would access an array: using the [] syntax. Just that dictionaries aren't restricted to using integers as keys; you can use any data type you like. Note: you'll know from the previous article, "The ASCII Table (C#)", that a character can be directly converted to an integer. Dictionaries work just as well if you use other data types, such as Strings.

Here is the output:


If you try to access a key that doesn't exist, such as morse['C'], you'll get a KeyNotFoundException. You can check whether a key exists using ContainsKey():

            if (morse.ContainsKey('C'))
                Console.WriteLine(morse['C']);

OK. Before we build our Morse converter, you should know that there are several ways of populating a dictionary. One is the Add() method we have seen above. Another is to assign values directly:

            morse['A'] = ".-";
            morse['B'] = "-...";

You can also use collection initialiser syntax to set several values at once:

            Dictionary<char, String> morse = new Dictionary<char, String>()
            {
                {'A' , ".-"},
                {'B' , "-..."}
            };

Since we only need to set the Morse mapping once, I'm going to use this method. Don't forget the semicolon at the end! Replace your current code with the following:

            Dictionary<char, String> morse = new Dictionary<char, String>()
            {
                {'A' , ".-"},
                {'B' , "-..."},
                {'C' , "-.-."},
                {'D' , "-.."},
                {'E' , "."},
                {'F' , "..-."},
                {'G' , "--."},
                {'H' , "...."},
                {'I' , ".."},
                {'J' , ".---"},
                {'K' , "-.-"},
                {'L' , ".-.."},
                {'M' , "--"},
                {'N' , "-."},
                {'O' , "---"},
                {'P' , ".--."},
                {'Q' , "--.-"},
                {'R' , ".-."},
                {'S' , "..."},
                {'T' , "-"},
                {'U' , "..-"},
                {'V' , "...-"},
                {'W' , ".--"},
                {'X' , "-..-"},
                {'Y' , "-.--"},
                {'Z' , "--.."},
                {'0' , "-----"},
                {'1' , ".----"},
                {'2' , "..---"},
                {'3' , "...--"},
                {'4' , "....-"},
                {'5' , "....."},
                {'6' , "-...."},
                {'7' , "--..."},
                {'8' , "---.."},
                {'9' , "----."},
            };

           

            Console.WriteLine("Press any key...");
            Console.ReadKey(false);


In the empty space between the dictionary and the Console.WriteLine(), we can now accept user input and convert it to Morse:

            Console.WriteLine("Write something:");
            String input = Console.ReadLine();
            input = input.ToUpper();

            for (int i = 0; i < input.Length; i++)
            {
                if (i > 0)
                    Console.Write('/');

                char c = input[i];
                if (morse.ContainsKey(c))
                    Console.Write(morse[c]);
            }

            Console.WriteLine();

Here, the user writes something and it is stored in the input variable. We then convert this to uppercase because the keys in our dictionary are uppercase. Then we loop over each character in the input String, and write its Morse equivalent if it exists. We separate different characters in the Morse output by a forward slash (/). Here's the output:


Awesome! :) In this article we used Visual Studio to create a program that converts alphanumeric text into the Morse-encoded equivalent. In the process, we learned to use dictionaries, and also revisited things like for loops and String methods.

Watch this space for more practical articles! In particular, after a few more articles, we'll be doing some network programming. Some great stuff is coming your way. :)