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!
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: CodeProject