Business administration yesterday afternoon, practical programming this morning; and both exams were harder than we expected. Business administration only slightly so, to be sure, but programming was murderous. And to think that only a few weeks ago I thought these two were the exams I had least reason to worry about.
In fact, business administration was almost exactly what we expected. Quite a number of the problems, particularly most of the bookkeeping transactions, were actually identical to those of an earlier exam, and since we were allowed to bring absolutely everything as long as it couldn’t connect to the internet, most of us had copies of the old exams complete with solutions, so there. What came as a surprise was that the mortgage calculation we had rightly expected having to do was complicated by introducing a disagio (apparently called discount points in Angloamerican usage), which our professor had never mentioned except in passing in the final lecture last week, so we had no idea how to deal with that. What surprised me even more was that I needed 70 of the 90 minutes alotted for the exam just to complete all the problems once without doublechecking my calculations. Our professor had claimed the exam could easily be completed within 60 minutes, probably even within 40.
But hey, that’s just saying getting an almost certain A took a little more effort than we had thought. Programming was a different kind of animal entirely.
Naturally it didn’t help that I slept very badly the night before in spite of telling myself in good faith (not knowing how mistaken that would turn out to have been) that in programming I had nothing to worry about. (As I said, my subconscious was starting to get in the way.) In the morning I was on campus almost an hour early, like most people. Everybody seemed rather nervous, and nobody did any serious studying. We were just hanging out in the Cafeteria or crowding in the narrow corridor before the PC labs, hastily discussing solutions to problems that were likely to come up, probably accomplishing nothing except making everybody even more nervous.
The whole setup of the examination was designed to impress of with the sober importance of the event. The lengthy procedure of filing into the room, signing the attendance list, thereby acknowledging that we were present, fit, and physically able to take the exam (for fear of somebody claiming in the middle of it that s/he was really sick and couldn’t continue), being distributed into the various adjoining computer labs in small groups of 8 or 9 (and per the list there were 61 of us, total), going through the printed sheet on one’s desk that contained assorted instructions, admonitions, warnings, and threats in case of noncompliance under the watchful eyes of a large group of CS department staff, filling in a form with one’s personal details, logging into the specially prepared examination account, starting up Eclipse, and finding a project already there which only lacked the solutions: It had something of a mix of a Catholic church ritual, a courtroom, and being admitted to prison as an inmate.
In spite of that I was rather cheerful when it started, because the problems looked quite manageable, and there were only four of them to complete in 180 minutes, as compared to three in 90 minutes in the mock exam. No. 1 was a day-of-the-week translator, German to English, no. 2 asked us to compute the average of the sum of the non-nil elements in a collection in three or more different ways, and no. 3 had us write a deque based on Ruby’s Array class. The only one a little more involved was designing a “Part” class whose objects might recursively contain other Parts. Yet that problem was broken down into seven specific assignments, so it looked like you could just tick those off one after the other and be done, without giving design decisions any particular thought.
And I got off to a good start. I overdid the translator by matching the German days of the week with regular expressions so they could be entered capitalized or not, abbreviated or full length, and was briefly surprised by one test not passing because the translator returned Sunday when the test expected Saturday, but that was only because I had picked the common German Samstag instead of the rather Hamburg-specific Sonnabend as the German version (our professor is a real Hamburger to be sure). I had some problems with the test setup for the average calculations, because the summary test method provided by our professor just passed without testing anything. I recalled having had the same problem in the mock exam, but thought it was a problem in the tests, and asked the professor (fortunately he was around for the entire exam). He kindly pointed me to the fact, that in a Ruby script, as opposed to a class file, methods are not automatically public, so we had to declare them so, in order for the tests to find them. He also remarked that I was not the only one to have that problem, but that in my case he was surprised I didn’t know. Ouch.
Anyway, when I had three versions of the calculation, but one of the seven tests still not passing, I decided to move on, as our tutors had advised us not to get bogged down on trying to solve a single problem. Better get back to it when there’s still time later. So I quickly wrote the deque, complete with comments, all tests passed.
That was less than an hour into the examination. Three problems almost done, for 60% of the total possible points. More than two hours left for solving the final problem, the “Part” class, and then quickly fixing the averages calculation. Nothing could go wrong.
I typed the code for the “Part” class, all seven assignments, within 5 minutes, and ran the tests. More than half of them hung. Well, that was to be expected: after all it was only a quick and dirty draft of the class yet. I actually like TDD, the game of methodically fixing one method after another until all the tests pass. So I ironed out a couple of problems and was at 9 assertions, 7 failures.
I don’t think I’ll be forgetting these numbers quickly, because I was staring at them for the next hour. Solid.
I have had problems finding bugs at times. I have been chasing individual ones for the best part of a day. But usually these involved either very subtle errors on my part, or intricacies of a language’s syntax that I simply wasn’t aware of. But this here was not subtle. In fact it was brutally simple. If you stick a Part object into a Part object, it should be there. If you take it out, it should no longer be there. That kind of thing. Should have been simple, yet I was unable to solve it. And the clock was ticking, and whatever I tried, I got “9 assertions, 7 failures,” and slowly I was beginning to panick. What if this really took half a day to figure out? What if I flunked the exam on that account? My mind was racing, but I simply couldn’t make sense of it. It should have been simple, but it wasn’t. The test code our professor had provided was very hard to understand, and so was the output, particularly since the to_s (to string) method I had written tended to produce very long representations of my part objects, filling the screen with lists of object ID’s and instance variable values. I temporarily simplified the output string to better see what was going on, I put tons of puts (print to console) statements into the test code, and ended up completely baffled. As it rightly should, when you put a Part into a Part, it was there. The array contained the element. Yet the test said it didn’t. That’s when I called the professor again, pointed him to that line in the test, and said something along the lines of “what gives”.
He first frankly admitted that there was a good chance it was a bug in the test. Then he looked at my code and saw at once why the test wasn’t passing. I said I couldn’t see it, but would keep looking. He smiled and said: For an object to be found in an array, what do you have to do? That was all the hint I needed, but bloody hell, I could have hit myself over the head with a blunt instrument for not seeing it myself. Didn’t I know the first thing about object-oriented programming? Searching in a collection is based on equality: You basically say “see if there is anything in there that (in some sense defined in an appropriate method) equals THIS OBJECT”. So unless I told my Part objects how to compare themselves to one another they wouldn’t know when they were equal so they couldn’t ever be found. Sure enough implementing the Combined Comparison Operator (<=>) fixed it.
11 assertions, 5 failures.
I fought for another half hour. One problem was the recursive structure of the Part objects. There were methods for adding Parts as children to an existing Part, and for adding a Part as a parent to another Part. What I had forgotten was that each of these operations, in turn, implied the other. If you add a child Part to a given Part, you also have to set that latter Part as a parent for the child, and vice versa. Implementing that got me rid of a few more errors.
14 assertions, 2 failures.
The last two almost drove me crazy. I quite saw that they were somehow about raising an exception when someone tried to add a Part object as a parent or child to itself. But whichever way I wrote the condition for the exception, it either got never raised, or raised every time, giving me an entirely depressing (at that point) “9 assertions, 9 errors”. After much erratic bumbling, it turned out the only way to get these last two tests to pass was to write the condition based on the object description passed into the constructor as a string.
16 assertions, 0 failures, 0 errors.
One deep, relieved breath. 30 minutes left in the exam.
I spent 15 more minutes fixing no. 2. There, too, I was on the wrong track for a while, thinking I had made an error in the way I delegated calculating the number of non-nil elements in the collection to a helper method, when in fact I had simply neglected to read the assignment carefully: An empty collection should return 0 as average. Not entirely illogical, when you think about it.
And then with 15 minutes left I blundered big time. At this point I should have gone through my entire code, checking for proper encapsulation and such, and adding comments where necessary. Our professor had stressed these points repeatedly in the lecture. Instead, I wasted my time on implementing a fifth, recursive solution for calculating averages, just to show I could do it, demonstrate that I wouldn’t be content with meeting the minimum requirements–and then in the end it didn’t even work! But it should have, and I figured I was so close that I wasn’t able to let it go and do something useful. Besides, the clock on my computer was not just one hour slow, as I had thought, but one hour and five minutes, so when I thought I had ten minutes left, the supervisor announced it were just five, and then it was sort of over anyway.
True to form, the ritual seriousness continued at the end with people walking behind us, peremptorily ordering us to save our work, close the IDE, and shut down the computer, now. The urgency in their voices made it sound like they were reading the checklist for an emergency shutdown in a nuclear power plant.
I left the room after three hours with a feeling of complete exhaustion, shock at how tough the exam had been and how hard to understand the test cases, but above all a sense of having narrowly escaped complete failure and certainly not having lived up to my own–and probably my professor’s and my co-students’–expectations.
My programming partner had set at the workstation next to me, and as always he had not found the exam quite as difficult, had not experienced the same sense of helplessness staring at the test cases, had not that badly run out of time, and above all, had not forgotten to encapsulate and comment. So he is almost certain of getting an A+.
But then again, he can’t be the benchmark even for me, let alone the others. And as far as I can say, the sense of shock and bewilderment was shared by nearly everybody else. The short message chat rooms usually so frequented before and after important events were quiet for hours. Not a single word. Only later in the afternoon did I inquire about the general mood in our small group, and that got them talking, but they were all angry and depressed in some way.
And the result of the exam must be truly abysmal. From the few people I talked with or heard from, my programing partner and myself excepted, not one had managed to write code that passed all the tests, and most had only a very small percentage of those for problem no. 4. At the bottom end, one person in our group had not even run a single test at all–he had spent the entire three hours writing code of which he has no idea whether it works, and it is very likely it won’t.
Four of us ate a hasty lunch, walked around out of doors for an hour to get some oxygene into our exhausted minds, spent an hour quizzing one another with questions for the theory exam on Friday, and then went home. As for myself, I felt almost sick with mental exhaustion for a few hours, and then got somewhat angry at the professor for writing such awfully confusing test cases, and very angry at myself for giving in to pride in the last 15 minutes instead of getting my priorities straight and checking whether I had at least done everything that was actually required from me. I do hope that goof won’t cost me dearly in points, though in fact, if it will, I would have to say it’s justified; I messed up. I messed up, to be sure, above all because it took me so long to pass the tests for no. 4. But even after that I certainly could have made better use of my remaining time. Besides, sparse comments and lousy encapsulation have always been my weak points. I just don’t find it useful to comment on the obvious (this method does just what it’s name says); and to think that whenever I return a reference somebody might invade and destroy my program seems kind of paranoid to me. So that I didn’t do these things well is probably a function of my really not caring about them.
That said, I still feel discouraged, and will feel even more so if I get an average grade. To be sure, it doesn’t have to come to that, because I think most people did poorly in the exam, and the grading scheme will probably allow for that; after all, out of a group of 61, somebody will have to pass with flying colors (since this is not Math), and I think it’s going to be us, in spite of my bungling.
But however this turns out, what I can say is that my eyes have been opened to what I actually let myself in for when I decided to study CS. This is not going to be a cakewalk.