What the Authors of “Hello, World!” Don’t Tell You About
Web DevelopmentAs a rule, the adherents of The-very-best-language write their promotional mini-programs something like this:
ageOfBob = 0
ageOfMary = 0
print("Input Bob's age: ")
read(ageOfBob)
print("Input Marry's age: ")
read(ageOfMary)
// Do the math
if (ageOfBob > ageOfMary)
print("Bob is older than Mary by ", ageOfBob - ageOfMary, " years")
else if (ageOfBob < ageOfMary)
print("Mary is older than Bob by ", ageOfMary - ageOfBob, " years")
else
print("Mary and Bob are of the same age")
It’s assumed that a newcomer will like another simplified version of the C-like syntax with automatic type conversion, without unnecessary semicolons, with simple names of standard functions, and so on.
If the newcomer becomes really interested in The-very-best-language, it will be too late to retreat by the moment he has to write real programs in accordance with the recommendations for writing safe code for serious clients or serious employer:
const MAX_PERSON_AGE = 120
const MIN_PERSON_AGE = 1
int getAge(string name) {
age = 0
print("Input ", name, "'s age: ")
read(age)
if (age < MIN_PERSON_AGE or age > MAX_PERSON_AGE)
throw IncorrectAgeInputException
else
return age
}
try {
ageOfBob = getAge("Bob")
ageOfMary = getAge("Mary")
} catch (IncorrectAgeInputException) {
print("You're doing it wrong!")
}
// Do the math
...
So, four stings of code turned into a definition of a few constants (since magic numbers in code is bad) and a function (see DRY) that throws an exception. If we also remember that the getAge
function should be covered with at least a pair of unit tests…that’s a separate story.
In practice, such a simple example is easily generalized to a wide class of problems related to processing of the external input, when the program receives obviously unknown values that can be anything.
Now, let’s see how features of strict typing can help us in solving this task.
We’ll rewrite our program in Ada. Since 1983, Ada has had the feature “if it compiles, it works” that is now part of what Haskell and Rust are promoting. In addition, programs in Ada compile in the native code and can also run on microcontrollers in real time, not much inferior to the C language in performance. Anyway, let’s focus…
with ada.text_io, ada.integer_text_io, ada.io_exceptions;
use ada.text_io;
procedure main is
type Age is range 1 .. 120;
package io is new ada.text_io.integer_io(num => Age);
ageOfBob, ageOfMary : Age;
begin
put_line("Input Bob's age: ");
io.get(ageOfBob);
put_line("Input Mary's age: ");
io.get(ageOfMary);
-- Do the math
if ageOfBob > ageOfMary then
put_line("Bob is older than Mary by" & Age'Image(ageOfBob - ageOfMary) & " years");
elsif ageOfBob < ageOfMary then
put_line("Mary is older than Bob by" & Age'Image(ageOfMary - ageOfBob) & " years");
elsif ageOfBob = ageOfMary then
put_line("Mary and Bob are of the same age");
end if;
exception
when ada.io_exceptions.Data_Error =>
put_line("You're doing it wrong!");
when others => null;
end main;
Compared to the simplest first version of the program, we only added a new type Age
with an explicitly defined range of values:
type Age is range 1 .. 120;
We also used the ada.text_io.integer_io
package, which was parameterized of that type:
package io is new ada.text_io.integer_io(num => Age);
Now, when calling io.get(ageVar)
function, in which ageVar
is a variable of type Age
, the number entered by the user will be checked. In case it does not correspond to its type Age
the Data_Error
exception will be generated.
It can often be heard that Ada is a complicated, verbose and difficult to learn language. I’ve provided an example of how “simple” at the first glance languages just shift some work to the programmer, while “difficult” languages, that might require more time on learning all of their features, allow us to save time on debugging and tests in actual development .
Comments