Preface

 

Purpose and approach

This book is an introductory text on programming using Java, intended for first year computer science undergraduates. The approach is object-oriented, sometime called "objects first." The text is intended to be supported by regular laboratories in which lecture concepts are reviewed and enforced.

We believe there is considerable benefit in beginning with the same fundamental methodology we expect students to be using when they complete the curriculum. We find this creates much less difficulty than starting with a procedural approach and asking students to "shift paradigms" (apologies, Thomas Kuhn) after they've experienced some initial success. With the conventional approach we`ve used in the past, students began by developing complete, self-contained solutions to simple, well-defined problems. This had the advantage of introducing fundamental algorithmic constructs and providing a grounding in the specifics of some programming language in a nicely confined context. The difficulty was that students found that these problems yield to an undisciplined, ad hoc approach. When later confronted with more substantial, less well-defined problems - problems for which design issues involving complex structural relations between components must be effectively addressed - they floundered, unwilling to abandon the "code now, think later" approach that had served them so well. We will go so far as to say that having students start by writing small, complete, self-contained programs is detrimental to their later development as competent programmers.1, 2

While traditional introductory programming texts approach the subject in a syntax and example driven format, we stress design and the discipline needed for developing complex software systems. The emphasis throughout the book is on problem modeling, using fundamental software engineering principles and concepts. Object orientation is presented using the specify-design-implement-test cycle. It takes considerable experience, of course, to acquire real proficiency in the design and construction of software systems. We hope to develop a set of fundamental skills in constructing system components and to introduce a point of view regarding system design that will be as useful in the construction of large systems as it is in the design of small components.

The programming language used in the text is Sun Microsystem's Java. We should be clear that this is not a text about Java. We are concerned with the design and construction of software systems, not language fluency. Nevertheless, since we assume our readers have no specific programming experience, we spend quite a bit of time covering Java syntax and semantics. We make no attempt, however, to cover the language completely or comprehensively. We chose Java because we felt it a good compromise between viability and semantic coherence. The language has become quite popular, and we expect adequate tools and libraries to be readily available. At the core, Java is a relatively clean and small language: one that supports the concepts we present without "getting in the way." We can spend a minimum amount of time explaining language peculiarities that have little to do with the fundamentals of software design. The UML is used (informally) for denoting objects, object relationships, and system dynamics.

Overview

There are several corollaries to the approach we have adopted. First, students must have at least an elementary appreciation of notions such as object, object state, and object feature before they attempt implementation exercises. Second, the distinction between an object's specification and its implementation is fundamental and must be emphasized throughout the presentation. Third, we must begin with small well-defined components, even though the payoff will be in the construction of large, evolving systems. This implies that the software elements students construct are carefully specified components of a conceptually large system.

The first three chapters are introductory. Chapter 1 provides some basic definitions and a simple operational model in which language semantics can be explained. Chapter 2 introduces the fundamental concepts of object and class, and relates them to the notions of value and type. Chapter 3 presents basic structural and lexical aspects of a Java program. These preliminary chapters can be covered quite quickly by moderately prepared students. Most of the items in Chapter 3 and some details in Chapter 2 were included at this point to get them "on the record" and out of the way of subsequent presentations. These topics could have been placed in an appendix or distributed throughout the text, with some loss in coherence and some later disturbance in topic flow. The critical matters in these chapters are objects and classes, and the constitutive processes of abstraction and composition.

In Chapters 4 through 10 we progress through specifying simple, well-defined classes, implementing and testing these classes, and designing and building small collections of interacting classes. Chapter 4 deals with class specification, and provides the first substantive look at Java syntax and semantics. It is unfortunate that the language does not syntactically separate a class's specification from its implementation, and we must depend on some documentation tool to "extract" the specification. Nevertheless, the conceptual distinction is essential. It is not possible to provide a correct implementation for an incompletely or inconsistently specified class. Chapters 5 and 6 cover basic algorithmic matters, including assignments, conditions, and method invocations. Chapter 7 introduces the important notion of component correctness from the point of view of programming by contract. Chapter 8 deals with testing. The first "complete program" is developed in the form of a system to test a class implementation. Chapter 9 sketches some basic organizational possibilities for interacting objects. The section concludes in Chapter 10 with the design and implementation of a complete system of moderate complexity.

Much of this early material deals of necessity with elementary algorithmic concepts and rather low level aspects of programming. Nevertheless, the context in which topics are presented is one of class development. Classes are specified and designed with the assumption that they are to be incorporated into a larger whole. Fundamental notions such as the distinction between specification and implementation, and the architectural distinction between model and user interface are emphasized. The basic structuring mechanisms of composition and extension are also introduced in this section.

Chapter 11, on software quality, presents a reflective pause in the material after the first substantial system has been seen. It is intended to hint at issues to be addressed, rather than detail a comprehensive inventory of software quality measures.

Chapters 12 and 13 introduce the sequential list as the paradigmatic container class. ("List" is simply a more fundamental notion than "array." Arrays are hardware architectural features - see the IBM 704 - bubbling up into the language syntax.) Iteration is discussed in Chapter 12, and basic list-related sorting and searching algorithms are presented in Chapter 13.

Essential class structuring devices, specifically inheritance and composition, are examined and compared in Chapters 14 and 15. The discussion of inheritance and polymorphism necessitates a presentation of some of the more baroque aspects of Java's scoping and accessibility semantics. While it is tempting to skip much of the detail, enough must be covered to enable students to understand otherwise incomprehensible program behavior.

Chapter 16 applies some of the structuring concepts to the list container, and Chapter 17 introduces recursion, starting from the perspective of lists. Chapter 18 expands on the programming by contract methodology, addresses the complex problem of error handling, and introduces exceptions, an important notion in Java. Chapters 19 and 20 provide a brief survey of the Java Swing library and a presentation of the model-view-controller architecture. The discussions of MVC and Swing allow us to examine specific examples of additional fundamental design patterns such as composite and observer.

Chapters 21 through 25 cover optional material and provide an introduction to fundamental data structuring concepts. Computational complexity is informally introduced in Chapter 21, so that the complexity of algorithms can be compared in subsequent chapters. The remaining chapters provide a introduction to some fundamental data structuring concepts, and serve as a case study in which to present choices for class and library design. Arrays and linked structures are introduced, and examples of factory methods, bridge and adapter patterns are encountered. The final chapter introduces several common containers such as stack and queue.

Some key points of the presentation are as follows.

A number of syntactic language topics have been omitted from the main body of the text. As we've said above, language syntax is not the organizing feature of the text. Linguistic structures that we felt essential to support the conceptual material are presented in some detail. Other aspects of the language, important or interesting as they may be in their own right, are not included. Applets and file-based i/o are treated in appendices. A third appendix provides an overview of most fundamental core structures of the language. We have chosen not to include comprehensive specifications of standard library classes. These are readily available on the Web, and are much more complete and up-to-date than any we could provide in the text. We hope this approach is adequate for the needs of most instructors.

Implementation

As mentioned above, the text is intended for beginning undergraduates in computer science. No previous programming experience is assumed, and the only mathematics required is elementary college algebra. We have taught the material several times as part of an introductory sequence in programming and software design. The material in the text is followed by traditional data structure topics, also presented in an object-oriented context. Our students are first and second year computer science majors with no previous computer science coursework. Though their backgrounds vary widely, a number have almost no prior computing experience. (In-class presentations can be a bit more formal than those given in the text if students have some knowledge of elementary topics from discrete mathematics.)

Laboratories:

Although it may not be obvious from the text, the approach depends on students' regular participation in structured laboratories. In addition to laboratory work, of course, students should also complete homework assignments of a broader scope.

Initial laboratory exercises, associated with the first few chapters of the text, familiarize students with the concepts of object, class, state, and so on, and help them understand simple class specifications. In our labs, students begin by experimenting with simple software systems to identify objects, their properties, and their behavior. Next they work from class specifications to develop test plans for simple classes. Testing is done using implementations and test drivers provided by the instructor. Students then develop, code, and compile class specifications. Since Java does not separate a class's specification from its implementation in distinct compilation units, methods are coded with "dummy" bodies so that compilation can take place. Such exercises are fundamental, and inculcate students with an "object-oriented perspective."

Subsequent exercises involve implementing simple classes from instructor-provided specifications. Initially, testing is done with test harnesses provided by the instructor. It is not long, however, before students are able to mimic instructor-provided test code and create their own test drivers. The first "complete systems" students encounter are test harnesses exercising a few simple classes.

From the start, the distinction between model and user interface is emphasized. Initially, students design, specify, and implement model classes, and are supplied other classes needed to construct test systems. As they progress, they are able to write their own text-based user interface components, and begin developing small systems with a few interacting classes. Later laboratories provide reinforcement of algorithmic concepts, language constructs, and class structuring techniques such as extension and composition. Independent homework assignments involve designing and implementing well-defined systems of moderate complexity.

Since the approach depends on building well-specified components of a conceptually large system, exercises generally require a supporting environment provided by the instructor. We have developed an extensive set of laboratories that we use with the text. Material for these laboratories is continually being updated and expanded. Laboratory material, support code for laboratory and homework exercises, a class library that includes elementary i/o and fundamental classes used in the text, are available at our Web site. We invite suggestions and contributions, and anticipate serving as a clearinghouse for the exchange of ideas, exercises, and supporting code.

Lecture organization:

Chapters 1 through 11 comprise the basic topics covered in the text. As mentioned above, the first three chapters are introductory and can be covered rather quickly with well-prepared students. Chapters 4 through 8 present fundamental algorithmic constructs from an object-oriented perspective. While many students will be familiar with the elementary algorithmics, the object-oriented slant will be new. We have found, however, that students tend to find the approach natural and have far fewer problems with the object-oriented concepts than we originally anticipated.

Chapter 9 is intended to "set the stage" for more complex class relationships to come. It can be treated very lightly, almost as a reader.

Chapter 10 is a first opportunity to put together something substantial. We concentrate on the important class relationships and the few new constructs in the example, and generally let students read the obvious code segments on their own. (This chapter may go down too well. Designs in subsequent courses often inappropriately reflect the basic structure illustrated here.)

Chapter 11 offers an opportunity for making a few points regarding software quality. The topics in this chapter could be presented almost anywhere in the course. The chapter can also be treated lightly, mostly as a reader.

Chapter 12 presents containers, in the manifestation of a sequential list. As mentioned above, "list" is a more fundamental notion than "array," and we can do the same algorithmic development with an indexed list as with an array. Instructors who prefer to introduce arrays early can insert material from Section 22.1 at this point.

Chapters 13 through 20 form a second segment of the text. Much of this material can be considered optional in a first course. In particular, sections 13.4 (verifying correctness), 16.2 (ordered lists), 17.5 (indirect recursion), and 17.6 (object recursion) can be omitted on first reading. Chapter 15 (modeling with abstraction) and Chapters 19 and 20 (the graphical user interface) could also be omitted. (Though in our view, Chapter 15 is one of the most fundamental in the text.)

Chapters 14 and 15 on modeling with inheritance and composition are a bit more conceptually advanced than the previous chapters. These chapters are the first in which more general design issues are addressed in a substantial way.

Finally, Chapters 21 through 25 cover topics often considered to be part of a "data structures" course. These chapters are included to give students a idea of "where we go from here" and, by providing some concrete list implementation alternatives, to complete a picture begun in earlier chapters. We would not expect this material to be covered in a typical introductory course.

Supporting material:

As mentioned above, considerable supporting material is available on the Web. This includes laboratories with supporting software, source and executables of library packages used in the text, source of examples used in the text, etc. Supporting material can be accessed through the Wiley server, at http://www.wiley.com/college/nino/ or through our server, at http://wakko.cs.uno.edu/ or http://www.cs.uno.edu/~fred/OOJ/.

Additional complementary material made available by other contributors is also available through these sites.

Comments, suggestions, corrections, contributions, etc. can be forwarded through the above sites, or to the authors directly at fred@cs.uno.edu and jaime@cs.uno.edu.

Readers interested in learning Java per se should investigate the Sun Java tutorial at http://java.sun.com/docs/books/tutorial/.

For specifics on the language syntax and semantics, consult the The Java language Specification, available at http://java.sun.com/docs/.

The Java Software Development Kit can be downloaded, as of this writing, from http://java.sun.com/j2se/.

(You might also try http://java.sun.com/products/ or http://java.sun.com/.)

Documentation for the standard Java libraries can be accessed at http://java.sun.com/j2se/1.3/docs/api/.

Documentation for local libraries used in the text can be found at http://wakko.cs.uno.edu/OOJ/docs/ or http://www.cs.uno.edy/~fred/OOJ/docs/.

If you have difficulty accessing the above sites, check the Wiley site at http://www.wiley.com/college/nino/, the Sun sites http://java.sun.com/products/, and http://java.sun.com/, or contact the authors directly.

Finally

We could not, of course, have completed this text without the help and support of many people. We are indebted to our colleagues for the confidence they showed in us by allowing us to overhaul the introductory programming curriculum and install an unproven approach. (Particularly noteworthy since most of them knew they'd end up trying to teach this stuff.) We are also indebted to the first few classes of students who endured our trails and errors - getting a first hand view of the design-implement-test cycle. They seem no worse for the experience, and didn't have much of a choice anyway.

We are grateful for the conscientious efforts of our reviewers, notably Fiona Gaston, Thaddeus F. Pawlicki, H.E. Dunsmore, Byron Weber Becker, and Alok Mehta. We'd like particularly to thank our colleague Bill Greene who labored through early versions of the notes on which this text was based and offered numerous helpful suggestions.

Special thanks to Robert Burton, for his many insightful and useful suggestions, and his careful reading of the text.

We are grateful for the help and guidance of the folks at Wiley, particularly Jenny Welter, and our editor, Paul Crockett.

Finally, we are grateful for the support of our family and friends, and for Bill Joy, James Joyce, Thomas Kuhn, George Elliot, John Reynolds, Ray Witham, Stephen Kleene, Larry Landweber, Dana Scott, John Adams, Jacques Barzun, Arnold Schoenberg, Jacqueline Du Pré, Immanuel Kant, Karl Hoffman, and Bertrand Meyer.

I should without hesitation split the infinitive and write to calmly consider.
--Jaques Barzun

They lard their lean book with the fat of others' works.
--Robert Burton (1576-1640)3


1 See, for instance, Duane Buck and David J. Stucki, "Design Early Considered Harmful: Graduated Exposure to Complexity and Structure Based on Levels of Cognitive Development," 31st SIGCSE Technical Symposium, Austin, March, 2000.

2 Another point of view is that this is complete hokum; the only useful programs are written by very clever people, and there's not much we can do to ruin them.

3 Borrowed from the preface of "The Java™ Language Specidication, Second Edition," Joy et. al., 2000.


Fred Hosch
Last modified: Wed Jan 16 08:24:47 CST 2002