Preface for

M.B. Feldman and E.B. Koffman, Ada 95 Problem Solving and Program Design, 3rd edition.

Copyright 1999, Addison-Wesley Publishing Company
ISBN 0-201-36123-X (textbook includes multiplatform CD-ROM).

Publisher's information on this text is available from the Addison-Wesley web page.


This textbook is intended for the introductory course in problem solving and program design using Ada 95. It assumes no prior knowledge of computers or programming, and for most of its material, high school algebra is sufficient mathematical background. The first two editions of this book have been used with success in a large number of introductory courses.

While the book is generally oriented to the first-term student of programming, there is more material here than is usually covered in a first course. Chapters 11 through 17 focus on abstract data types, generics, recursion, dynamic data structures, inheritance-oriented programming, and concurrency. They can be used selectively in a fairly advanced first course or as part of a second-level course. The book covers the Ada 95 language thoroughly enough to serve as a useful introduction for professionals.

The Ada 95 language standard was adopted early in 1995 by the International Standards Organization and the American National Standards Institute. Ada is a foundation language in a growing number of institutions (about 150 at this writing). Ada is also a language of choice in many important industry sectors, especially commercial aviation and air traffic control, high-speed and metropolitan rail transportation, scientific and communications satellites, and manufacturing control. The consensus among teachers of Ada is that its pedagogical virtues are very similar to its industrial ones.

Problem Solving and Program Design

The primary focus of this book is problem solving with Ada 95, not a study of the Ada 95 programming language per se. We achieve this focus by selecting features of the language that lend themselves to good program design. We also emphasize abstraction and use the time-tested six-step approach to software development: problem specification, analysis, design, test planning, implementation, and testing. Each of the 35 case studies throughout the book follows this software development method.

New in the Third Edition

This edition includes a number of new end-of-chapter projects. Also, a new Chapter 2 uses an Ada 95 "spider" package--similar to the turtle graphics of Logo--to introduce the basics of algorithms and the fundamental sequential, loop, and test control structures, all in a platform-independent animated framework. Chapter 2 is independent of the others and thus provides flexibility to an instructor who sees real benefit in introducing all the major control structures together as early as possible. Instructors who were satisfied with the presentation order in the first two editions can simply skip from Chapter 1 to Chapter 3 without loss of continuity.

This edition also contains alphabetical indexes of syntax displays, case studies, and program style guides and a new Appendix A, High-Resolution Color Graphics. This appendix provides a platform-independent package for simple two-dimensional graphics and examples including a high-resolution color spider package.

Finally, this edition incorporates a CD-ROM, which is described in Appendix G. This CD-ROM contains

  • the complete set of about 200 book programs, all in standard, platform-independent Ada 95
  • the Appendix A software for various platforms
  • platform-specific versions of the GNU Ada 95 Compiler (GNAT) and interactive development environments (IDEs) for Apple Macintosh, Microsoft Windows 95/98/NT, MS-DOS/PC-DOS, and Linux
  • various browsable editions of the Ada 95 Reference Manual and Rationale and additional reference documents such as printable reference cards and graphical syntax diagrams
  • a copy of Tenon's MachTen Code Builder system, a virtual UNIX environment for the Macintosh

General Organization of the Book

The order of presentation is designed to do justice both to modern programming concepts and to the power of Ada. Each chapter beyond Chapters 1 and 2 presents a balanced mixture of a number of important language and computing issues. These are organized in a number of categories; most chapter section headings give the main category of the section as well as the specific topic, to orient teacher and student alike to the flow of material in a given category from chapter to chapter. The categories are:

  • Problem Solving: Here is where language-independent concepts of program design, algorithm development, and so forth, are introduced.
  • Control Structures: Each of these sections introduces the program-level control structures of Ada: decisions, loops, assignments, and so on.
  • Data Structures: In each of these sections appears a discussion of data types and their uses, in the usual order of scalar types followed by structured or composite (record and array) types.
  • System Structures: Each of these sections introduces a concept that is useful in what is often called "programming in the large." These concepts help the student, right from the start, to realize that real-world programs really consist of many smaller pieces built up in systematic fashion. Included under System Structures are such things as functions and procedures, packages, and exception handling and propagation.
  • Tricks of the Trade: These are the universal techniques that all programmers must learn in order to survive productively: debugging techniques, program tracing, documentation techniques, and the like.

Pedagogical Features

In this book we employ several proven pedagogical features:

  • Complete, compilable programs: From the beginning, students see full, compilable, executable programs. These are captioned "Program x.y" to identify them clearly as compilable programs and not fragments, which are embedded in the text or numbered as figures. Each listing of a main program is immediately followed by a sample execution, to give the student an idea of the expected results.

    A particular advantage of Ada as a teaching language is that the strong standard ensures that program behavior will be nearly independent of the particular compiler or computer being used. The programs in this book have been fully tested and can be compiled and executed using any validated Ada 95 compiler.

  • Case Studies: A case study is a program that is developed from specifications, step by step, from a statement of the problem to a complete working program. The software development method is taught, reinforced, and applied. We focus much attention on program testing and the development of test plans.

    Of the 35 case studies, some--especially in the early chapters--are presented in their entirety, while others are intentionally left incomplete so that their completion can be assigned as class projects.

  • Syntax displays: A syntax display is a brief description, with words and examples, of the syntax and interpretation of a newly introduced structure. These are set apart typographically for ease of use, and they codify the language structures as they are first presented.
  • Programming style displays: These are brief discussions, again set apart typographically, offering advice to the student about how to write good programs. Many of these are of course universal and language-independent; many are also Ada-specific.
  • End of section exercises: Following most sections there are two kinds of exercises, self-check and programming.
  • End of chapter exercises: Each chapter review contains a set of quick-check exercises with answers, review questions, and programming projects.
  • Error discussions and chapter review: Each chapter ends with a section that discusses common programming errors and a review section that includes a table of Ada constructs introduced in that chapter.

Program Design Issues

Concepts of object-oriented programming (OOP) are introduced throughout the book as appropriate. While it is true that type extension and dynamic polymorphism are generally seen as necessary to "full" OOP, it is essential for the student to understand that these are not sufficient. Ada's strong support for packages, generics, exceptions, private types, and subprogram overloading--like their equivalents in other languages--play important roles as well. The idea that an object--even a scalar object--has state (value) and behavior (appropriate operations) is introduced beginning in Chapter 3, and "object thinking" is pervasive in the book. Type extension per se is an advanced topic that cannot be understood without a good grounding in the other topics, so it is deferred until Chapter 16.

We present stepwise refinement of an algorithm right from the start but make only rare use of top-down implementation through procedure stubs and the like. It is crucial to foster habits of design for reusability very early, and this argues for early emphasis of packages and the reusable functions and procedures they provide.

Functions are presented very early: They are used in Chapter 4 and written in Chapter 5. Procedure calls are introduced in Chapters 2 and 3 to support the spider package and Ada's input/output operations; procedures are written starting in Chapter 7. Functions are more intuitive than procedures, and, in Ada, cannot have IN OUT ("variable") parameters. Since functions in Ada are not restricted in their result type--arrays and records as well as scalars can be returned--this early exposure to functions will pay off later in encouraging students to use functional notation where possible. Introducing functions early allows us to introduce the writing of packages early (again in Chapter 5).

Enumeration types are introduced very early (Chapters 2 and 4). Enumerations are a useful structure for representing a set of values without regard to their internal representation. Students of other languages have a hard time seeing the utility of enumerations because they are so hard to read and display. In Ada, the input/output library provides a generic package for reading and displaying enumeration values. Furthermore, enumerations serve as a useful vehicle for motivating generic instantiation (for Enumeration_IO) and attributes (Pos, Val, Succ, Pred) very early in the game.

Records and arrays are presented together in Chapter 9, with records first. Other books have introduced arrays of scalars early, with arrays of records as an "advanced" topic. We prefer to teach that arrays of records are as natural as arrays of integers.

Design of abstract data types (ADTs) is introduced systematically beginning in Chapter 11. Ada.Calendar is seen as an ADT, and the discussion continues with ADTs for calendar dates, monetary quantities, employee records, and multiple spiders. Unconstrained array types are treated along with generics in Chapter 12; multidimensional arrays and variant records are introduced in Chapter 13. Chapter 14 presents an introduction to recursion. Dynamic data structures, in the form of one-way linked lists, as well as subunits and LIMITED PRIVATE types, are introduced in Chapter 15, with applications to stacks and queues. Tagged records are introduced in Chapter 16; these are seen to be supportive of the type extension (inheritance) that is now seen as essential to full object-oriented programming.

Finally, Chapter 17 introduces the important concept of concurrent programming, introducing Ada's task types and protected types as language-provided constructs for concurrency.

Preconditions and postconditions for subprograms are introduced at the start. We encourage the development of programs from their documentation; in case studies, the steps of the algorithm are written before the program is developed and become comments as the program is refined.

We encourage appropriate use of comments but do not get carried away with them; the programs and the book would be far too long if we used industrial-strength comment conventions.

Ada Issues

Ada 95 is a rich and powerful language. It is important to introduce the language to beginners, step by step, without overwhelming them. Here is a list of a number of Ada capabilities and how we have handled them:

  • Numeric Types: Subtypes are introduced early in the book, as a way of specifying ranges of values that are sensible in the application. Where values shouldn't be negative, we always use a positive subtype, for example, and often use a subtype with range constraints where it makes sense not to allow the full range of integer.

    We have avoided the use of new and derived numeric types because the compatibility issues that arise from their use create more problems than they solve for beginners. It is range checking that is important to them, not the esoterica of type compatibility.

    Furthermore, using new or derived numeric types for simple beginning-level numerical problems gives completely counterintuitive results: Attempting to use types for distance, rate, and time, for example, to compute the old

    Distance := Rate * Time;
       

    formula leads to type-compatibility grief that no novice should have to endure.

  • Packages and related issues: Using packages is introduced in Chapter 2 with the spider system and in Chapter 3 with the use of the various sublibraries of Ada.Text_IO. In Chapter 4, students learn how to use some of the capabilities of Ada.Calendar, which has a richness that is not often explored even by advanced Ada texts. Ada.Calendar is a recurring theme in this book, and is discussed in the absract data type material of Chapter 11, since Time and the various Time and Duration operations from Ada.Calendar serve as a particularly nice predefined example of a private ADT. Also, students understand times and dates intuitively; there is nothing esoteric about them. The year range of Ada.Calendar (1901<2099) provides an opportunity to discuss the Year 2000 problem.

    Also in Chapter 4, use of a simple screen-control package is introduced. Students will need to compile this before they use it, since it is provided with the book and is not part of most compiler distributions. Thus they will learn how to compile a package and understand specifications very early on, even if they don't yet understand the details of the package body, which are discussed at some length in Chapter 8. Screen is used in a number of examples in the book, especially for menu handling, plotting, and the spider examples.

    By Chapter 5, students are writing simple packages; by Chapter 6 they are learning about overloaded function and procedure names. Private types and operator overloading appear in Chapter 11.

  • The USE clause: This is introduced in Chapter 8. Ada industry practice generally avoids the USE clause for a number of good reasons. We avoid it here, in general, because qualifying all references to package resources helps the student to really understand which resources are provided by which libraries. USE and its Ada 95 variant USE TYPE can be useful in taking advantage of the overloading of infix operators; this is discussed in Chapter 11. USE is a better solution for novices than the industry-favored device of renaming declarations.
  • Generic predefined libraries: For numeric input/output, we use the Ada 95 Ada.Text_IO.Integer_Text_IO and Ada.Text_IO.Float_Text_IO. Using these new "preinstantiations" obviates the need for the student to instantiate numeric input/output packages. The new "preinstantiations" are introduced in Chapter 3 and are used consistently throughout. In Chapter 4 the student learns to instantiate Ada.Text_IO.Enumeration_IO for the desired enumeration type. The student instantiates Ada.Numerics.Discrete_Random beginning in Chapter 8.
  • Generics in general: Some simple generic units appear starting in Chapter 12. Writing generics is really an advanced topic that should wait until CS2, when the student is better equipped to handle the underlying abstraction principles.
  • Exceptions: Discussion of Ada's predefined exceptions occurs in Chapter 3, where compilation and run-time errors in general are introduced. Robust exception handling cannot be taken up until after the control structures have been presented, and so program level exception handling is first discussed in Chapter 6. Robust input loops are presented in Chapter 7, along with a package providing robust input operations. User-defined exceptions are introduced in Chapter 11, as a natural aspect of abstract data types.
  • Lexical style: We have continued the practice of the earlier editions in using uppercase reserved words. We believe that beginners in programming should learn the structure templates through heavy reinforcement, and the uppercase reserved words make the structure templates stand out. Ada is not a case-sensitive language, and although reserved words are printed in the standard in lowercase, an uppercase convention is perfectly allowable and is, in our experience, pedagogically effective. It is emphasized in the text that teachers and students can, and should, develop their own coding styles and that consistency of style is more important than following any specific rule.

    Only one statement appears per line. We believe that this makes for more modifiable code and is a good habit for students to develop. Similarly, each variable and constant is declared in a separate declaration on its own line.

  • Procedure parameters: Named association is used exclusively in the early chapters and almost exclusively thereafter. This is not only good Ada but also good pedagogy because--as our experience shows--the student has a much easier time understanding the formal/actual binding if the two always appear together.
  • Initialization expressions: Initialization expressions are introduced in Chapter 8, along with record types, and the reader is advised to use initializations to ensure that record fields are always well defined. With some reluctance we have decided not to introduce initialization expressions for variables. It is true that a declaration with a static initialization such as
    X: Float := 57.0;
       

    contributes to program readability. However, an initialization such as

    X: Float := 3.0 + Sqrt(Y);
       

    is permitted but should not be used, because an exception that is raised if Y is negative will propagate unexpectedly. Instead of artificially limiting initializations to static expressions, we have simply chosen not to use them at all.

  • Private and limited private types: Private types are covered in depth in Chapter 11, in the discussion of abstract data types. Specifically, a number of examples are given of situations in which giving a client access to the details of a type would allow the client inadvertently to violate the integrity of the abstraction. The exported types in this chapter all provide for default initialization so that assignment and equality test are always meaningful operations.

    In later chapters attention is paid to those situations--especially in the use of dynamic data structures--in which assignment and equality test can indeed be used misleadingly, for example, to copy just the headers of lists. The potential for abuse of these operations provides useful justification for limited private types, for objects of which assignment and equality test are prohibited.

  • Subunits and Ada stubs: The list-handling packages of Chapter 15 serve as a way to introduce this concept, which is confusing if brought in too early. Besides being an interesting Ada technique for doing top-down testing, the use of subunits serves as a convenient way to present the operations of the packages as individual program displays and files.
  • Tasks and protected types: Ada is unique among major programming languages in providing support for parallelism and concurrency within the language. Parallelism is now seen as a "recurring paradigm" in computing, and we think it important to introduce students to it as early as possible in their education. The material in Chapter 17 serves this purpose; we have made it independent of Chapters 12Ð16 so that a teacher desiring to introduce concurrency in a CS1-level course can do so after Chapter 11.

Instructor's Manual and Other Online Resources

Information regarding this text is available from the Addison-Wesley World Wide Web site at: http://www.awl.com/cseng/titles/0-201-36123-X.

The Instructor's Manual is available electronically. The public part, containing chapter and section summaries and objectives, new terms, notes, and suggestions, as well as program libraries and errata, WILL BE at:
http://www.seas.gwu.edu/faculty/mfeldman/cs1book.

The private part, containing solutions to exercises and projects, is available to instructors only from Addison-Wesley. Contact your sales representative for access information.

It is intended that teachers make the full set of about 200 programs and packages available to their students so that they need not waste time keying them in. Of course the programs are available on the included CD-ROM; we hope that teachers will make them available centrally for courses using central systems for projects. The programs are also available from the above-named WWW sites.

Afterword

This book's earlier editions incorporated a great deal of new material that is intended to introduce the beginning programmer to the power of Ada while building on the successful pedagogy of the earlier Koffman works. The earlier editions' success among teachers of Ada--in a number of cases, even serving as critical "ammunition" in moving introductory courses to Ada--confirms the soundness of the approach.

The present edition builds on the success of the first two, serving as an important aid to teachers ready to introduce students to Ada 95.

Acknowledgments

All the programs have been tested using the GNU Ada 95 Translator (GNAT), running on an IBM-compatible computer under Windows, an Apple Macintosh under MachTen, and a Sun-SPARC computer under Solaris. The authors acknowledge the School of Engineering and Applied Science Computing Facility at The George Washington University for having provided the Solaris computing resources.

The authors are indebted to the following educators, who served as formal reviewers and provided unusually cogent and helpful assistance: Todd W. Breedlove, Jessica Lambert, Linda Null, David Nash, Ming Wang, and Phyllis Ann Williams. John Dalbey provided the original Spider package. We are further indebted to Chet Lund for some very creative project ideas; to Thibault Estier, Magnus Kempe, Laurent Pautet, and Paul Pukite for their Ada 95 electronic reference documents; to James Cross for GRASP; to Jerry van Dijk for the original AdaGraph package for Windows and other help; and to Martin Carlisle and James Hopper for their help in developing AdaGraph ports to other platforms. We offer thanks to Ada Core Technologies for providing the GNAT compilers, and to Tenon Intersystems for allowing us to distribute MachTen CodeBuilder.

The Addison-Wesley editorial and production staff, including Susan Hartman, Katherine Harutunian, Patricia Unubun, Diane Freed, Bob Woodbury, and Lynne Doran Cote, deserve hearty thanks for their expert and always good-natured assistance.

Finally, Ruth Feldman has earned a vote of gratitude for tender loving care and help on the index. Ben and Keith Feldman have, as before, always been there to cheer their father on through the development of (in their words) "yet another book."

Bethesda, Maryland, Michael B. Feldman
Philadelphia, Pennsylvania, Elliot B. Koffman