Sunday, March 26, 2006

Processing Notes, 26 March 2006

So it's been quite a while since my last post, but with the AAC course focused on projects, I've been giving more tutorials and doing less large teaching.

Today in a tutorial, I stumbled upon another nit-pick with Processing's adaptation of the Java syntax: Processing's designers wisely choose to abandon Java's requirement of “one public class per file,” but the pendulum can swing the other direction. We should not be afraid to make the syntax more restrictive when it helps learning.

An example of this is single statement bodies. Processing should never allow this:


    for (int i=0; ...)
       doSomething(i);


But should enforce:


    for (int i=0; ...) {
        doSomething(i);
    }


Again this is very subtle and almost ridiculous, but details matter when teaching.

Thursday, February 09, 2006

Processing Notes, 8 February 2006

Last night's lecture topic was shape grammars. Since we spent much of the time on background and theory, my Processing reflections are skimpy-er.

Method listing: I tend to find the sophisticated code completion features of environments like Eclipse to be overkill, but one specific tidbit would help novices learning to program with Processing: Method listing, or being able to see a list of all the methods defined on an object. Don't bother with changing what I'm typing — no one ever wants that — but instead follow another common interface metaphor: Select a bit of code, right-click, [Processing parses that tab's AST-and-thinks,] and then show a list of methods in the context menu. Oh and if you don't have a right mouse button, stop drinking the koolaid.

This is important for Java-specific classes, since Sun goes through great effort to bury and obscure the JDK documentation. Kinda like their API... (Thank you javadocs.org.) Coping with inconsistent naming schemes is another good reason (.println() for “print line” but .printMatrix() for “print matrix”). And lastly, method listing would encourage better software design, as the names chosen for methods will be more visible by “trickling up.”

Arrays as primitives: The newer releases of the Sun's JDK reveal one of the early design mistakes in Java, since arrays have become progressively more like proper high-level data types. Processing should embrace this by providing someArray.length() as a pseudo-method on arrays (note the parens), instead of the inconsistent someArray.length. For novices, inconsistency details matter.

Duck typing: Not so much a Processing enhancement, but my crying over another in a long line of student questions about the utter madness of teaching novices un-duck typed languages:

Student: Why do we have to cast what comes out of the vector?
Lecturer: Because Java is a overly typed language.
Student: Huh?
Lecturer: Because it's faster. Or something.
Student: But don't we usually ignore performance problems while learning to program...?
Lecturer: /cries

On on that cheery note, that's it for this week.

Friday, February 03, 2006

Teaching Interfaces

A recent comment on Toxi's blog asked about techniques for teaching novice programmers about interfaces, in the context of the Processing development environment. My approach starts by taking a step back from Java's OO biases, and asking about interfaces in general. Contrary to Sun's marketing, interfaces are not best understood as a gentler version of C++'s multiple inheritance. Instead they are a language construct for explicitly representing an object's Contract. A class implementing an interface is guaranteed to provide "at least" a certain sort of behavior, by which we mean "methods."

Considered as a syntax for specifying class contracts, we've found a decent metaphor for teaching: It is quite natural for students to understand the necessities of Contract, and even to understand interfaces as a restriction on "freedom." An object is free to behave in any way it likes, as long as it does at least X, Y, and Z... Three behaviors the rest of the world is expecting of the object.

Please forgive my blurring of "class" and "object" above. This reveals another of my software writing biases, this time for prototype-based languages. Here even my cherished Ruby falls short. Prototype-based languages make no distinction between "classes" and "instances." Everything is just an "object." Create a new object by cloning a already-existing one, and then customize its behavior by dynamically adding methods and data. It is the context of how an object is used that determines its "abstract-ness." If one only ever clones an object but doesn't use it, that object is effectively an abstract class.

While prototype-based design can be quite a leap for OO programmers accustomed to the C++/Java way of doing things, it is actually quite easy to teach novices. Since prototype objects are closer simulacra for physical objects, we needn't use such stretched teaching metaphors. No more "classes are blueprints," and "instances are houses."

Imagine being able to shrug off awkward explanations of both the static keyword and the new operator, without any significant loss in elegance or expressiveness. I would love to see Processing do prototype-based OOP.

Thursday, February 02, 2006

Processing Notes, 1 February 2006

Last night's lecture on genetic algorithms:

Be wary of method argument names: When writing code for students, try not to give method arguments the same names as the outer scoped variables. This is difficult to explain but easy to demonstrate:


void func(int width, int height) {
    // do something with width and height
}
// later
int boxw = getBoxWidth();
int HEIGHT = getAnotherHeight();
func(boxw, HEIGHT);


is more instructive than:


void func(int width, int height) {
    // do something with width and height
}
// later
int width = getBoxWidth();
int height = getAnotherHeight();
func(width, height);


Again this may seem overly subtle, but the former style gives a visual cue to groking variable scopes.

Function side-effects: Methods that return values should have few — ideally zero — side effects. Novice programmers are comfortable with the "formula" metaphor from high school algebra, but side effects will tempt this metaphor to bite back.

And now two more features for Processing to help in teaching programming to designers and architects:

Comparable and casting: High level array sorting and inserts are provided by the Java Comparable interface. Since Java is overly typed, implementing this interface almost always requires casting. Object casting is an absolutely brutal concept to teach. Instead Processing should provide a method in all classes called "toNumber()" which converts an instance into a numeric representation. All classes should by default implement Comparable, and should by default implement "compareTo()" as:


int compareTo(Object o) {
    ProcessingObject processingObject = (ProcessingObject) o; // cry...
    if (toNumber() < processingObject.toNumber()) {
        return -1;
    }
    else if (toNumber() > processingObject.toNumber()) {
        return +1;
    }
    else {
        return 0;
    }
}


Programmers could just override "toNumber()" in their subclasses, and then "Arrays.sort()" would work magically. Sorting by a numeric representation of an instance is by far the most prevalent.

Random array elements: Selecting a random element from an array or Collection is a common idiom, but also a obscure, bug-ridden one. Implementing it requires students to understand zero-based array indexing (as opposed to natural one-based), float to int conversion for the index and pseudo-random numbers. Processing should implement an additional "faux-method" on arrays like "array.randomElement()" that does:

return ar[(int) (random() * ar.length)];

Until next week.

Wednesday, February 01, 2006

Response to Tom

Thanks for pointing me at the auto-format. Any way I can blame this one on my students?

Your point about () for no-arg methods is sorta beside the... point. The real source of the problem is ambiguity that "obj.gizmo" could ever be a reference to a member variable. Processing should have (force?) implicit accessors ala' Ruby.

Processing does a bunch of little things to deemphasize stack traces: truncated traces, line numbers are mangled, no reference to tabs, no browsing based on the stack trace, etc. I say "deemphasize" instead of "buggy" because stack traces are such a fundamental part of debugging that I can't imagine these problems getting through — unless they're almost intentional?

I'm not going to submit Processing bugs to Bugzilla because I wouldn't do myself justice, and it would be flamebait: "1.) Replace Java with Ruby, 2.) Replace all custom GUI widgets with standard Win32 / Aqua / Qt toolkit components, 3.) Emulate all OpenGL functionality in P3D, 4.) Implement a comprehensive unit test suite so there are no steps backward on new releases," etc.

Processing is explicitly designed for doing computer graphics. Doing computer graphics in a development environment higher level than C/C++ over OpenGL or DirectX will compromise your performance. Thus if you program in Processing you already accept a compromise of weaker performance for higher level language constructs. So a Processing developer should have access to constructs like arbitrary-precision, ubiquitous floats.

Teaching architects and designers ubiquitous, arbitrary-precision floats is easy. It's the principle of least surprise; it's what people expect.

Maybe instead of your Processing sketch skeleton macro, just start with each of those functions as a tab in every project?

Positions and vectors are probably the same class (hierarchy). "...modeling a velocity vector and a spatial position with the same underlying data structure." It needs to be drilled because most students balked at a general Point class.

Scope and heaps are hard to teach. Their faces always glaze over when I talk about visibility and local-clobbering-global. Must more about this.

Processing Notes, 25 January 2006

I am a lecturer on an MSc course at the Bartlett in UCL, and one of my friends Tom suggested I keep a log of particular difficulties in teaching architects and designers to program via the Processing platform. Thus disclaimed are my digressions from rare postings on chefery, politics and Potter.

Divuldging my side of the fence: I feel Procesing is a deeply flawed albeit contagious and buzzy platform for teaching programming. My criticisms are plenty but now public — because "in the trenches" teacher and student would benefit from these gripes being addressed. It behooves the whole community if nascent programmers come away from their terms spent in Processing with academe nostalgia, not flight. Their appraisals at future design and architecture gigs will make or break Processing, either promoting or dashing its current momentum.

And so, my notes from last week's lecture on boids:

Algol to C to Java to Processing: Matching curly braces — or begin/end blocks — is a necessary evil in this lineage of programming languages. Processing helps by highlighting a matching brace while hovering, but this is of limited use to students who are learning by cut 'n paste. A more helpful feature would be an "auto format" option to indent and align a tab of Processing code, especially after said code has been mangled by many-a CTRL-V. Check, thanks Tom.

No argument methods and functions: Other 4GL languages skip the irritating verbosity of parentheses when passing no arguments, so why shouldn't Processing? Think "obj.meth;" instead of "obj.meth();". Like many of my criticisms, this may seem pedantic nit-picking of the Java legacy. However these sort of redundant redundancies just devastate novices.

Stack traces: Processing should move my cursor to the correct tab and line of a particular stack trace. There seems to be a deemphasis in Processing on making stack traces visible, but they are actually a very natural and linear way to review a program's logic in hindsight. At the bare minimum, Processing's stack traces should at least list line numbers and tabs.

float vs. int: Now we come to probably the most consistently baffling and frustrating (to both teacher and student) aspect of learning to program with Processing. The distinction between floating point numbers and integers, and the accompanying nasty casting, is fundamentally non-intuitive. This is the 21st century; memory, disk and CPU are cheap. Have the stones to make everything arbitrary-precisioned floating point numbers. All literals and all numeric variables are this "super float," and let the interpreter or compiler worry about the optimizations of when-and-where a value can be coerced for faster integer math. From the learning programmer's perspective, it is almost maddening that "1.0/99 != 1/99". And in light of Processing's already compromised performance, please ignore anyone saying "but it'll be slow."

Not criticisms of Processing specifically, but general practices to remember when teaching designers and architects to program:

Top down: Professional developers grow accustomed to a progressive focus on the minutiae of a problem, while gluing these pieces together "later." Long experience in writing software, or a background in mathematics, facilitates this minutiae-driven programming process. Though you may know this bit of code will be needed eventually, it is more conducive to teaching good programming style — or to teaching programming at all — to work from the top down.

Even if it does not resemble your actual programming practice, live lecture or lab demonstrations of coding should invert the minutiae thinking: Code and discuss the most general logic of the program first, and fill in the blanks later. One of my first programming teachers taught programming in this style, and while demanding of the lecturer, it is deeply instructive to code the skeleton first.

Vector vs. points data representation: While we're used to modeling a velocity vector and a spatial position with the same underlying data structure, this is a significant leap for students getting used to 3D programming. This is true even for those designers and architects comfortable with a CAD package. Drill this "not distinction."

Heap data is sorta global: Yet another murky legacy of Algol-ish, side-effect-ridden languages is the confusing heap; that an object instantiated in a small method, but referenced via a stack variable that is eventually returned, is visible to the caller — another conceptual leap for novice programmers. A visual diagram of a simplified heap can help. A purely functional language for learning would help even more...

While these feature requests are certainly not on the grand scale of software methodology practics, these sorts of "little things" are what enable frequent and vicious refactoring, a vital practice in good top-down object oriented (OO) development.

Tuesday, November 22, 2005

Peeled, Seeded and Diced Tomato [food]

Like shallots and alcoholism, most real chefs are into “tomato concasse.”

Boil some water, and prepare a bowl of ice water. Lightly cut an X across the bottom of your tomatoes. From the top of your tomatoes, remove the core by cutting a scoop. Drop the tomatoes into the boiling water. Remove them when the peel starts to shrivel. Immediately toss the tomatoes into your ice water. (This stops us from actually cooking the tomoatoes.) Pull away the peel in the water. Cut the tomoatoes into length-wise wedges. By holding one point of the wedge against your cutting board and cutting away from you, discard (eat) the bitter and seed-y innards. Dice what's left: Cut them into quarter-inch strips, then into quarter-inch cubes.

Use this tomato concasse to garnish everything savoury, especially pasta and crispy (fried) meats. Most tomoatoes now-a-days taste of nothing, since they've been bred to be tough for shipping but weak in the mouth. If you're loaded, so-called hierlooms are an incredible decadence.

Monday, November 21, 2005

Goblet

An excessive aura of pop culture skepticism is required for membersihp in the club, but there's always been a blurred line between skepticism and utter fascination. (“Eighties. Living in the eighties.”) Reading one of J.K. Rowling's best selling screenplays is a negotiation on this line. I read her as the films are released, so I can play that mental game of wondering how someone with mad budget chooses to visualize a hippogrif on screen. She suffers from the usual Tokien-esque shortcomings, but doesn't benefit from his insulation of genre definition.

1. Everyone evil is ugly, and usually wants to pretty.
2. Anti-heroes are glorious in being selfish, by getting what they want but not necessarily winning.
3. Class struggle is delineated by birth only.

This sort of uber-Western prattle is not something I'd choose to indoctrinate in my hypothetical child. However my friend's mother – a big shot children's librarian on the Island – insists that Rowling is fighting the good fight in bringing kids back to reading. I would love to see non-anecdotal evidence that the kids of Potter fandom read much outside the series, since I suspect a fiesty cult of personality is at work. (How many Scientologists read proper psychology, for perspective?)

I would much rather children of the short attention span generation (bollocks) spend a few hours watching quirky, surreal (drug-addled), clever children's films like Labyrinth and Lilo & Stitch. Then again, the Potter series isn't written for children. Right?

Sunday, November 20, 2005

Internet as Agreement

The longer we maintain against regulating the Internet, the longer there is legal ambiguity about the most appropriate linguistic metaphor for the Internet (pipes vs. space), the more people wil remain accustomed to the Internet as a natural resource. That it is a natural resource, an agreement is an affirming nuance.

The more people think of the Internet as a natural resource, the more resistance there will be to regulation, to moving things away from the edges. In an inverse corollary of government reticence to allow any given cash flow to dry up — Illinois' toll roads were supposed to be abandoned back in the 1970-80's — people used to getting something for free will expect that price in perpetuity. Maybe we don't need to win, but just stall 'em.