[comp.object] Readability of C/C++ vs. Readability of Ada

plyon@emx.utexas.edu (Paul Lyon) (04/20/91)

This is my entry in response to Showalter's challenge. Though it does
the reverse computation from Showalter's ADA function, it seems to
me to be appropriate in light of the topic of this thread, since it
is, in fact, production code. It is also written in C not C++; in as
much as the complaint about the latter is it's being an extension of
the former, that should not count against it in the present context.

A couple of remarks about the source are in order: the first two bits 
come from the declaration section at the head of the programme from 
which conv_julian_date() was taken. It will be observed that
no data validation is done in conv_julian_date(); there was another
function in the programme that did that. This one would not be
called if the year or day values were out of range or missing.

The amount of comments may be deemed excessive; I do tend to get
carried away a bit in writing them :-) I will leave it to the
judgment of those who have been following this thread whether
this code is less perspicuous than that given by Showalter.

/*****************************************************************************
*                                                                            *
*   Various mnemonics used for testing character values and setting          *
*   character values in the program.                                         *
*                                                                            *
*****************************************************************************/

#define  NUL    '\x00'
#define  LF     '\x0A'
#define  SPACE  '\x20'
#define  HYPHEN  '-'

/*****************************************************************************
*                                                                            *
*   The following array is used in converting julian dates to standard       *
*   dates in the conv_julian_date() function. The first row of the array     *
*   gives the number of days in each month of an ordinary year, and the      *
*   second row gives the number of days in each month of a leap year.        *
*   The mnemonics are used in the function to reference the appropriate      *
*   row of the array.                                                        *
*                                                                            *
*****************************************************************************/

int day_table[2][13] = 
{
   { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
   { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },

};

#define ORD_YEAR  0
#define LEAP_YEAR 1


/*****************************************************************************
*                           S E C T I O N  0 1 0                             *
*                       conv_julian_date() function                          *
*                                                                            *
*   Date Written : 24 July, 1988                                             *
*   Date Changed : 30 July, 1988                                             *
*                                                                            *
*   Author : Paul Lyon                                                       *
*                                                                            *
*   Description : this function takes a date in JULIAN form, namely          *
*                 "YYDDD" where "DDD" is the number of days since the        *
*                 first of the year, and converts the day value into the     *
*                 correct month and number of days into that month.          *
*                                                                            *
*   Remark : the routine for converting a day of the year into a month       *
*            and a day of the month has been borrowed (with                  *
*            modifications) from Kernighan & Ritchie, Chapter 5, Section     *
*            7. The idea is this. We compare the number of days to the       *
*            number of days for the month (as recorded in the appropriate    *
*            row of the day_table array defined in the declarations          *
*            section above). So long as the number of days is greater we     *
*            subtract off the number of days for that month and repeat       *
*            the comparison for the next month. Once the number of days      *
*            as reduced so far is less than or equal to the number of        *
*            days for the current month value, then the two values will      *
*            now give the correct month and day of the month. Example:       *
*            ordinary year, days of the year == 73. First comparison: 73     *
*            > 0, so subtract 0 from the number of days and set the          *
*            month = 1, and compare again. Second comparison: 73 > 31,       *
*            so subtract 31 from the number of days and set month = 2.       *
*            Third comparison: 42 > 28, so subtract 28 from the number       *
*            of days and set month = 3. Fourth comparison: 14 < 31, so       *
*            quit. The month is 3 (March), and the day of the month is       *
*            14.                                                             *
*                                                                            *
*   Parameters : - pointer to input field (5 characters).                    *
*                - pointer to output buffer for the month (2 digits).        *
*                - pointer to output buffer for the days (2 digits).         *
*                                                                            *
*   Returns : none.                                                          *
*                                                                            *
*****************************************************************************/

conv_julian_date( input_field, month_buf, days_buf )
char *input_field;
char *month_buf;
char *days_buf;
{
   char conv_buffer[4];

   char *field_start;

   int k,
       years,
       month,
       days,
       month_days,
       year_type;

   conv_buffer[0] = *input_field++;
   conv_buffer[1] = *input_field++;
   conv_buffer[2] = NUL;
   years = atoi( conv_buffer ) + 1900;

   conv_buffer[0] = *input_field++;
   conv_buffer[1] = *input_field++;
   conv_buffer[2] = *input_field;
   conv_buffer[3] = NUL;
   days = atoi( conv_buffer );

   if ( years % 4 == 0 && ( years % 100 != 0 || years % 400 == 0 ) )
      year_type = LEAP_YEAR;
   else
      year_type = ORD_YEAR;

   month = 0;
   month_days = day_table[year_type][month];

   while ( days > month_days && month < 13 )
   {
      days -= month_days;
      month++;
      month_days = day_table[year_type][month];
   }

   sprintf( month_buf, "%2.2d", month );
   sprintf( days_buf, "%2.2d", days );
}

kers@hplb.hpl.hp.com (Chris Dollin) (04/25/91)

Jim Showalter writes:

   [Quotes someone; sorry, no attribution]
   >It would be foolish to program for the reading level of the novice
   >programmer
   [Jim says]
   Not really. The vast majority of work on software that goes on (like,
   about 70%) is MAINTENANCE. This is often performed by underpaid,
   underskilled, and overwhelmed junior programmers ...

[Now it's me] Perhaps that's true. Perhaps we ought to treat maintenance as a
skilled job, not a trial-by-ordeal for aspiring programmers (or software
engineers. or whatever.)

Still, once the product is out the door, who cares?

[Just in case; the latter is not my opinion, nor Hewlett-Packard's.]

--

Regards, Kers.      | "You're better off  not dreaming of  the things to come;
Caravan:            | Dreams  are always ending  far too soon."

jimad@microsoft.UUCP (Jim ADCOCK) (04/30/91)

|Jim Showalter writes:
|   Not really. The vast majority of work on software that goes on (like,
|   about 70%) is MAINTENANCE. This is often performed by underpaid,
|   underskilled, and overwhelmed junior programmers ...

Seems to me this is like arguing that since the trim panels keep falling
off of American cars, we ought attach them using big slotted screws, so that
when they *do* fall off anyone with a big slotted screw driver can fix them.

lerman@stpstn.UUCP (Ken Lerman) (05/09/91)

In article <72084@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
[...]
>Seems to me this is like arguing that since the trim panels keep falling
>off of American cars, we ought attach them using big slotted screws, so that
>when they *do* fall off anyone with a big slotted screw driver can fix them.

Half the trim on cars performs no useful function anyway.  Just get
rid of it.  Do the same with trim on programs.

Ken

david@ap542.uucp (05/17/91)

jimad@microsoft.UUCP (Jim ADCOCK) writes:
>|Jim Showalter writes:
>|   Not really. The vast majority of work on software that goes on (like,
>|   about 70%) is MAINTENANCE. This is often performed by underpaid,
>|   underskilled, and overwhelmed junior programmers ...
>
>Seems to me this is like arguing that since the trim panels keep falling
>off of American cars, we ought attach them using big slotted screws, so that
>when they *do* fall off anyone with a big slotted screw driver can fix them.

Yes, exactly.  Cars with nicely tailored but impossible to fix features
like some trim panels are specifically meant to fall apart and be thrown
away so people buy new cars rather than fix their old cars.  This is
intentional, "planned obsolescence" and all that.  Otherwise the car
manufacturers would have stopped building any cars a long time ago.

Software SHOULD be written to be maintained, not simply developed.  APL,
the best example of a write-only-language I know of, is really a WONDERFUL
language for capturing everything you are thinking about right now.  But
if you are trying to solve a problem which takes many people to think about
for a long time, then it is useless - you simply can't tell what the hell
you did last week!

Many languages, and I think C++ or poorly written C are two good examples,
are easy to write and deal with for VERY GOOD programmers, and simply
impossible for the "underskilled and overwhelmed junior programmers" who
end up maintaining and enhancing to software.

You must think about the poor slobs who come after.  I sure as hell
don't want to spend my life maintaining something I developed.  I
would much rather make it so simple, so easy to understand, that
ANYBODY can figure out what I did.  So they don't ask me silly
questions.

**========================================================================**
David E. Smyth
david%ap542@ztivax.siemens.com	<- I can get your mail, but our mailer
				   is broken.  But I can post.  You figure...
**========================================================================**

ab46+@andrew.cmu.edu (Andrew F. Boardman) (05/17/91)

>Many languages, and I think C++ or poorly written C are two good examples,
>are easy to write and deal with for VERY GOOD programmers, and simply
>impossible for the "underskilled and overwhelmed junior programmers" who
>end up maintaining and enhancing to software.

	I would have to disagree with saying C++ is hard to maintain.
I would argue, in fact, that C++ is easier to maintain than a lot of C
code (especially well written C++ code), because of the OO nature of
the design.  I'm talking about C++ code that's written with C++ in
mind (i.e. 99% of the code is in the data structures, etc).

	If C++ code is modularized correctly, even in the biggest
projects the worst a maintainer would have to do is re-write an
object.  The OOP nature also makes debugging a lot easier.

	In the project I'm currently working on, one of the biggest
things I'm keeping in mind is getting it modularized to the extent
that even if almost all the sections of the program are changed
around, the interface between the different objects would stay
consistent.  This means very maintainable code, and very powerful
flexibility.



					--Andrew

Andrew F. Boardman :  ab46@andrew.cmu.edu
Carnegie-Mellon University - Graduate School of Industrial Administration
Raving Mad Lunatic Individualist, but Generally Nice

rockwell@socrates.umd.edu (Raul Rockwell) (05/17/91)

David E. Smyth:
   Software SHOULD be written to be maintained, not simply developed.
   APL, the best example of a write-only-language I know of, is really
   a WONDERFUL language for capturing everything you are thinking
   about right now.  But if you are trying to solve a problem which
   takes many people to think about for a long time, then it is
   useless - you simply can't tell what the hell you did last week!

Interesting idea, but total nonsense.

I work in an APL shop -- we've got 6 people presently coding in APL (7
if you include the vp), mega-bytes of code (and gigabytes of data).
Some of the code is 10 years old, some of it written by long departed
programmers.  Some of it is buggy, but mostly it runs fine.  We
maintain old code and develop new stuff...

An interesting point is that everybody has systems-analyst
responsibilities.  (The coding work is generally so trivial it isn't
worth hiring somebody to just crank out code.)

The reason APL might be hard to maintain has nothing to do with the
language, but the representation.  Since the APL character set was not
included in ASCII, most programmer tools do not work with APL (can you
imagine programming without your favorite editor, without grep,
etc.?).

Of course, there are ways to work around all these problems (many
utilities can be written trivially in APL, there are APL dialects
which use ASCII, and X-windows supports the APL character set (and the
kitchen sink, but that's another story)).

obligatory object oriented stuff: APL (especially the newer dialects)
treats encapsulization very nicely, but does not provide a user class
structure (you can invent classes, but the primitives will treat them
as raw data-structures).  Part of the problem is that APL is
essentially a functional language -- does anyone know of a way of
implementing object classes using a functional notation?  (no side
effects)  It seems like this ought to be possible, but every
implementation I think of gets really messy when I get into the
details of   A f B   where f is some function (addition, array
declaration, whatever) and A and B are different user defined classes.

Raul Rockwell