comp.lang.ada
 help / color / mirror / Atom feed
From: "Marin David Condic" <marin.condic.auntie.spam@pacemicro.com>
Subject: Re: Learning Ada (newbie)
Date: Thu, 5 Apr 2001 18:06:07 -0400
Date: 2001-04-05T22:06:09+00:00	[thread overview]
Message-ID: <9aiq8h$ik8$1@nh.pace.co.uk> (raw)
In-Reply-To: z75z6.679803$U46.21074483@news1.sttls1.wa.home.com

Many Kudos. You might just want to spiff this up a little bit and submit it
somewhere as an article. I like the commentary about catching errors early.
You might want to note that catching errors early is not just a matter of
coolness or intellectual tidiness. It translates very directly into $$$$$
saved! (I'm currently doing a *lot* of C programming and getting quite
urinated-off at the lack of checking that makes me have to get code loaded
into the box, executed, exploded and debugged just to discover some kind of
parameter mismatch happened that I could have fixed at compile time & saved
myself the whole development iteration!!!) Money is a pretty strong
incentive for the commercial developer - it just isn't well known that Ada
will, in fact, save you quite a bit of it.

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com
Web:      http://www.mcondic.com/


"Mark Lundquist" <mark@rational.com> wrote in message
news:z75z6.679803$U46.21074483@news1.sttls1.wa.home.com...
>
> Ayende Rahien <Dont@spam.me> wrote in message
> news:9af9ao$6ee$1@taliesin.netcom.net.uk...
>
> > What are the advantages & disadvantages of Ada compare to C or C++
> > and other languages?
>
> OK!  I'd like to take a whack at that question...
>
> "Other languages" of course is pretty broad... :-) so most of my
comparisons
> will be with the "C-class" languages, C/C++/Java (and there are others on
> this group who know Java a lot better than I do, so they can add to what I
> have to say).  Someone like Brian Rogoff  :-) can handle comparing Ada
with
> functional languages like OCAML.   You probably already understand the
> issues involved w/ scripting languages vs. compiled languages, so I'll
leave
> that alone.
>
> I'll give a summary first, then go into more detail in a bit.
>
> The bottom line is: "Done sooner, fewer bugs, less pain".  And over the
> lifecycle of a long-lived project, I think that well-written Ada code is
> more maintainable than well-written code in many other languages (of
course
> it is possible to write crap in any language, and there isn't much point
in
> comparing the crap :-).  This benefit accrues primarily to two factors.
>
> The first factor is the expressive power of Ada, which translates directly
> into better understandability of code written in Ada.  I think a
> programmer who really knows both Ada C++ (for instance) can communicate
> "intent" better in Ada.
>
> The second factor has to do with early detection of programming errors.
Let
> me try to explain this.. :-)  When you make a programming mistake, the
> result is going to fall into one of four categories:
>
>     1) The compiler will reject your code.  Or,
>     2) Your code will compile OK, but when you try to link your program
you
>          will get errors (undefined symbol references).  Or,
>     3) Everything compiles and links OK, but when you run your program it
>         blows up with an unhandled exception.  Or,
>     4) No exception is raised, your program just goes beserk.  This result
>         can range from subtly or occasionally incorrect behavior or
results,
> to fatal
>         errors (e.g."segmentation fault"), to system hangs, to destructive
> crashes.
>
> Compile-time errors are generally the easiest thing to figure out.  If I
> make a mistake that results in one of these errors, it could be that I
just
> made a simple mistake that violated one of the language definition rules.
> In that case, I just figure out what rule I broke and fix the code.  Other
> times, the violation of a language rule points to some underlying logic
> error or design error.  Now I have to step back and do some redesign, but
> then I'm glad that at least my error was one that could be caught at
compile
> time instead of later, because later means more head-scratching and
farting
> around to figure out what the problem was.
>
> A robust, programmer-friendly language would be consciously designed to
> "shift" the manifestation of errors along the scale toward the
> "compile-time" category and away from "unbounded run-time" category.  This
> is just what Ada is designed to do.
>
> The designers of Ada tried to eliminate as much nonsense as possible at
> compile time.  For instance, an Ada "function" is analogous to a
> non-void-returning function in C (the analog of a void-returning function
is
> an Ada "procedure").  Now, if you write an Ada function with no "return"
> statement, the compiler will reject it because this is not legal Ada.  But
> in C, it's perfectly legal for a non-void-returning function not to have a
> return statement.  The result of this at run-time is that the caller
simply
> takes as the return value whatever happens to be in the return-value
> register.  Don't miss the fact that this behavior is in fact the *meaning*
> of that formulation in C.  Now how likely is it that the programmer
intended
> this meaning?  Fat chance... How likely is it that he/she just forgot to
> write the return statement, or deleted it inadvertently?  Pretty likely.
> Now consider that the resulting error may not appear until well after the
> product has been released to the user community.
>
> That's just one example out of many.  Another is Ada's "case" statement,
> compared to the fall-through semantics of C's "switch" statement.  And
it's
> well-known that  in C, a simple typo of "=" in place of "==" (or
> vice-versa) can escalate right up to an unbounded run-time error.  From
the
> syntax level all the way up, Ada was consistently designed to catch these
> kinds of errors at compile time, and it does this without imposing burdens
> on the programmer.
>
> Link-time errors are more of a pain than compile-time errors.  The
compiler
> has all kinds of information that the linker can't see, so a compiler is
> able to give error messages with a lot more specifics about what went
wrong.
> All a linker can say is "I couldn't resolve symbol X", and then it's up to
> me to figure out what I did wrong.  In Ada, linker errors are virtually
> unknown.  The only times you ever get a linker error are due to (a)
linking
> against modules written in other languages; (b) linking against object
> module archives (which is legitimate, but outside the scope of what is
> defined by the Ada language, or (c) a bug in the Ada language
> implementation (compilation system or whatever).  You never get a link
error
> when linking an ordinary, self-contained Ada program.
>
> Once you get into run-time errors, it's a whole different ball game.  A
lot
> of times, finding the problem means debugging, which is more or less pain
> depending on the nature of the program and the nature of the error.  For a
> simple, small program, it's not bad.  For a large system that's heavily
> state-dependent and timing-sensitive, debugging can be next to impossible,
> i.e., doing it is going to require a serious investment in time and
> creativity.
>
> The "exception" error mode is preferable because (a) it gives you a good
> hint of where to start when debugging or otherwise investigating the
> problem, and (b) it represents a boundedness on the error behavior of the
> program; that is, the error is being "caught" at some point by the program
> itself rather than going on to wreak more havoc.  The program may have no
> better way to deal with the exception than to terminate, but in that case
> this is still better than not having raised an exception at all.  When an
> error isn't caught by a run-time check, often the result is a
chain-reaction
> of cascading error effects in the program, and it's not uncommon to begin
> investigating by debugging a second- or third-order downstream effect of
the
> error (for example, the error causes corrupted data which is later read
and
> causes the observable incorrect behavior).
>
> Obviously, in C all run-time errors fall into the last category (unbounded
> run-time error), since C doesn't have exceptions.  C++ has few run-time
> checks (bad_cast, bad_typeid) that throw exceptions, so unhandled
exceptions
> usually originate with an explicit "throw" in the program rather than a
> language-defined check.  Java defines a few more run-time checks (such as
> the array vounds check), but not as many as Ada.  Ada defines a large
number
> of run-time checks that raise exceptions, which would otherwise result in
> unbounded errors.  Better yet, Ada's language rules are constructed in
such
> a way that the compilers can often optimize away a suprising number of the
> language-defined checks.  Java doesn't have this ability to the same
extent.
> (It's often asked, "Don't the run-time checks carry a lot of run-time
> overhead?"  The answer is, first of all: "Not as much as you might think",
> but more importantly, Ada gives you the choice.  All the run-time checks
can
> be suppressed, either through pragmas in the source code or compilation
> options.  So you get to decide the cost-benefit tradeoff as you see fit).
>
>
> Blow-by-blow, here are the technical aspects I see contributing to the
> factors of "expressive power" and/or "early error detection".
>
> 1) I think one of the coolest things about Ada is its 'package' construct.
> Packages represent the programming concept of a "module" and are
absolutely
> fundamental in Ada.  The package construct unifies, very cleanly and
> elegantly, three important concepts: (1) encapsulation (which is about
> privacy, i.e. hiding an abstraction's representation from its clients),
(2)
> separation of interface and implementation, and (3) namespace control.
> Every package has a construct called a "specification" (the interface),
and
> most packages, depending on the contents of the specification, also
require
> a "body" (the implementation).  The idea of separation of interface and
> implementation calls for more than just textual separation, it implies a
> "contract" specified by the interface which the implementation is
obligated
> to fulfill.  So in Ada, if the body is incomplete or incorrect with
respect
> to the spec, you get an easy-to-understand compilation error when you try
to
> compile the body.  If you do not provide a body for a package that
requires
> one, then you'll get a prelinker error when you try to link the program
(not
> a linker error complaining that a screenful of symbols is undefined, but a
> clear error message that you are "Missing body for package Foobar" or
> whatever).
>
>    Compare this with C/C++.  The interface is typically given by a ".h"
> header file containing extern declarations, and the implementation is
given
> by a .[cC] file.  But there is no language-defined
correctness/completeness
> relationship between the header file and the implementation file, and the
> identification of either one with a "module" is entirely notional.  If the
> "implementation" doesn't match, the code is still perfectly legal and will
> compile just fine.  The backstop for catching this is the linker, when it
> can't resolve all the symbols.  Moreover, you can only do this if you are
in
> a position to link a main program, which is an annoyance when developing
> libraries or developing components of large software projects.  And it's
> quite easy to violate the interface/implementation contract in ways that
are
> not caught by the linker, so and so will cause a run-time error.  C/C++
has
> three separate mechanisms to handle the three aspects of modularity:
classes
> for encapsulation, namespaces for namespace control, and the .h/.c
> convention to simulate separation of interface and implementation; but the
> three mechanisms don't fit together snugly.  Some other random notes... If
> you want to inline a member function, it must go in the class declaration,
> i.e. the header file (thus violating separation).  The "namespace"
construct
> in C++ also is inferior to the namespace control provided by Ada packages
> (don't have time to go into detail on this).  In C/C++, namespace control
> must largely be implemented through ad-hoc policies that must be manually
> checked and enforced by a human "name czar" (see the book "Large-Scale C++
> Software Design", by John S. Lakos -- it covers high-maintennance
techniques
> for working around this and other problems that don't exist -- at least to
> nowhere the same degree -- in Ada, such as circular compile- and link-time
> dependencies).  Ironically, one gripe against Ada is that it has too many
> rules.  With other languages, instead of  language-definition rules that
> work
> with you to help you express intent, you have to submit to labor-intensive
> project policies if  you want the project to succeed.
>
>    Compare with Java and Eiffel...  In both of these languages, a class's
> interface and implementation are not separated.  Java has a mechanism (the
> "interface" construct) that can be used to simulate this, but that's not
> really what it's meant for.  I think Eiffel also has a construct that can
be
> used to achieve some separation of interface and implementation. But in
both
> cases it would be somewhat onerous to implement a "modularized" design
using
> these features, and the result would be code written in an unnatural style
> for those languages.
>
>    Embracing packages is the "library unit" concept in Ada which allows
for
> true separate compilation of modules while maintaining semantic
> relationships between them.  One result is that the reliance on makefiles
> for codifying compilation dependencies is rendered obsolete; the
compilation
> system can do all the necessary dependency analysis on the fly.
>
>    The bottom line is that since modularity is fundamental to programming,
> it should be primitive in a programming language.
>
> 2) Ada has a powerful type system.  Some have called this "strong typing",
> and strong static type checking is indeed part of it, but not all.  It's
not
> just that the type system is "strong", it's that it's also "rich".  One
> aspect of this is the ability to create user-defined types -- not just
> record types (which are like C/C++ structs and classes), but user-defined
> numeric types which are distinct from each other and the predefined
numeric
> types, user-defined array types (most array types in Ada are named, while
in
> C-class languages they are all anonymous), real enumeration types that are
> not aliases for integers and can be used as array index types (and that
> don't collapse into ints as soon as you get in with a debugger), and more.
> Another aspect of "rich" typing is the very cool concept of "type/subtype"
> (no time to go into this right now, and covered in at least two other
recent
> threads on comp.lang.ada).
>
> The classic example of why you need distinct types even for numbers is
> something like this:
>
>     function Area (Radius : Meters) return Square_Meters;
>
> where the types "Meters" and "Square_Meters" both happen to have the same
> representation (say, a floating-point number), but are clearly not the
same
> type.  If you take something of type Square_Meters and try to pass it as
the
> parameter to Area, you want the language to tell you at compile time.
>
> Packages and the type system head up my short list of technical
advantages.
> A few others:
>
> 3) Generic units, which are similar to C++ templates except that they are
> almost perfectly type-safe and compile-time checkable.  They also
implement
> a programming concept called "constrained genericity", which you can read
> about on the Web or wherever (no time to go into it here).  For some, in
> whose minds Ada went overboard in requiring explicit instantiation of
> generics, Ada generics do not represent the ideal but are still preferable
> to C++ templates.  When you make a coding mistake when working with Ada
> generics, you get brief and informative compile-time error, where the
> comparable mistake in C++ can result in a linker error message that is
truly
> epic in size and whose cryptic syntax renders it virtually unreadable (if
> you've ever used STL, then you know what I'm talking about! :-)
>
> 4) Safe pointers.
>
> 6) A crisp model for inheritance and dynamic polymorphism that is *not*
> based on the idea of a "class".  IMHO, class-oriented languages
> (Simula/Smalltalk/C++/Java etc.) embody an intellectual error in their
> treatment of encapsulation (privacy and primitive operations, a.k.a.
> methods), by making the the "class", which is really a type definition,
also
> the unit of modularity.  The conflation of "module" and "type" in the
notion
> of "class" results in all kinds of distortions: special syntax and sematic
> complexities for various types of constructors (constructors as a
> language-level concept do not exist in Ada, since they are unnecessary
> without classes), the need for a "singleton" idiom, and the need for
> "friend" classes.
>
>    Also, Ada's dispatching model is nice and clean.  Inheritance does not
> imply dispatching, and dispatching is a property of the method invocation,
> not just the method declaration.  And you can dispatch on the return type
of
> a function, not just parameter types.
>
> 7) Limited types.  In C++ if you want to define an abstraction that
retains
> complete control over its own instances, e.g. does not allow clients to
copy
> instances or test for equality, you have to jump through some hoops --
> declaring the abstraction as a class, then declaring private
> equality/inequality operators private and constructors.  In Ada, the idea
of
> a "limited type" is primitive, and you get it by including the single word
> "limited" in the type declaration.
>
> 8) True array types, including constrained and unconstrained array types
and
> multidimensional arrays.  The concept of an "array" is another fundamental
> programming concept, and collapsing to the pointer-based, machine-model
> level
> a la C/C++ doesn't do it justice.
>
> 9) Support for tasking and task communication/synchronization, at a higher
> and nicer level of abstraction than the "thread" level.  The tasking model
> allows all kinds of errors to be caught at compile time that are simply
> impossible when coding to thread-level library routines.  The task
priority
> model is unified with interrupt priorities.
>
> 10) To make it an even 'Top-Ten List' :-)... The Ada Reference Manual is a
> masterpiece of definition.  That's about all I can say about it!
>
> It could go on, the list of advantages by no means ends there.  OK,
> fine-grained control over the machine-level representation of data
> structures... package elaboration... lexical scoping... better string
> handling...
>
> Compared to other mainstream languages, Ada holds a lot of cards in
> terms of technical advantages.  Some technical disadvantages:
>
> 1) A lot of people think Ada would be better if it had more support for
> something like Eiffel-style "Design By Contract" (preconditions,
> postconditions, invariants).  Personally, I'm undecided, but quite
> intrigued.
>
> 2) That's about all I can think of right now.  That doesn't mean there
> aren't a lot of things I'd like to see improved, I just don't think the
> things on my wish list rise to the level of "disadvantages", especially
> compared to C/C++/Java.
>
>
> > 3. I read in Jargon File that "hackers find Ada's exception handling &
> > inter-process communication particularly hilarious." among other stuff.
> Why
> > is that?
>
> In all honesty, nobody knows.  This is just somebody talking out of the
> wrong orifice :-)  The Jargon File seems to be a pretty good source for
> information about jargon, i.e. slang terms.  I doubt if it's much good for
> anything else.  In addition to the "particularly hilarious" nonsense, the
JF
> entry perpetuates the myth that Ada was "designed by committee" (patently
un
> true, as a matter of public record) and refers to Ada's "elephantine
bulk",
> which is hardly fair... Once the C++ standard was published at long last,
it
> was basically just as huge, and even at that, success in C++ still depends
> on a large knowledge structure that falls outside the language itself --
> linker and makefile details, the standard libraries, threads libraries...
> but mostly a vast body of knowledge of "pitfalls" about which whole books
> have been written.  These pitfalls are all the same kinds of things that
> were designed away in Ada, whose language definition is roughly the same
> size.
>
> Mark Lundquist
> Rational Software
>
>
>





  reply	other threads:[~2001-04-05 22:06 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-04-04 13:25 Learning Ada (newbie) Ayende Rahien
2001-04-04 14:36 ` Marin David Condic
2001-04-04 18:31   ` Ayende Rahien
2001-04-04 14:46 ` chris.danx
2001-04-04 15:09 ` Ted Dennison
2001-04-04 16:00 ` David Starner
2001-04-04 18:05 ` martin.m.dowie
2001-04-04 18:29   ` Ayende Rahien
2001-04-05 11:18     ` martin.m.dowie
2001-04-04 22:25 ` Peter Milliken
2001-04-04 23:57 ` Jerry Petrey
2001-04-05 13:46   ` BSCrawford
2001-04-05 21:06 ` Mark Lundquist
2001-04-05 22:06   ` Marin David Condic [this message]
2001-04-06  4:04     ` Mark Lundquist
2001-04-06 21:52       ` Britt Snodgrass
2001-04-06 14:13     ` Ted Dennison
2001-04-06 14:53       ` Marin David Condic
2001-04-06 17:24       ` Mark Lundquist
2001-04-07 17:59     ` Georg Bauhaus
2001-04-09 14:54       ` Marin David Condic
2001-04-06  0:44   ` Ayende Rahien
2001-04-06  0:56     ` Ayende Rahien
2001-04-06  7:04   ` Martin Dowie
2001-04-06 14:11     ` Mark Lundquist
2001-04-06 16:33       ` Mark Lundquist
2001-04-24  5:24   ` David Thompson
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox