Structured Programmers Learning Object-Oriented Programming
John Minor Ross and Huazhong Zhang
Vol.29 No.4, October 1997
Structured Programmers Learning Object-Oriented Programming: Cognitive Considerations
OOP Versus Structured Programming Learning OOP: Cognitive Issues
- Negative Transfer
Incompatibilities between OOP and Programmers
Resistance to Learning New Things
Expert versus Novice Programmers
Frustrating Conclusion: No Pain, No Gain
With object-oriented programming (OOP) in Java and C++ increasing in popularity, retraining current structured programmers (e.g., users of C or COBOL) is of considerable interest in the computer discipline. One commonly expressed problem with this training task is that the interaction between programmers and their programming language environment appears to be significantly altered during both design and coding phases when using an OOP language versus earlier, so-called structured, approaches. Programmers using existing techniques experience confusion, frustration, and sometimes fail in their attempts to acquire new OOP skills. After comparing and contrasting object-oriented approaches with structured design and programming, the authors review the cognitive difficulties novice and expert structured programmers encounter in switching to OOP technology and suggest ways to ameliorate the troubles. Finally, preliminary research is presented which indicates that, contrary to commonly expressed views, experts do not find it more difficult to change paradigms than do novices. They may, however, experience more frustration as they are temporarily reduced to near-novices again.
The current hot approach to computer programming is object-oriented programming (OOP). Advocates stress that designing computer solutions with a focus on real-world objects "can lessen the gap between what the programmer models and the application domain being modeled" (Kilian, 1996, p. 39). OOP has been hailed for its naturalness, understandability, extensibility, reusability, and ease-of-maintenance. As a result, they are being suggested as solutions to many problems (e.g., Backlund, 1997). Because it has many technological benefits over traditional structured programming, Yourdon (1993) says that by the year 2000, most programmers will be working with OOP technology instead of traditional structured programming.
Unfortunately, experts in the current technique, structured programming, often experience frustration in shifting to OOP technology. Building re-usable and extensible code is extremely complex, and programs with the full benefit of current OOP technology are not easily constructed. As a result, OOP technology is not expected to be the "silver bullet" that eliminates current software development troubles (Brooks, 1987; Fischer, Redmiles, Williams, Puhr, Aoki & Nakakoji, 1995). It is, however, expected to replace the current techniques because even incremental improvements in productivity in the software business have enormous financial benefits.
In the following analysis, we first compare OOP technology with traditional structured programming. Then we discuss the cognitive difficulties structured programmers face in switching to OOP technology and provide tentative explanations and solutions to these difficulties.
Regardless of the language used prior to OOP, programmers since the 1970s have embraced a style called structured programming. As with earlier "spaghetti code," computer programmers still used such concepts as variables, assignments to variables, expression construction, and function evaluation. Typically, those programmers spent long hours designing, coding, and debugging programs. Structured techniques, such as the use of subroutines rather than GOTOs, resulted in improved development timelines and increased supportability. Although improved over prior coding techniques, structured programmers found that they usually could not reuse routines already coded for earlier programs. In 1967 the first OOP language, SIMULA-67, was introduced which had several unique ways of coding subroutines with improved potential for reuse. Current OOP languages such as Java (derived from C++) and Smalltalk share commonalities with traditional structured programming languages such as C and COBOL while adding in the ideas first developed in the 60s. Despite the many commonalities, object-oriented programming is significantly different from structured programming as described next.
In structured programming, while analysis starts with a consideration of real-world problems, the real-world focus is lost as requirements are transformed into a series of data flow diagrams. As shown in Figure 1, the data flow diagrams (not shown) are the intermediate step before the design stage. When program design takes place, the process has distanced itself from the real world. The design stage culminates in the creation of structure charts and detailed logic diagrams. By the time the programming team goes to work, they are no longer focused on the real-world objects being emulated. That focus is replaced by what the systems analyst decided the programmers needed to know to code the program.
Figure 1. Program development life cycle in structured programs. Structured development life cycle has discrete phases. Each phase is focused on modeling the processes (from Bordoloi & Lee, 1994).
In contrast, using object-oriented analysis, design, and programming techniques, the focus remains on the real-world objects throughout the development cycle. Although there is no clear winner in object-oriented analysis (Missikoff & Pizzicannella, 1996), there is, as shown in Figure 2, an overlap between each of the three development steps. The analyst and the programmer are both interested in development of usable (and reusable) objects. These programming objects (referred to as class declarations), once tested and made available to other programmers, do not have to be retested and redesigned every time changes are made to the data layout.
Figure 2. Program development life cycle in object-oriented programs. Object-oriented (OO) life cycle phases overlap with each phase having the same object focus (from Bordoloi & Lee, 1994).
In structured programming, data and functions (or procedures) are separate, whereas in OOP, they are integrated into data structures called classes. In a structured program, data (e.g., employees, orders, or sales records) are essentially passed to functions (e.g., print, display, add, change, and delete routines) that act on the data as required. In OOP, encapsulation is used to package data with the functions that act on the data. The declaration of such an encapsulated unit is called a class, which refers to an abstract view of objects in the real world. The class may be considered as a blueprint for objects the programmer desires to construct (Prosise, 1995). Once instantiated, a class becomes an object in the program. In other words, in OOP, an object is an instance of a class.
Another major difference is that in structured programming functions are the primary focus of design. Data are of secondary importance. As shown in Figure 3, the structured programming approach results in many different parts of a program all having access to the data. The main control routine and any sub-routine may be coded to access the data directly, change it, and inadvertently introduce mistakes. If one programmer changes the representation of the data in the computer's memory by re-arranging fields within a record, other sub-routines in the program may need to be re-written and must then be re-tested to account for this change.
The OOP approach reverses the emphasis of data and functions used in structured programming. In OOP, programs pass messages to object methods (subroutines) that are conceptually packaged with an object's data. Object-oriented programming requires the analyst, designer and programmer to focus on objects instead on actions. This is a fundamental change from structured tools that focused on desired program actions with data playing a role in the shadows. Rosson and Alpert (1990) contrast the differences between conventional structured programming languages and OOP this way:
Figure 3. Data access in structured programs. Structured program data is openly accessible from other parts of the program. This introduces risk in that error control coding may be inadequate in one of those parts. If the data is corrupted, the programmer has multiple places in the program to review for correctness.
Rather than invoking procedures to act on passive data, messages evoke object activity: A message sent to an object is a specification of some action, a request for the object to exhibit some behavior, or to supply some information. The action taken by the object is a function of its interpretation of the message and its internal state. (p. 355)Object-oriented programs typically restrict the programmer from haphazard access to the data, as shown in Figure 4. If a programmer using an object wishes to, for example, display or change the data, the only way of doing so is via a controlled access mechanism (a method of the class. A programmer writing a control routine in the main part of a program using OOP techniques simply sends a message to the object asking it to print, display, or change its data. All of the methods written with the class have open access to the data associated with an object of that class, but no part of a program constructed in the future, outside of the object, can change the data thereby possibly introducing mistakes or errors in the program. As Clarkson (1992) put it, "objects manipulate themselves; nothing reaches inside and stirs their contents around" (p. 148).
In OOP, a new class similar to an existing class can be constructed using the principle of inheritance; new classes can inherit all or part of the structure and procedures from a previously established class, for example, a "house" object may inherit all of the characteristics of a "shelter" class. A new class can be built from parts of multiple pre-established classes, for example, a "houseboat" may inherit characteristics of both a "house" and a "boat."
Lastly, in OOP, polymorphism permits the program to decide at run-time which of like-named methods derived from the same base class is the appropriate one to execute. Using this technique, also referred to as late-binding, a program coded to land "flying vehicles" can correctly land such flying vehicles as airplanes and helicopters without the need for traditional if-else or switch-case logic.
Figure 4. Data access in object-oriented programs. Object-oriented program data access typically restricts the programmer using a class from accessing the data directly from other parts of the program. If any trouble is found, there is only one interface to alter. Changes to the data layout do not impact the main parts of the program.
The object-oriented approach is more than just another programming method; it represents a paradigm shift in Kuhn's (1970) terminology. In a nutshell, OOP technology is a more powerful paradigm for analysis, design, and programming than traditional structured programming.
When programmers knowledgeable in one language learn a new one, similar features between the languages lead to positive transfer. "Good software design," according to D'Souza (1993), builds upon "insights into the processes of previously solved problems, as well as the products of those processes" (p. 44). Whitelaw and Weckert (1995) found positive transfer of simple concepts such as variables, assignments to variables, expression construction, and function evaluations for structured programmers switching to OOP.
Détienne (1990) studied expert structured programmers learning OOP paradigm with the focus on how experts learned "new concepts in their domain of expertise" (p. 972). This research suggested that knowledge learned from earlier languages carried over advantageously for the experts facing the new language learning experience.
Sonnentag (1996) considered the problem-solving approaches of thirty-five professional software designers (6.6 mean years of experience). Sonnentag concluded that such designers rely on their "broad knowledge of . . . useful strategies [to] guide the work process" (p. 221) and do little explicit planning during problem-solving.
It is often difficult to change the way people do their work. Dumas and Parsons (1995) found that expert structured programmers do not want to change their paradigm. It is also possible that expertise in the traditional structured paradigm is counterproductive to the shift to OOP. Historical performance may guide or distort the mental processes needed to learn the new approaches. Gavelek and Raphael (1985) note that "individuals behave in reflective, planful, and where necessary, self-correcting ways" (p. 107). Such self-correcting actions include mental efforts to hold onto one's existing beliefs. The interference of past experience while learning of new material was documented by Pennington, Lee, and Rehder (1995). They found that even following object-oriented training, "certain procedural practices crept" into the efforts of novice object-oriented designers (p. 203). "Typically, it will take longer [to learn OOP] for a person experienced in some other paradigm" according to Luker (1994, p. 59). Beck (1991) put it this way:
At the end of that first half year, I had a solid grasp on all the little issues of an object language, but I still knew nothing about objects. I had been reimmersing myself in issues familiar to me from my days as a procedural programmer. I focused on the non-object-oriented aspects of my object-oriented language to avoid the uncomfortable feeling that I didn't know what was going on. By clinging to my old ways of thinking, like a nervous swimmer to the side of the pool, I was preventing myself from reinventing my perspective. (p. 39)
As Détienne (1990) says, "experts in programming learn a new programming language by the evocation and the adaptation of old schemas" (p. 976). This adaptive process may slow the transition to object-oriented programming. Eckel (1995) believes that:
Programmers work out a model in their heads of how things work and have some trouble dislodging that model once they've tested it and come to believe in it. This prevents them from making big mistakes, such as switching to a language that's too limited for their needs, but it also significantly slows down the shift to a more powerful way of thinking. (p. 17)Another problem is that programmers may build programs from expectations rather than what was said in a class or in a book. Students of the new paradigm may attempt to understand the object-oriented programming in terms of their prior structured background rather than give up what they feel comfortable with. According to Margolis (1993), mental habits are usually helpful and experts seem to use them frequently. "But since a person is ordinarily unaware of habits, she will also ordinarily be unaware of when a habit is not serving her well" (p. 15). Missed opportunities happen when a habit is "so deeply entrenched and entangled in expert practice that escaping it is difficult even after some logical or empirical anomaly directly challenging that habit comes on the scene" (p. 32).
Dué (1993) believes that "the change in mindset required to move to the object paradigm seems to be the single biggest obstacle" (p. 70) in the transition. "Achieving such object-oriented benefits is not easy; this approach to designing and building applications requires changing mindsets" (Tasker, 1991, p. 79). Eckel (1995) suggests that those learning object-oriented programming face the problem of simply finding a perception of what it is they are learning.
Several things can be done to overcome the impact of negative transfer. First, expert structured programmers should be explicitly told that they are not learning just another programming method. Instead, OOP requires a new orientation and a changed programmer mindset. Second, whenever possible, OOP should be introduced in the undergraduate curriculum as early as possible (Luker, 1994). It may even be advantageous to teach OOP as the first programming language (Koenig, 1996).
OOP is marketed as "natural" to human users (Rosson & Alpert, 1990). Although OOP is more natural than structured programming, it is still not fully compatible with human users (Davis et al., 1995; Fischer et al., 1995; Whitelaw & Weckert, 1995).
First, although it is often claimed that objects in OOP are similar to real-world objects, the analogy is at best limited (Davis, Gilmore, & Green, 1995; Fischer et al. 1995; Whitelaw & Weckert, 1995). If objects in OOP were indeed similar to real-world objects, programmers would transfer their every-day experiences to programming and learn OOP technology with little effort. Unfortunately, "in many respects, the naturalness of [OOP] to nonprogrammers is very unnatural to traditional programmers" (Eaton & Gatian, 1996, p. 23).
Second, OOP provides only one representation (object-oriented). Although this representation may be advantageous in many ways, humans use multiple representations (Davis et al., 1995). For example, expert OOP programmers may focus on the functional properties of the code instead of on objects. In order to take human factors into consideration and make OOP technology adapt to humans rather than the other way around, future OOP technology should supplement diverse representations.
Third, although OOP technology allows the creation of reusable components, programmers may not know what reusable components already exist, how to access them, how to understand them, and how to combine, adapt, and modify them to meet current needs. Current OOP technology provides only limited tools for locating reusable classes and methods. Thus, drawing an analogy from cognitive psychology, we can say that reusable classes and methods are available but inaccessible. To make them more accessible, Fischer et al.'s (1995) cognitive model may be a step in the right direction.
Pennington et al. (1995) found that although expert OOP programmers are more efficient than expert structured programmers, expert structured programmers are more efficient than novice OOP programmers who were expert structured programmers before learning OOP. Therefore, expert structured programmers shifting to OOP technology must be patient and should not expect to master OOP technology overnight. For efficient learning, programmers should be informed of the limitations of the paradigm.
Learning new knowledge (e.g., statistics) is hard and, in general, people are reluctant to learn new things. This reluctance may be overcome if there is a demonstrated need. Because OOP is new to structured programmers, they may not be really motivated to learn it. One solution is to use real-world examples to illustrate the power of and the need for OOP technology.
The problems that learners of OOP technology confront also include that of false understanding. Gilovich (1991) illustrates a series of human reasoning mistakes, in a series of chapters covering: making something out of nothing (misinterpreting data); seeing too much when looking at too little (misinterpreting incomplete or unrepresentative data); finding what we expect to find (biased evaluation of data); and finding what we want to find ("motivational determinants of belief") (p. v).
According to Stacy and MacMillian (1995), a programmer's knowledge "about the world is stored and manipulated using some form of mental representation." When using this existing background to develop and understanding of a new topic, they suggest that people "tend to seek evidence that could verify [their] theories, but not evidence that could falsify them" (p. 60). Aiding programmers to fix false understandings and unlearn old approaches may ease their transition to OOP.
In learning a new paradigm such as OOP technology, expert structured programmers often suffer from a high degree of frustration (perhaps higher than novices. The frustration may occur because expert structured programmers do not recognize the existence of the paradigm shift.
Although both expert and novice OOP programmers decompose design problems into objects, experts are more efficient than novices (Détienne, 1995; Pennington et al., 1995). Often times, given the same program, experts see objects but novices do not. Expert and novice OOP programmers often differ in their ways used to identify classes, to analyze problems through classes, to create methods along with classes, and to use mental simulations. Thus, it helps to explicitly tell novices how experts might approach the same design problem and direct novices to emulate the processes followed by experts (Pennington et al., 1995).
In an effort to assess whether experts reported similar or higher levels of trouble transitioning to OOP as contrasted to novices, a one-page questionnaire was given to 56 students completing an OOP course in C++. Over five semesters (fall 1994 through fall 1996), Likert scale answers were collected reflecting student self-assessment through three questions: (a) whether structured programming was similar or different from OOP; (b) whether learning C++ was harder or easier than learning non-OOP languages; and (c) whether programming in C++ was easier or harder than programming in non-OOP languages.
The students were enrolled at a commuter campus serving both traditional and returning adult students. Student ages ranged from 18 to 48 with a mean of 30 and a modal age of 28. The surveyed groups consisted of 12 females and 44 males. Over sixty percent of the students surveyed already had baccalaureate degrees. Forty-five percent (25 out of 56) called themselves good or skilled programmers.
Students reported knowing many different languages although none were object-oriented. Thirty-two percent of the students knew either one or two languages. Forty-six percent knew three or four languages. Twenty-two percent knew five or six languages. Most students had no workplace experience or no technological experience, while 36% had prior experience considered to be likely to elevate them above novice status. Based on the work of Sonnentag (1995), these differences of experience level and programming languages known were selected as ways to differentiate experts from novices.
On the first question, most students (67.9%) felt that OOP was either different (42.9%) or very different (25.0%) from structured programming. The others reported it was the same (3.6%, one student), similar (12.5%), or a "bit different" (16.1%). This seems to be consistent with the claim that OOP is a paradigm shift rather than just an incremental change.
On the learning difficulty question, 57% of the students reported that C++ had been harder for them to learn. "No difference" was the answer selected by 30% of the students while 13% reported that it was easier. While this may be attributed to the OOP language used (C++) rather than to the paradigm, it also may be viewed as another sign of a paradigm shift at work.
In contrast to answers on the previous question, near the end of the semester 43% of the students reported C++ was easier to program in while 30% reported it was harder to use versus structured languages they already knew. This could be seen as an endorsement of the idea that OOP is closer to the way that problems exist in the real-world.
Several interesting significant results were found when analyzing the characteristics of the students against their answers. Splitting the group by experience, those with information systems work experience split 10 students each as to whether structured programming was different from OOP (answers "different" and "very different" as opposed to answers "same," "similar," and "a bit different"). Those without relevant work experience split 8 versus 28 in favor of there being considerable difference (χ2(1, N = 56) = 4.54, p < .05). This may suggest that either students with relevant work experience were not distracted by surface-level differences or that they could not see the "true" differences between OOP and structured programming.
Also, students who knew four or fewer languages felt that C++ was harder to learn (1 or 2 languages, 11 harder vs. 7 not harder; 3 or 4 languages, 18 harder vs. 8 not harder). Students who knew five or six languages reported that C++ was not harder to learn (9 not harder vs. 3 harder; χ2(2, N = 56) 6.73, p < .05). This could support the traditional view that expertise assists these students in learning OOP.
OOP seems to be more advanced than structured programming languages in terms of technology (Boehm-Davis & Ross, 1992; Pennington, Lee, & Rehder, 1995), but it is also more complex and probably takes longer to learn (Boehm-Davis & Ross, 1992; Kim & Lerch, 1992; Rosson & Gold, 1989). Many students become confused by the bewildering number of classes and methods to be mastered (Mazaitis, 1993; Osborne & Johnson, 1993). The amount of new elements to be learned certainly contributes to learning difficulties. In addition, learning new material is made more complex when some of the elements must be learned together (Sweller & Chandler, 1994).
As a result of all these factors, "the acquisition of an object-oriented world view . . . will not happen overnight. The frustration level of experts transitioning to OOP may be higher leading to reports of disappointment and distress among such learners (and lending face validity to claims about the effects of negative transfer). Such negative factors do not mean that the switch will not take place. Alan Kay, one of creators of the Smalltalk OOP language, remembers struggling with object-oriented ideas when he was assigned to evaluate SIMULA-67 (the first object-oriented language) at the Palo Alto Research Center of Xerox. When he "suddenly saw what SIMULA was trying to be," Kay reported that "the shock of realization was so great that it was the last time I ever thought in terms of subroutines and structures" (Stewart, 1992, p. 12).
Backlund, B. E. (1997). OOE: A Compound Document Framework, SIGCHI Bulletin, 29(1), 68-75.
Beck, K. (1991). Think like an object. UNIX Review, 9(10), 39-43.
Boehm-Davis, D. A., & Ross, L. S. (1992). Program design methodologies and the software development process. International Journal of Man-Machine Studies, 36, 1-19.
Bordoloi, B., & Lee, M. (1994, Winter). An object-oriented view. Information Systems Management, 22-30.
Brooks, F. P. (1987). No silver bullet: Essence and accidents of software engineering. IEEE Computer, 20(4), 10-19.
Clarkson, M. (1992, December). What's in an object? Byte, 148.
Davis, S. P., Gilmore, D. J., & Green, T. R. G. (1995). Are objects that important? Effects of expertise and familiarity on classification of object-oriented code. Human-Computer Interaction, 10, 227-248.
D'Souza, D. (1993, March-April). An educated look at education. Journal of Object-oriented Programming, 40-46.
Détienne, F. (1990). Difficulties in designing with an object-oriented language: An empirical study. In D. Diaper, D. Gilmore, G. Cockton, & B. Shackel (Eds.), Human-Computer Interaction--INTERACT `90 (pp. 971-976). Amsterdam: Elsevier.
Détienne, F. (1995). Design strategies and knowledge in object-oriented programming: Effects of experience. Human-Computer Interaction, 10, 129-169.
Dué, R. T. (1993). Object-oriented technology: The economics of a new paradigm. Information Systems Management, 10(3), 69-73.
Dumas, J., & Parsons, P. (1995). Discovering the way programmers think about new programming environments. Communications of the ACM, 38(6), 45-56.
Eaton, T. V., & Gatian, A. W. (1996, March/April). Organizational impacts of moving to object-oriented technology. Journal of Systems Management, 18-24.
Eckel, B. (1995). Introduction. In G. Entsminger (Ed.), The tao of objects (2nd ed.). New York: M&T Books.
Fischer, G., Redmiles, D., Williams, L., Puhr, G. I., Aoki, A., & Nakakoji, K. (1995). Beyond object-oriented technology: Where current approaches fall short. Human-Computer Interaction, 10, 79-119.
Gavelek, J. R., & Raphael, T. E. (1985). Metacognition, instruction, and questioning. In D. L. Forrest-Pressley, G. E. MacKinnon, & T. G. Waller (Eds.), Metacognition, cognition, and human performance: Vol. 2. Instructional practices. Orlando: Academic Press.
Gilovich, T. (1991). How we know what isn't so: The fallibility of human reason in everyday life. New York: Free Press.
Kilian, M. (1996, June). Interpreting C++: Making Reusability Dynamic. Object Magazine, 6(4), 38-41.
Kim, J., & Lerch, F. J. (1992). Towards a model of cognitive process in logical design: Comparing object-oriented and traditional functional decomposition software methodologies. Proceedings of the CHI `92 Conference on Human Factors in Computer Systems, 489-198. New York: ACM.
Koenig, A. (1996, June). C++ as a first programming language. Journal of Object-oriented Programming, 9(3), 47-49.
Kuhn, T. S. (1970). The structure of scientific revolutions (2nd ed.). Chicago: University of Chicago Press.
Luker, P. A. (1994). There's more to OOP than syntax! SIGCSE Bulletin, 26(1), 56-60.
Margolis, H. (1993). Paradigms & barriers: How habits of mind govern scientific beliefs. Chicago: University of Chicago Press.
Mazaitis, D. (1993). The object-oriented paradigm in the undergraduate curriculum: A survey of implementations and issues. SIGCSE Bulletin, 25(3), 58-64.
Missikoff, M, & Pizzicannella, R. (1996). A visual approach to object-oriented analysis based on abstract diagrams. SIGCHI Bulletin, 28(3), 56-64.
Osborne, M., & Johnson, J. (1993). An only undergraduate course in object-oriented technology. SIGCSE Bulletin, 25(1), 101-106.
Pennington, N., Lee, A. Y., & Rehder, B. (1995). Cognitive activities and levels of abstraction in procedural and object-oriented design. Human-Computer Interaction, 10, 171-226.
Prosise, J. (1995, February 7). Much ado about objects. PC Magazine, 257 & 261-262.
Rosson, M. B., & Alpert, S. R. (1990). The cognitive consequences of object-oriented design. Human-Computer Interaction, 5, 345-379.
Rosson, M. B., & Gold, E. (1989). Problem-solution mapping on object-oriented design. Proceedings of OOPSLA '89, 7-10. New York: ACM.
Sonnentag, S. (1995). Excellent software professionals: experience, work activities, and perception by peers. Behaviour & Information Technology, 14(5), 289-299.
Sonnentag, S. (1996). Planning and knowledge about strategies: their relationship to work characteristics in software design. Behaviour & Information Technology, 15(4), 213-225.
Stacy, W., & MacMillian, J. (1995). Cognitive bias in software engineering. Communications of the ACM, 38(6), 57-63.
Stewart, M. K. (1992, November-December). The natural history of objects. C++ Report (supplement), 12-13.
Sweller, J., & Chandler, P. (1994). Why some material is difficult to learn. Cognition and Instruction, 12(3), 185-233.
Tasker, D. (1991, April 22). Object lesson. Computer World, 79-81.
Whitelaw, M., & Weckert, J. (1995). The humanness of object-oriented programming. In K. Cox, J. Marsh, & B. Anderson (Eds.), First international cognitive technology conference (pp. 115-129). Hong Kong: City University of Hong Kong.
Yourdon, E. (1993). Decline & fall of the American programmer. Englewood Cliffs, NJ: Prentice Hall.
Indiana University Kokomo
2300 South Washington Street
Kokomo, IN 46904-9003, USA
Vol.29 No.4, October 1997