Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / .NET

COBOL for .NET: Better than C# at Conveying Programmer Intent

0.00/5 (No votes)
23 Dec 2009CC (ASA 2.5)3 min read 9.5K  
COBOL for .NET

Recently, there have been some discussions of COBOL for .NET which have been very ill informed. Here, I hope to indicate how far COBOL has evolved and how it continues to be an excellent language for conveying programmer intent - especially for business paradigm programs.

It is very easy to pick a nasty, poorly written bit of COBOL.net and say that this is worse than the equivalent C#. What has one proved by doing so? Any language can be written badly. So, what I want to do here is discuss what COBOL was created for and how the best modern dialect of COBOL (yes - I do work for Micro Focus) has taken those original ideas and brought them firmly into the 21st century.

One of the key ideas behind COBOL over the last 50 years has been to make the COBOL clearly show the intent of the programmer. Whilst the original idea that a non programmer could understand the code has not proven possible, the underlying concept of readability is still very important. Code which is going to have a long life time needs to be easy to understand. languages which have a highly terse and symbolic syntax suffer from being hard to maintain, a famous example being PERL which is often referred to as a write once, read never language. I must point out that even PERL can be written well, just as COBOL can be written badly. The issue is how a language lends itself to being easy to read.

99 bottles is an example of a nice programming challenge which is quite business like. The idea is to write a program which displays the words to the song 99 Bottle Of Beer (I also like bubbly - hence the picture). Native (unmanaged) COBOL can do this but the code is a little complex looking when compared to more modern languages like C#. If you are interested in this - check out the 99 bottles of beer website.

By using .NET types, Micro Focus COBOL for .NET makes a very clean language for implementing this programming challenge. When I wrote the code below, I wanted to make something which was very easy to read, relatively concise (but not at the expense of readability) and which re-used the lyrics of the song rather than just having the different version of the lyrics repeated in the code. For example, it replaces "bottles" with "bottle" rather than having a special copy of the entire line "1 bottle of beer..."

     $set sourceformat(free)
01 bottles         binary-long.
01 bottle-word     string.
01 count-word      string.

perform  varying bottles from 99 by -1 until count-word equals "No"
   evaluate bottles
       when 0
           move "No"      to count-word
           move "bottles" to bottle-word
       when 1
           move bottles   to count-word
           move "bottle"  to bottle-word
       when 2 thru 99
           move bottles   to count-word
           move "bottles" to bottle-word
   end-evaluate
  
   if bottles not equals 99 then
       display "Take one down and pass it around, " count-word::"ToLower"()
               " more " bottle-word " of beer on the wall."
   end-if
              
   display count-word " " bottle-word
       " of beer on the wall, " count-word::"ToLower"()
       " " bottle-word " of beer."
      
end-perform
display "Go to the store and buy some more, 99 bottles of beer on the wall."

Beauty is in the eye of the beholder and if you are used to the 'curlies' of C#, then the COBOL might look a bit wordy. However, I think it would be very hard indeed to claim it is a 'code horror'; the above clearly shows the intent of the programmer and is transparent in function. Further, it has very little unnecessary syntactic baggage. Whilst it is a COBOL program, please also note how it makes use of the .NET Framework using OO syntax to invoke the ToLower() method on the String class.

Here is the direct translation into C#. As 99 bottles is firmly in the paradigm for which COBOL is designed, it should not shock us that the C# version is actually longer than the COBOL. However, I suspect that this simple revelation will shock some people!

C#
using System;

namespace ConsoleApplication11
{
   class Program
   {

       static void Main(string[] args)
       {
           Program p = new Program();
           p.sing();
       }

       public void sing()
       {
           int bottles;
           string bottleWord = "";
           string countWord  = "" ;
           for (bottles = 99; countWord != "No"; --bottles)
           {
               switch(bottles)
               {
                   case 0:
                       countWord = "No";
                       bottleWord = "Bottles";
                       break;
                   case 1:
                       countWord = bottles.ToString();
                       bottleWord = "Bottle";
                       break;
                   default:
                       countWord = bottles.ToString();
                       bottleWord = "Bottles";
                       break;
               }

               if (bottles != 99)
               {
                   Console.WriteLine("Take one down and pass it around, " + countWord.ToLower() +
                       " more " + bottleWord + " of beer on the wall.");
               }
               Console.WriteLine(countWord + " " + bottleWord + " of beer on the wall, " +
                   countWord.ToLower() + " " + bottleWord + " of beer.");
           }
       }
   }
}

Will this make people suddenly switch from C# to COBOL? I doubt it; however, it does show that people who discount COBOL for .NET as a silly idea really do not understand what they are talking about.

A Final Point

My COBOL was written for clarity. To make it run at greater efficiency, one should use this version which Robbert Sales tweaked.

     $set sourceformat(free)
01 bottles         binary-long.
01 bottle-word     string.
01 count-word      string.

move "bottles" to bottle-word
perform  varying bottles from 99 by -1 until bottles < 0
    if bottles = 0
        move "No" to count-word
    else
        move bottles to count-word
    end-if
    if bottles = 1
        move "bottle"  to bottle-word
    else
        move "bottles"  to bottle-word
    end-if
    if bottles not equals 99 then
        display "Take one down and pass it around, " count-word::"ToLower"()
                " more " bottle-word " of beer on the wall."
    end-if

    display count-word " " bottle-word
        " of beer on the wall, " count-word::"ToLower"()
        " " bottle-word " of beer."

end-perform
display "Go to the store and buy some more, 99 bottles of beer on the wall."

Also posted at:

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License