You are on page 1of 7

International Conference on Computer Systems and Technologies - CompSysTech07

A Case Study in Introductory Programming


Janusz Jabonowski
Abstract: In this paper we present a case study concerning the choice of the first programming language for the computer science study. We show a small example, typical for introductory courses, then show construction of its solution in Java and conclude with some remarks, about the (in)adequacy of Java-like languages for the introductory programming courses. Key words: Computer Programming, Programming in the small, Java, Pascal.

INTRODUCTION There has been a lot of discussions (e.g. [3], [5], [6]) about choosing the programming language for the introductory programming course in the computer science curricula. Although there are many proposed languages and a lots of arguments behind all of them, it seems that C++ [9] and Java [2] have been chosen in most of the current curricula. In this small case study we are trying to show that for the aims realised during the first semester of computer study such languages are not the best choice. In fact we think that C++ in this role is not even a good choice (since it is much too complicated, as for the introductory course), so we concentrate in our paper on Java (which in this aspect is much better than C++). We would like to stress very strong at this point that the intention of this paper is not to say that C++ or Java are bad programming languages. The author of this paper has been teaching object-oriented programming and similar subjects using both of this languages for several years and can honesty say that both of them are among his favourite ones. The problem is not in the languages themselves. It is in the context in which they are going to be used and the results we want to obtain. So, what is our case when we think about first introductory course in programming? The context consists of students, who may not have much (or even may have no at all) experience in programming. And concerning the result it is not to teach them some wonderful technologies like JEE or ASP.NET (it will be time for that later during their study) but to teach them programming in the small. And let us stress: just programming, just the art of solving problems and expressing solutions in rigorous and precise way, and not programming in any particular language. The programming itself is so much important in computer science curriculum and so difficult at the same time that it is the sole subject of the course. The tool used for teaching programming is irrelevant as far as it does not hinder the teaching process. And our thesis illustrated here is that C++ to great extent and Java to some extent do hinder achieving the goals of the first programming course. What does not mean (we stress it again) that they should not be taught. Of course they should but later, not in this context and not with this aims. PROBLEM STATEMENT In the rest of this paper we will solve a problem typical for final part of an introductory programming course. So let us start with formulation of the problem. The problem is a shortened version of the original formulation from the Country-wide Open Programming Competition [7] (and is used here by courtesy of the organizers). The task: There is a conference organised, consisting of m presentations, which for some reasons have to happen all at the same time. The conference building contains a lot of rooms, each of the same size. Each room has place for up to k persons. Hence if there are
Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. To copy otherwise, to republish, to post on servers, or to redistribute to lists, requires prior specific permission and/or a fee. 2007 ACM ISBN: 978-954-9641-50-9

- IV.13-1 -

International Conference on Computer Systems and Technologies - CompSysTech07

more participants to one presentation than k, then the organisers book another room, if it is still not enough place then they book another one and so on. The organizers have to pay for the hired rooms (the cost of hiring one room is always s) and they charge the visitors for tickets. Each ticket for the i-th presentation (i stands for the number of a presentation and is in the range 1..m) costs ci. We assume that each ci is so calculated that selling tickets for half of the room makes hiring it profitable (i.e. the cost of tickets for half of the places in a room is higher than s). People wanting to come to the conference place reservations. Each reservation is for only one presentation but may ask for many tickets. As the organisers want to maximize their profits, they granted themselves the right for cancelling some reservations. The question is: having all reservation records (the number of them is l) determine which reservations to cancel, to maximize the organizers income (more precisely: compute the maximal possible income). We assume that the number of rooms is high enough to fulfil even all reservations. Of course above we have just summarize the story, to write a program we need more precise specification. Here it is (slightly modified after [8]): The program should read data from standard input and output its result to standard output. Data has the form of text lines containing integer numbers separated by spaces (at least one space between consecutive numbers). The first line of the standard input contains four integer numbers described in the previously presented story: 1 <= m <= 100, 2 <= l <= 1 000 000, 2 <= k <= 400, 1 <= s <= 1 000). The second line contains presentation costs ci (i ranges from 1 to m, each ci <= s and is such that selling tickets for half of the room is already profitable). The next l lines represents reservations. Each reservation is described in one line consisting of two numbers. The first number is the presentation number and the second one is the number of tickets (not greater than 1 000) asked for in that reservation. The required output consist of one number, the maximal income possible to obtain. SOLUTION - ALGORITHM We will not analyse here the problem in details, instead we will give the general idea of the solution and the we will skip to the implementation which is most interesting for us here. Of course during regular lesson we would concentrate on the solution itself, hoping to have enough support in the tool (the chosen programming language) used, to be able to easily formulate our algorithm in the form of a program. It is easy to see, that all presentations can be handled independently, so we can concentrate on finding best solution for one presentation. From now on we will use c without index to refer to the ticket price for the presentation under consideration. Obviously all large reservations (i.e. such that the number of requested tickets multiplied by the ticket price is larger than s) should be preserved. If we sum up all requested ticket numbers and divide the sum into k (the room size) we get as the integer result the number of full rooms and as quotient (let us call it q) the number of persons in the last room. If the price of requested tickets in the last room is larger than s, then we are done we accept all reservations. Otherwise we have to consider cancelling some reservations to free the last room (but freeing the last room does not have to be necessary in this case, consider for example room size k = 10 and only one reservation for 11 places). Since hiring half of the room gives income for the organizers, we need to free that last room only when there are some reservations, which sums up to a number of tickets greater or equal q but not large enough to pay for one room (i.e. let t be the sum of tickets requested in those reservations, then it must hold that: t >= q and t * c < s). Of course we have to find smallest such t. Hence we have a typical use of the classical knapsack problem and we - IV.13-2 -

International Conference on Computer Systems and Technologies - CompSysTech07

have to use dynamic programming to decide, whether we need to cancel some reservations and free the last room or not. SOLUTION IMPLEMENTATION So let us now take a look at the implementation in Java. Unfortunately there are many obstacles in front of us. First one is that we want to write a program which has quite simple internal structure: it reads data, computes results and outputs them. All we need to make it a properly structured is to write few routines (we may call them methods or procedures). We do not need to create own classes and objects. Of course not because object-orientation is useless or we cannot define some classes. Object-orientation is nowadays the best answer of the entire software industry to the demands of today's market. And of course we can define some additional classes here. But the problem is that our program, although far from trivial, does not require the full power of object orientation nor does it require definition of some new classes (types). It will show to be extremely useful to use some predefined objects (as streams or collections) but we will not need objects of own classes. Why does it matter? Because solving such problems in Java strongly drives us to misuse of classes. Since the problem itself does not require creating new objects it is quite common to define all needed routines as class methods (or static methods if one prefers C++ jargon). So we are pushed to define class methods not because our object oriented model needs them (we do not have any object oriented model here) but just because we do not require object creation. Let us note by the way that also the main method is static. Taking into account the fact that classes are not meant to be first-class citizens in Java (it is only reflection which allows us to talk with class representations) using Java for solving such simple (from the object-oriented point of view) problems results in using objectoriented environment in an counter object-oriented style. Not to mention the question of deciding how to explain to students the need of adding the static keyword to all methods and variables (or attributes, if we decide to use object-oriented terminology, which is generally better, but the problem here is that we do not know what are this attributes of). The other way would be not to use class methods, but to create object of our main class or to define other class and create its objects. But since we do not need our own objects (we define them just to not use the keyword static') this solution is also artificial. So by now we may end up with main method like this:
public static void main(String[] args) throws IOException{ readData(); // Let's calculate the result (for each presentation independently)... int income = 0; for(int i=1; i<=m; i++){ income += computeResult(sumOfLarge[i], small[i], k, s, price[i]); } // ... and output the result System.out.println(income); }

Second problem concerns data flow. Our method for getting data from standard input does not have parameters, what is a very bad solution when examining the main method we do not see the data flow. What is the reason that the programmer did not add parameters to readData? Because he could not. Parameters in Java are always passed by value1, what is perfect for input parameters but generally does not work for output ones. What could be done to help here? Well, one could define new helper class, with so many attributes as parameters to be passed, proper constructor and a set of getters (one for
1 Note that when passing objects to methods one actually passes (by value) the reference to an object. So also in that case there is passing by value.

- IV.13-3 -

International Conference on Computer Systems and Technologies - CompSysTech07

each parameter). Then redifine readData as a function returning new object of this helper class and after the call use getters to access the read data. One could do that, but it is much easier not to do that, but just move declarations of all variables out of the main method. The problem is here, that language used for teaching young programmers should make writing better programs easier and not harder, as it is in this case. One can argue, that some environments could half-automatically refactor code to the better solution. But note that refactoring also requires understanding it, so we require the student to understand algorithms, then a language for describing them and now also some obviously powerful, but hidden somewhere in the environment refactorings. But we wanted at the beginning to make things simpler by choosing Java (as good language which it in fact is), not more complicated. So there is a good chance, that we end up with declarations like that (at the class level, again with lots of artificial static keywords):
static static static static int m, l, k, s; int[] price; long[] sumOfLarge; ArrayList<Integer>[] small;

The first line declares variables for storing the number of presentations, number of reservations, room size and room cost respectively. The second line contains declaration of an array price for storing prices of presentations. The third line introduces sumOfLarge, the array for summing numbers of tickets in large reservations (we do not have to store the large reservations themselves). And finally the last line declares an array called small containing collections (with one collection for each presentation, ArrayList type was chosen here). It is introduced for storing size (the number of required tickets) of each small reservation. Here we see the third obstacle: how to explain to students in an intuitive way why we had to write Integer where we wanted int (in the declaration of the ArrayList)? It is difficult because it is just not intuitive. We just have to write it so, because of internals of the generic types implementation in Java. And in fact the reason lays even deeper the type system of Java (much older than generics in Java) which allows few non-object types (int being one of them). As a lecturer we have two solutions, both bad. First one is to say that for some reasons we just need to write Integer here, and we do not care why. The obvious drawback of this solution is that it makes students think, that the tool (the language) they are using is very complicated and beyond their comprehension capabilities. It is difficult to find something more discouraging the will for self-study! The second solution is to describe precisely internals of generics implementation. It is nothing particularly wrong with such description, in fact it is needed and sheds more light on the internal working of programs in Java. But first semester is the wrong place for such discussion we have quite different aim in mind, we want to teach programming understood as the activity of problem solving. We want our students to understand and use for example the notion of loop invariant (extremely useful and extremely difficult to teach subject), and not the peculiarities of implementations of some languages (not now). Now comes the fourth obstacle. Let us take a look at the method for reading data (for brevity we will show only fragments of this method).
public static void readData() throws IOException{ Reader r = new BufferedReader(new InputStreamReader(System.in));

- IV.13-4 -

International Conference on Computer Systems and Technologies - CompSysTech07


StreamTokenizer sTok = new StreamTokenizer(r); sTok.parseNumbers(); // First line sTok.nextToken(); m = (int) sTok.nval; sTok.nextToken(); l = (int) sTok.nval; sTok.nextToken(); k = (int) sTok.nval; sTok.nextToken(); s = (int) sTok.nval;

Java provides programmers with powerful set of streams and operations on them. In particular the set of streams is build according to the Decorator design pattern to enable flexible assembling of streams best suited for the task at hand. All this is true, but in this program we would rather expect one line with one simple input statement for reading four integers. In the code above we have three (!) stream objects, one tokenizer object and four castings. Surely this is not the code we would like to deal with in introductory programming course. Instead of focusing on the real problem (finding proper algorithm and code it in simple, readable way) the student has to struggle with lots of tools, unnecessary for her at this level of learning. But we must admit that since the Java 1.5 release the situation is much better, because we can now use the Scanner class, which greatly simplifies reading values of standard data types and eliminates type-casting, as can be see in the following example:
Scanner sc = new Scanner(System.in); m = sc.nextInt(); l = sc.nextInt(); k = sc.nextInt(); s = sc.nextInt();

And in the same method we find another, already fifth, obstacle.


// Now the second line price = new int[m+1]; for(int i=1; i<=m; i++){ sTok.nextToken(); price[i] = (int) sTok.nval; } // ... to be continued

Everything seems to be natural here (apart from the casting we have discussed already before). But there is another one artificial element in the above code. It is the size of the array. Since arrays in Java have zero-based indexes, if one wants to number things (like presentations here) from one then she has trouble, and has to declare one-to-big array as we did (and forget the first element, that with index zero) or to declare the array with proper size and always remember to subtract one from the desired index. Is it a problem to number things form zero? Certainly is. First of all, counting from 1 is what we were taught at schools. Secondly sometimes (like in this task) the formulation of the problem involves numbering array elements from a number other than zero. So we have another small inconvenience effectively driving our attention from real problem solving to small, unimportant but bothersome details. - IV.13-5 -

International Conference on Computer Systems and Technologies - CompSysTech07

The sixth obstacle is again related to some shortcomings of the implementation of generics in Java, so we will not discuss it here, we just show the code, where raw collection (i.e. one stripped from the type information about its contents) has to be used.
small = new ArrayList[m+1]; // raw collection type

CONCLUSIONS AND FUTURE WORK We have illustrated with a small example the virtues and drawbacks (mainly the drawbacks) of using Java for teaching introductory programming. One can of course argue that all of them may be overcome by providing a suitable packages (for example for reading data). But then, what is the point in choosing for teaching one language and immediately hiding it under an umbrella of specially designed packages? We want to stress here again that this paper is not meant as a criticism of Java (or C++ which was mentioned in the introduction). Java is a great language (although with some weaknesses, but nobody is perfect), with lots of applications and powerful IDE's (like NetBeans, Eclipse or IDEA). There are many advanced technologies build around Java (like servlets, JSP pages or JSF just to enumerate some of them). The point of our paper is only such that this tool is not proper for introductory programming courses, because of the context and aim of this teaching process. And to conclude with a constructive conclusion: we have described what we think is not the right solution, so what could be used instead? Our answer is that the old, good Pascal [4] (considered just as a language of while-programs with procedures) has all needed machinery (and nothing more) to be successfully used in such courses. Of course there are more options to choose (Smalltalk [1] being one of them). REFERENCES [1] Goldberg,A., Robson,D.; Smalltalk 80: The Language (The Blue Book); AddisonWesley Professional; 1st edition; 1989. [2] Gosling J., Joy B., Steele G., Bracha G.; The Java Language Specification, 3rd edition, 2005; Sun Microsystems. [3] Gupta D.; What is a Good First Programming Language?; http://www.acm.org/crossroads/xrds10-4/firstlang.html. [4] ISO; Pascal ISO 7185:1990. [5] Jabonowski J.; Some Remarks on Teaching of Programming; Proceedings of the 5th international conference on Computer systems and technologies, June 17-18, 2004, Rousse, Bulgaria. [6] McIver L., Conway D.; Seven Deadly Sins of Introductory Programming Language Design; http://www.csse.monash.edu.au/~damian/papers/PDF/SevenDeadlySins.pdf. [7] Potyczki algorytmiczne 2007; Country-wide Open Programming Competition 2007; http://www.konkurs.adb.pl/user.phtml. [8] The original statement of the problem used in the paper (from the competition site [7]); http://www.konkurs.adb.pl/pracownicy/user.phtml?op=zadania. [9] Stroustrup,B.; The C++ Programming Language (3rd Edition); Addison-Wesley Professional; 3rd edition; 1997. ABOUT THE AUTHOR Assisting Prof. Janusz Jabonowski, PhD, Institute of Informatics, Warsaw University, Phone: +48-22-55-44-484, -mail: janusz@mimuw.edu.pl, Web page: http://janusz.mimuw.edu.pl. - IV.13-6 -

International Conference on Computer Systems and Technologies - CompSysTech07

APPENDIX Just for those curious, the computeResult method.


public static long computeResult(long sumOfLarge, ArrayList<Integer> smallOnes, int roomSize, int roomPrice, int ticketPrice){ int sumOfSmall = 0; for(long elt: smallOnes){ sumOfSmall += elt; } long sum = sumOfLarge + sumOfSmall; long roomNo = sum / roomSize; // these rooms are full int profitable = roomPrice / ticketPrice; if (roomPrice % ticketPrice != 0){ profitable++; // sufit } int rest = (int) (sum % k); // no of persons in the last room if (rest == 0){ // they fit perfectly return (sum*ticketPrice - roomPrice*roomNo); } else if (rest >= profitable) { // let us take them all return (sum*ticketPrice - roomPrice*(roomNo+1)); } else { // real computation boolean[] isPossible = new boolean[profitable+1]; for(int i =1; i<=profitable; i++ ){ isPossible[i] = false; } isPossible[0] = true; for(int elt: smallOnes){ for(int i=profitable-elt; i>=0; i--){ // important to go from right to left! if(isPossible[i]) isPossible[i+elt]= true; } } // Look for first true with index >= rest for(int i=rest; i<=profitable; i++) if (isPossible[i]){ return ((sum-i)*ticketPrice - roomPrice*(roomNo)); } return (sum*ticketPrice - roomPrice*(roomNo+1)); } }

- IV.13-7 -

You might also like