Tartalmi kivonat
Teaching programming using JavaScript Peter Warren, Information Technology Programmes, University of Natal, Pietermaritzburg peterw@cs.unpacza Abstract There is a growing concern that standards in elementary programming courses are declining, yet these courses remain a major stumbling block for many students. The blame has been attributed to the increasing complexity of modern programming languages and their environments. The proposed solution is to reduce the initial complexity level, and this paper explores ways to do this using spreadsheets and JavaScript. Spreadsheets provide a gentle introduction to programming because all the data are visible, greatly reducing the level of abstraction required from the student. JavaScript is a suitable vehicle with which to continue because it removes unnecessary complexity. JavaScript has a dynamic type system, its arrays are dynamic, heterogeneous, associative and sparse, and finally object creation is vastly simpler than in class-based
languages. 1. Introduction Proulx [13] comments that the first programming course is a major stumbling block for many students and that “some otherwise competent students cannot program independently a simple loop”. She blames the increasing complexity of programming languages. It is certainly our own experience The point is further emphasized by the loss in algorithmic complexity in modern textbooks (e.g [8] [2] compared with the older materials [9] [1]). Less well-prepared students entering tertiary education in South Africa further compounds the problem. We believe that this amounts to a crisis in the teaching of entry-level programming, which has to be addressed by a radical rethink of what we do. If languages and environments are too complex, the solution is to reduce their complexity for the novice. In simulations there is a trade off between realism and simplicity [18] Too much realism brings with it inevitable complexity which slows or even stops the learning process.
Conversely too much simplicity makes transfer to the real world problematic. Another insight comes from the review of mental models in [11] as applied to user interface design. A novice creates an initial model of how the information fits together which is later elaborated. Finally the minimalist techniques of [3] produce further evidence that reducing the initial complexity can enhance the speed of learning of the whole system. All this confirms we should start simply if we are to overcome the current impasse. Warren Page 1 of 9 It is worth noting that it is not whether the complexity of the construction of modern software needs to be mastered, but how students can get to master the complexity. We are going to argue that inter alia JavaScript is a suitable vehicle for preparing students for doing this. It is not claimed that this is a better language for large projects, or that learning difficulties should force a rethink of the way programming languages are designed. Such issues
are simply beyond the scope of this contribution 2. Problems with programming in Java and C++ 2.1 Framework This section examines those aspects of the Java/C++ (J+C) model that cause the novice to have unnecessary difficulties with programming. We will analyze the situation in terms of some of the issues known to cause learning problems with user interfaces. • • • • Gratuitous complexity. Complexity is gratuitous if it contributes nothing to the task in hand even if it does assist in some other task [18] (page 135). The novice can well do without this hurdle. Inconsistency. Inconsistency is always a problem because it requires that the material be learned twice. A particularly pernicious form of inconsistency is where the syntax suggests an interpretation different from the actual semantics [4] [12]. Modes. Modes cause difficulties as systems behave in differing ways, and hidden modes are even worse [14]. Implementation issues. Implementation issues, which are not part of the
novice’s mental model, cause learning difficulties [12]. Irrelevant efficiency issues are but one example of harmful implementation concerns. Such issues are not unique to user interfaces but will cause difficulties with the learning of any kind of system. It is not claimed that they will expose all learning problems with programming. It is a vantage point, other vantage points may well throw up other problems. They do, however, identify a number of concerns that need to be addressed. It will not eliminate anything like all the learning problems that novices have, but it can reduce their number. 2.2 Some examples of problems Below is a catalogue of some of the unnecessary problems that novices can be expected to encounter with J+C. These issues are raised in the context of a novice only and examined in terms of the above framework. In Section 4 we will argue that using spreadsheets and JavaScript to teach the algorithmic concepts can obviate many of these difficulties. It is not a
detailed critique of Java or C++ Variables create a lot of problems. A variable is essentially a hidden mode, which causes code to behave in different ways. Further the concept of a variable is inconsistent with its mathematical interpretation. The primitive type system of J+C is a mass of gratuitous complexity. C++ is considerably worse than Java in this respect, the reforms in Java seemingly Warren Page 2 of 9 acknowledging the problem but hey do not go far enough. The existence of many different integer and floating point types with peculiar names (like double) has very little to do with elementary algorithms and everything to do with implementation issues in obsolete architectures. The model of reals and integers as separate types is inconsistent with mathematics where integers are a subset of the reals. Strings and numbers are compared differently and this is a concept that cannot easily be avoided. Nevertheless we can expect problems with the difference between ‘23’ and
23 as the novice will see the differences as inconsistent. Further the introduction of a character type seems an unnecessary addition of no algorithmic utility and is an example of gratuitous complexity. The whole concept of a type can be traced back to Aristotle yet it has been abandoned by philosophers and cognitive scientists [16] and attacked by some Computer Scientists [7]. Types are inconsistent with the way people actually think [17] The novice can recognize the type from the content accurately enough to write elementary programs. Having to predefine variables at the outset just introduces gratuitous complexity from a novice’s point of view. Those who remain puzzled by this position are asked to contemplate the additional complexity that would be introduced into spreadsheets if the type of each cell had to be predefined. Objects in J+C introduce a number of difficult concepts, which are not needed to solve elementary problems. Here are two A novice trying to develop an
algorithm has little need to face the additional complexity of writing accessor methods. Inheritance can lead to counter intuitive results, for instance, it only adds data so one winds up with a rectangle being a special kind of square. We need to be careful that object orientation provides the novice with support and not another piece of gratuitous complexity. Unfortunately in J+C the syntactic overhead with objects is also considerable. Our experience in teaching object orientation for a data structures course in C++ is that the amount of code required to construct the classes exceeds the amount required to perform the algorithm on the data structure. Similar experiences with two Java exercises confirm this. A heap implemented in JavaScript consisted of approximately 100 tokens while the Java implementation was 400 tokens. The Sieve of Eratosthenes implementation in JavaScript was 90 tokens while in Java it was 170 tokens. The additional complexity in Java is necessary for industrial
strength programs, but for teaching the concepts behind the sieve or heaps it is simply gratuitous complexity. Functions in C++ have value and reference parameters. The reference parameter mechanism destroys the semantics of a function as a computational device that maps values onto values and is an example of an inconsistency. Reference parameters are thus double trouble for the novice, something new to learn to help them misunderstand computing. In Java the situation is even worse than in C++ Java, JavaScript has no explicit reference parameters, just reference objects. Since object creation is tedious it is not feasible to pass an object back as a function result, which encourages the use of the reference parameter mechanism as the alternative. However it is inconsistent as it is only possible for objects and not for primitive types. Arrays in C++ and Java are mappings to memory, which means they are of fixed size, store homogeneous types and are dense. This is an implementation
issue There are many further inconsistencies in C++ if one is not aware that an array is a pointer. But the syntax is not that of a pointer, which is a hidden mode the novice must contend Warren Page 3 of 9 with. Although J+C provide container classes to avoid the problem, the novice is faced with the gratuitous complexity of a choice of techniques. The problems that systems have with memory leaks should convince everybody that programmers managing their own memory is a bad idea. Once again the intrusion of memory management issues into data structures is a bad decomposition of the problem for everybody let alone the novice (gratuitous complexity). Fortunately Java has automatic memory management. As far as we know there has been no study of the influence of the complexity of the programming environment on the ability of a student to learn programming. Tools like Visual C++ are designed to support a professional programmer and they make a very poor job of supporting the novice.
Personal experience with programming environments and the views of Cooper [4] on the negative effects of gratuitous complexity in word processors is sufficient evidence to contend that simpler tools would be more productive. In conclusion, the cognitive overload in learning to program in J+C is very high. The list is no doubt incomplete and a more structured analysis could well expose more problems. This is not the issue here The discussion is sufficient to demonstrate that it is hardly surprising that J+C programming is a major stumbling block to many students. Any reduction in the setup costs these students experience will be worthwhile. 3. A brief overview of JavaScript JavaScript is a programming language introduced by Netscape for use in browsers. The Microsoft version is called JScript and the version standardized by the European Computer Manufacturers Association is called ECMAScript [5]. Netscape describes it as a smaller language than Java in the spirit of dBase and Hypertalk
[10]. There is much in common with the NewtonScript [15] object model. Such languages, say Netscape, offer programming tools to a much wider audience because of their easier syntax, specialized built-in functionality and minimal requirements for object creation (our emphasis). JavaScript only runs in browsers It has very limited I/O support only being able to process the notorious cookies and has no support for graphics. However, it would be a mistake to dismiss it as a toy language. It is a sophisticated modern object based language despite these restrictions. JavaScript is not a watered down version of Java. The similarity stems from the fact that they are both descended from C++ and the name is a marketing ploy [6]. The major philosophical and practical difference is that JavaScript is dynamically typed while in Java the typing is static. The consequence of dynamic typing is that there is no need to declare variables. If a variable is used as an ‘rvalue’ without having been
declared an error will occur. JavaScript has a reduced number of primitive types compared with J+C. Numerical values are handled only by “numbers” There is a string but no character type. However, there is a Boolean type Conversion is automatic, the language trying to do the most sensible thing but not always getting it right. Arrays are dynamic, heterogeneous, sparse and safe. Associative arrays are supported but they are no different from objects, thus obj[x] is the same as obj.x Since Warren Page 4 of 9 everything is dynamic, properties may be added or deleted at runtime. JavaScript is an object but not a class-based language. An object is created by simply stating its properties for instance, return {x:1,y:4,z:7} can be used to return a vector from a function. Functions are first class objects, and may be assigned to variables and thus be attributes of objects. These functions now look like methods and the “this” and the “dot” operators are available. Inheritance
can be implemented It would be fair to say a class-based approach is supported but not required. Otherwise the syntax is vintage C. 3.1 Problems with JavaScript Like Java, JavaScript has primitive and reference variables [6]. The latter have the syntax of primitive types but the semantics of pointers. This allows JavaScript to have arrays of seemingly heterogeneous objects, greatly simplifying the programmer’s view of the world – and providing unexpected complexities later. Declaring a variable in a function has the effect of making it local. This is not the semantics that one would associate with the process. JavaScript freely converts from one type to another, simplifying the programmer’s task but creating an illusion of an un-typed language. Further the overloading of the plus operator is going to make it very difficult to explain that 2*3 is 6 while 2+3 is 23. All of the above are examples of hidden modes. 4. The proposed solution We will now discuss how to exploit the
advantages of spreadsheets and JavaScript to reduce the complexity that a novice faces in a first programming course. 4.1 Using spreadsheets If variables are the hidden modes of programming, the solution is to make them visible, and we can do this by using a spreadsheet before tackling a programming language. There are a surprisingly large number of concepts that can be handled this way [19]. Two are of particular importance The cell model of memory in spreadsheets makes the whole concept of a variable concrete and displaces the mathematical concept . Evaluating recurrence relations provides the basis for many loops in a highly visible manner. The other advantage of spreadsheets is that the issues can be tackled without the complexities of J+C and their programming environments. 4.2 Using JavaScript The programming environment. Only a very simple text editor, which supports line numbers, is needed to develop JavaScript programs. Our experiences with novice programmers are that it is
better to do without some features, than to overload the environment with too much gratuitous complexity. It would be an advantage if the browser could be launched from within the editor. So far we have used Note Pad which does not support line numbers. Warren Page 5 of 9 Functions. Functions can be used as a model of computing which is consistent with the mathematical notion of a function. We would like to keep it that way as far as possible and at least to start that way. Our first example is to construct a calculator based upon three “input” fields and four buttons. A two-tier architecture is introduced, with the function doing the computation and the event handler dealing with the issues of moving information to and from the input fields. It creates an understanding of functions as free standing interchangeable units doing computation. No attempt is made to prevent division by zero - infinity is safely returned in JavaScript (removal of gratuitous complexity). The simple
calculator allows a number of straight-line programs to be constructed which develops the problem solving skills of students. We asked students in an introductory C++ course to do the exercise. They were given a short introduction to the basic HTML form, shown how to write an event handler, and a very brief conversion course from C++ to JavaScript. They experienced no difficulty in the JavaScript but some basic computer literacy problems surfaced. They also struggled with the algorithms (for instance finding if a number is prime), but we already knew that the traditional approach was failing to get these concepts across. Events and non Events. There is a propensity of students to want to see the whole program which is not always possible. We wish therefore to write individual pieces of code each doing independent tasks and event handlers provide such an opportunity. We look at these in the context of “roll overs” which offer an immediately visible effect so the degree of
abstraction is reduced (removal of hidden modes). We elaborate on events from the point of view of a computer executing a series of sequential steps unless there is some specific exception to this rule. It is tedious to debug functions unless the more conventional input and output is available, so these topics are also covered. We use these to illustrate the more traditional question and answer kind of program. Selection. The traditional approach to selection sees it as distinguishing between alternative courses of action. However, students will have seen the “if” as a function returning a value in a spreadsheet so we treat selection as a table look up process initially. This is to provide consistency with what they already know Associative arrays are then introduced as another form of table lookup. An interesting case study is the standard quadratic equation solver. The particular version of the problem [9] called for the return of zero, one (degenerate case) or two roots. The
example is instructive in JavaScript as we do not need to handle exceptions and that we can easily return an array of zero, one or two roots. Repetition. There are two important programming patterns that beginners stumble on, firstly computing the result for a recurrence relation and secondly data structure traversal. Sequential search is a particularly important sub-problem where the traversal of the whole data structure ends prematurely. We only look at these two problems. To do so we only need one form of the loop, the for loop This express the fact that most repetition problems consists of initialization, a test to see if a loop has terminated, an incremental step and a body. Post processing is the last activity although the ‘for’ loop does not explicitly deal with this step. Warren Page 6 of 9 The importance of JavaScript is the ease of use of dynamic arrays maintaining their own length, which means this topic can be covered where it belongs - with loops. The removal of
complexity in the tool means we are able to tackle and explore more complex algorithms and there are many of them in this context. Objects. Objects are introduced at the start of this course as we use a model of a function as taking information and returning information. An object is a useful wrapper to return composite results. The “document object” is also used so the idea of sending a message to an object is understood. It is only a small step syntactically to add functions as attributes of objects. The next step is to add a constructor so that multiple examples of the same kind of object can be created. Then there is the need to realize that each object has to store the functions and that is a “bad thing”. The techniques of prototypes are thus introduced as the need for them becomes apparent. Finally inheritance is introduced using the same mechanism. An advantage of JavaScript is that the class-based concepts can be introduced, as they are needed to simplify the
student’s life not to complicate it. This cannot be done in a class-based language where the overhead is present right from the start. (Reduction in gratuitous complexity.) Data structures. With dynamic arrays the construction of stacks and queues from an object orientation point of view is not only possible but also desirable. Since an array is a list in the LISP sense, and can contain heterogeneous objects, the techniques used in that language to implement trees only require a straightforward translation to JavaScript. The tree is a convenient place to develop recursive methods Graphs can be implemented using adjacency list techniques or as a set of nodes and a set of arcs. The use of associative arrays greatly simplifies the task. With dynamic arrays, linked structures are of little utility. However, the ACM curriculum calls for an understanding of pointers. There is no difficulty in implementing these in JavaScript. The only rethink we had to make was that a tree always exists
even if it is empty. We found this more consistent with our thinking of about a tree than a null references representing an empty tree. Consider the tree constructor function tree(){}. Exception processing. The need for early concern about exception processing is greatly reduced in JavaScript as indexing outside the bounds of an array and division by zero are not exceptions. This reduces gratuitous complexity This means that exception processing can be delayed until such time as the students are ready for the exception model. This avoids having to teach a fundamentally wrong model of exception processing, namely that of writing out an error message in a function, a technique that totally destroys the functional model of the computation. 5. Discussion and Conclusions We believe that there is a crisis in the teaching of introductory programming courses and that the four concerns of i) gratuitous complexity, ii) inconsistency, iii) modes and iv) implementation issues in J+C contribute to
that crisis. Spreadsheets remove the problem of a variable being a hidden mode, thus freeing the student to concentrate on other issues, and providing a model for variables. JavaScript has sufficient richness to cover most of what is required in an elementary course and it is a real language Warren Page 7 of 9 with immediate application for the student. At the same time it can use a simple editing environment, the complexity of the language is reduced, the consistency is improved, and many implementation issues regarding arrays and types are avoided. The last issue is whether such a course can be constructed. Our conclusion is that it can be. Complexity can be added when it is needed to solve problems rather than an overhead, which the novice has to face right from the start. The additional advantage is that the underlying syntax is virtually identical to J+C and there is little to unlearn as even the class-based approach has been introduced. This will ease the transition to J+C
or other class-based languages which is our ultimate objective. An anonymous referee complained that our position was to “ensure that conceptual contrasts, with everyday thought, are minimised at the start, or at least that they enter one at a time, not too thick-and-fast”. This expresses our position far more eloquently than we have been able to articulate ourselves. If this is not done the result is the teaching of a programming language and not the teaching of programming. Furthermore we do not believe that is inconsistent with “going the other way, be at pains to draw students attention: yes, this is something different from the way we normally think” (referee again). On the contrary, along with [3], our argument is that by starting slower to start with we can get there faster. One drawback is the paucity of suitable educational material as the existing texts teach JavaScript and not programming. The books we have looked at in J+C, however, suffer from much the same
problem. The question has been raised about the evidence that supports these claims. This question in turn usually requires empirical evidence to be presented. Such evidence is seldom forthcoming, and when it is available, is subject to considerable uncertainty in the interpretation. The evidence at this stage is indirect based upon LISP and Perl courses and draft notes. On the other hand there is plenty of evidence that the current approaches do not work despite claims of support from empirical data. There is no substitute for examining the theoretical claims presented here, and we invite that evaluation. Acknowledgements. This research was done while the author was on sabbatical leave in the supportive environment of the Computer Science and Information Systems department at the University of Port Elizabeth. Several colleagues especially Janet Wesson, Larry Tooke and Lester Cowley have contributed to sharpening the arguments. References [1] [2] [3] [4] E.I Organick & WStenberg
AI Forsythe, TA Keenan, Computer Science A first course, John Wiley and Sons, New York), 1969. Scott R. Cannon, Understanding programming An introduction using C++, West Publishing Company, Minneapolis/St Paul, 1997. John M Carroll, The Nurnberg funnel : designing minimalist instruction for practical computer skill, M.IT Press, Cambridge, Mass, 1990 Alan Cooper, The inmates are running the asylum, SAMS, 1999. Warren Page 8 of 9 [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] ECMA, EcmaScript: A general purpose, cross-platform programming language (standard ECMA-262), ECMA - European association for standardizing information and communication systems., 1997 David Flanagan, JavaScript : The definitive guide, O’Reilly and Associates, California, 1998. William Kent, Data and reality: basic assumptions in data processing reconsidered, NorthHolland Pub. Co, New York, 1978 P.A Lee and C Phillips, The apprentice C++ programmer, a touch of class, International
Thompson Computer Press, London, 1997. Andrew D. McGetterick and Peter D Smith, Graded problems in Computer Science, AddisonWesley Publishing Company, London, 1984 Netscape Communications Corporation, Mountain View, CA, Core JavaScript guide, 1998. W.M Newman and MG Lamming, Interactive system design, Addison-Wesley, Harlow, Essex, 1995. D.A Norman, The psychology of everyday things, SAMS, 1988 Viera K. Proulx, Programming patterns and design patterns in the introductory computer science course, Proceedings of the thirty-first technical SIGCSE technical symposium on Computer Science education (Austin, TX, USA), March 7-12 2000, pp. 80–84 Jef Raskin, The humane interface, Addison-Wesley, Reading, Massachusetts, 2000. Walter R Smith, NewtonScript : prototypes on the Palm, Prototype-Based Programming. Concepts, Languages and Applications, Springer-Verlag, Singapore, 1999. Antero Taivalsaari, Classes and prototypes. some philosophical and historical observations, Prototype-Based
Programming. Concepts, Languages and Applications, Springer-Verlag, Singapore, 1999. Tim O’Shea Moina Minoughan & Randle B. Smith Thomas RG Green, Alan Boring, The Stripetalk papers. Understandability as a language design issue in object-oriented programming systems, Prototype-Based Programming. Concepts, Languages and Applications, SpringerVerlag, Singapore, 1999 Stephen M. Alessi & Stanley R Trollip, Computer-based instruction, 2nd ed, Prentice-Hall, New Jersey, 1991, Fidelity in simulations. Peter Warren, Spreadsheets, Unpublished notes University of Natal, 1999. Warren Page 9 of 9