Month: January 2008

So, yesterday I went to Java class again. This time very much curious to see how others handled their homework. No big surprises there: a couple of people got the basics done, most got them horribly wrong with regards to a sane design.

I threw in a couple of weighted opinions about how things should be done, along with some API hints.

Near the end, I asserted that you should be able to make pretty much every local variable except loop counters final and still have the program compile. Even the teacher was stunned. I explained that in the hands of beginners, mutable variables can easily lead to nasty crap like Object temp being assigned to four times in a single method, and good luck trying to figure that one out.

And the teacher said: “we don’t teach real-world programming here. We deal with ideal conditions only.” Fair enough, but we’re not dealing with ideal programmers, we’re dealing with a bunch of wet-behind-the-ears newbies that are actually there to learn real-world Java. Claiming that we deal with ideal conditions only is a cheap cop-out, especially when I wasn’t demanding the students to refactor a 400-line method that uses instance variables for temporary state. I was just pleading that they don’t write the mess to begin with!

I’ve read a lot of postings recently denouncing Java as a teaching language. I tend to agree with that sentiment, but not because I have any particular beef with Java.

I’m currently studying in the Open University. I’m a high school dropout, I learned programming on the job and I’ve long felt that my CS knowledge is rather weak. That’s not to say I’m an especially bad programmer, just that my knowhow is limited mainly to practical, day-to-day business programming. I’m now trying to rectify that.

During these few months I’ve been studying (a few hours every week, an exam here and there) mostly subjects that I’m already intimately familiar with. Basics of programming. Programming in Java. Database basics. I have an upper hand over many other students.

I’ve also noticed that were it not for said upper hand, I’d probably have trouble learning how to program. Not because it’s inherently hard, but because the choice of teaching Java as a first language.

When you’re teaching the basics of programming, what you really should aim for is helping the students build a mental model of how things work. Focus on the what instead of the how. Java comes with a lot of baggage that makes it extremely difficult.

Magic!

One of the first things I noticed people get from the lectures is that programming is really hard. You have to be real smart to know all this stuff. Even though the lecturer always says nobody is too dumb to be a programmer, he nevertheless skips a lot of things as too complex to explain. But we have to keep doing those complex, inexplicable things like wrapping every program in a public class MyProgram { } with a magic public static void main (String args[]) { }. Why is everything public? What does static mean? Or void, for that matter? Where does main come from?

Yes, I know, after years of programming it’s obvious. Java is object-oriented — or should I say, class-oriented — so everything must be wrapped in a class. Main is the entry point method by contract. Static things are specific to a class (whereas non-static things are specific to an instance). Public things are visible outside of your class instance and package. Void means we don’t return any value.

Try explaining that to anyone who isn’t a programmer. Now try doing that in a single lecture, and expect them to not only remember, but understand.

Or you could skip all that, and get everyone used to having a lot of “noise code” they don’t care about. After a full course of that, try to wean them off copy-pasta and explain DRY.

And then you can wonder why the students call every method an accessor. It’s because you’ve overloaded them with a bunch of terminology they don’t understand, and what sticks is what they hear the most. You keep telling them that calling getLength() is calling an accessor, and the example code has a 10:1 ratio of accessors vs. mutators or, you know, plain methods.

Take only what you can carry

How do you focus on the fundamentals of programming when you’re drowning in syntax?

If you can’t build a solid foundation, how can you begin to think you can teach good object-oriented programming? The students don’t understand how inheritance works, let alone what it’s good for.

The best example of getting it very wrong I can think of is one of the students, who in front of the class told everyone that the way he understood inheritance, the point was to gain access to the member variables of the base class, right?

Don’t laugh. Because nobody there did either. I was too stunned to comment at first. Then I thought I’d say it ain’t so because, dear Bob, this might be the one thing some of the students remember from the course. And then I thought, I don’t have the tools to explain this. My peers entirely lack the vocabulary for discussing such matters.

So it would all be better if we only used C#, right?

No, the problem isn’t how Java lacks this feature or that, and obviously the worst possible response would be moving to something that is basically Java vNext. The problem is how Java and its siblings force all of that complexity down your throat at once. It’s not a difficult language if you already grasp the basics –I’m ignoring the bits on purpose that would be considered obscure by a beginning programmer — but how do you expect to teach the basics like that?

finally { }

I’m having a hard time wrapping this up because I feel like I should have an answer. At the very least I should try to sell you my idea of the best teaching language. But I think for now, I’ll settle for trying to explain things to my fellow students as best I can. This spring, we have a programming exercise where we are supposed to independently build a simple Java app. I’m eager to see how that will play out.

I’ve grown so accustomed to Java not having String.format, that when Formatter appeared, I started using that (mercifully only for a few lines of throwaway code) and merrily assumed that it was the best I could do. Of course it felt dumb, and I wrapped it in helper methods that um… do roughly the same thing as String.format.

Onwards with the learning experiences. Next, I’ll try to pin down some thoughs and observations on the dumbing down of comp sci education. (Irony, thy name is Rytmis; I’ve never actually experienced the undumbed-down education, since I only just got started!)

Today was a relatively good day. I’m currently on a Java course at the Open University, and while there’s relatively little new they’re teaching me, it has proven to be a good source of inspiration to learn new things myself. One of those things was how to convert java bytecode to a readable representation, and to an admittedly small extent, read the converted bytecode.

That was a few days ago. The reason I did that was to prove my hunch about how many operations an array size lookup would be (given the array was an instance variable) compared to a static final integer variable — this was a case where the array was initialized to a length specified by said variable. Without actually having factual knowledge, I conjectured that a static final integer could be inlined by the compiler, whereas the array size lookup would be at least two operations. Turns out that I was right on both counts (edit: at least in this instance; I’m not experienced enough to know of any proven reason why optimizing the array size lookup would be impossible). This java code:

That makes it three instructions, not two. For my own benefit (since typing this out will ensure I don’t forget it), here’s a not-quite-accurate explanation of what goes on there:

// push local variable "0" (the "this" pointer) into stack
0: aload_0
// call getfield, which pops (?) "this" off the stack and pushes the field onto the stack
// (the #2; bit is the location of the field, not entirely sure how it should be interpreted
// note to self: find out!)
1: getfield #2; //Field arr:[C
// call arraylength which pops the array off the stack and pushes the length
4: arraylength
// return integer from stack
5: ireturn

Compare and contrast with getFinal which doesn’t do any lookups, just says “push the following byte to the stack as an integer” and then “return integer from stack”.

Now, before anyone accuses me of premature optimization, that’s not what this was about. This was mainly about fact-checking and a desire to understand what goes on underneath. 🙂

Any day I get to prove myself right is a good day. But any day I get to learn something like this and deepen my understanding about a language I use is even better.