UML sucks

16 May

Everything said here.

I’ll just add that pictorial representation of code is fundamentally flawed because it inevitably means drawing a bunch of boxes and connective lines all over the place. Just as there’s no one true way to distribute your functions and classes in text, there is no true optimum 2D layout for boxes representing functions and classes. No algorithm does this layout well enough to not need human reworking. Every good diagram of any complexity you’ve ever seen, whether of code or of a subway system, has been heavily hand-massaged if not entirely hand-generated. Even if you had a decent algorithm for layout, the layout it computes might change radically each time you add a box or connection, which would be disorienting in the same way as if someone were to rearrange your workspace behind your back. A big part of what it means to be comfortable with a codebase is knowing where most things are. How familiar can you ever be if the codebase gets constantly scrambled? The only solution is to have the coder position all the boxes and draw the connections manually, but this will just mean that systems will get uglier and uglier as they grow and that refactoring the layout will grow more and more painful.

Text to some degree has these problems too, for you have to decide which file to put a function or class in, and you must then decide how to order the functions and classes of each file. But in text, you aren’t burdened with the stylistic choice of how to draw connections: everything has a proper name, and you make connections by using the proper name, end of story. Making connections pictorially is only simple if you stick to straight lines, which typically makes the diagram much harder to read than were the connections cleverly grouped and routed along the cardinal directions. Text code with many connections is complicated but readable; diagrammed code with many connections is complicated but totally unreadable. The whole point of diagramming code is to visualize connections, to see the shape of a design, but past a rather low level of complexity, the visualization is too much to mentally process.

In sum, stick to code for code. Use diagrams only for broad communication, and use them only when they are understood to be lies.

Intuition: I do not think this word means what you think it means.

26 Apr

Jeff Raskin on “intuitive interfaces”.

c.f. Hume, David.

I lick your cake! I lick it up!

17 Apr

Little things add up

8 Apr

A discussion of various little things about Python 3.0 that make it easier to learn than Python 2.x.

Subtlety hinders grokability

17 Mar

Here’s some nice paragraphs recycled from an old crappy post no longer worth reading.

In C, the conceptual and syntactical distinction between definitions and declarations is blurred. This is a prime example of a misguided attempt at conceptual unity in design.

I think what goes on in designers’ heads is that they spend their time juggling many parts around, mentally banging the parts together to see which fit with which and which overlay the others, and then occasionally, in moments of revelation, the designer sees how parts they were thinking of as separate can be neatly overlayed, interlocked, or even dissolved into one, greatly simplifying the design. A small minority of the time, these revelatory moments really pan out just like they seem they will in that initial flash of recognition. However, most of these moments come to nothing when it later turns out that, upon further reflection, the idea doesn’t really make sense or fit consistently with the rest of the design. Other times, refactoring the rest of the design to fit the revelatory idea actually makes the whole more complicated. Other times, the idea can be accommodated just fine, but the gain is just an illusion: the designer, unhappy with some trade off, finds a solution that seems to dissolve that trade off, but euphoria blinds the designer to some side-effect introduced by his solution; on any other day, this new problem would displease the designer just as much as the problem he’s just solved, but he just isn’t thinking about it at the moment—maybe he’ll notice in a week or two.

I believe the misguided attempts at conceptual unity in C that displease me so are actually partly examples of success: after all, the conceptual unities of C ‘work’ in the sense that (obviously) they comprise a real working language and the sense that the conceptual unities do in fact reduce the syntax (e.g. pointer and array declaration syntax mirrors the syntax for dereferencing and array indexing). Still, these design choices also exhibit the designer euphoria blindness I described: aspects of the design have been simplified, but only by incurring disregarded costs elsewhere. In this case, the costs are to language transparency: these supposed conceptual unities in C are difficult to convey to outsiders because they really only make sense to people who already understand them. Having read many accounts of the C language, I’ve come to the conclusion that many of the traditional stories and vocabulary which C programmers use to talk about the language to each other simply fail to account for what is really going on in the language. Really, this is an unfortunate fact of any area of expertise: the experts are already cognizant of what’s really going on, so it’s fine for communication amongst themselves if their explanations and vocabulary abridge or misrepresent to untrained ears what they’re actually saying, but these inaccurate utterances are profound barriers to the uninitiated.

No, Mr. Perl, I expect you to die

28 Feb

Steve Yegge on Perl

UPDATE: Oops, apparently it’s from 2004. Still good, though.

Hello world!

25 Feb

Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!

if !johnny.canRead() then…

4 Feb

The state of educational programming languages.

Ideally, a proper programming education would start with a thorough discussion of how data is represented as bits, followed by a brief tour of encryption, compression, information theory, data structures, search/sort algorithms, and machine architecture. Unfortunately, students are just too impatient to start their education properly, having approached the topic of computing with the desire to get their computers to do something, preferably something neat, preferably something now. This is where educational languages should come in: students should be able to learn a simplified language in a week or two of lessons with no prerequisite material, thereby satisfying their curiosity of what programming is at least like. Learning a quick-and-painless language should make students more receptive to covering some of the theoretical basis of computing while also preparing students for learning their first ‘real’ language, whether it be C, Java, Python, Scheme, Javascript, Ruby, Haskell, whatever.

In the before time…

Today’s learners of programming typically start out with Javascript, PHP, Python, Ruby, Java, C, C++, or C#. Things used to be different. For much of the 80′s and 90′s, newbies to programming were directed to languages typically thought of as learner’s languages, such as BASIC and Pascal, though these languages weren’t necessarily designed explicitly for education. Why did languages like these fall out of favor as educational tools? Most likely for the same reason they fell out of general use: they simply got old and out of date. Practicing programmers begin to look upon superseded languages like they do old code—as distracting, bothersome clutter. In turn, the neophytes take their cues from practicing programmers and insist they be taught a “real” language, and in the end, it’s just very hard for a language to gain and maintain wide adoption as an educational tool when no one wants to do any real programming in it.

While some may mourn BASIC and Pascal, I think people’s estimation of these languages is blinded by nostalgia. Pascal, in particular, overstayed its welcome in the classroom. By the mid 90′s, you might as well have taught C in place of Pascal, for C had sufficiently matured that it was essentially Pascal with pointers, different syntax, and no silly distinction between “procedures” and functions. Moreover, by 2000, the only* easily available implementation of Pascal for students to run on their own computers was (and is) Free Pascal, which actually supports a much changed dialect of Pascal, the result of cross-pollination with Delphi. The added complexity was bad enough, but then the Pascal text books simply didn’t keep up, thereby compounding Pascal’s fate: if new programmers don’t learn the Pascal in actual use, they won’t continue to use Pascal once they’ve learned it, leaving the language stuck in a death spiral.

(*There are actually Pascal implementations other than Free Pascal still available, but they too all significantly diverge from the classic Pascal of classrooms.)

BASIC suffered from an even worse fracturing problem and was eventually wholly overtaken by Visual Basic, which came to be seen as the modern BASIC even though it bore only superficial resemblance to the BASIC of 1980′s nostalgia. Visual Basic saw decent up take in the classroom, but as Microsoft took VB from 3.0 to 6.0, the language got more and more complex until, finally, today’s VB.NET is an almost entirely pointless syntactical variant of C#, a language just as complex as Java and C++.

What now?

Among the languages in use today, the best candidates for starter languages are the dynamic languages: Javascript, PHP, Ruby, and Python. Javascript and PHP, however, can be quickly discounted:

  1. Both Javascript and PHP lack a real read-eval-print interactive prompt.
  2. Non-programmers are most familiar with programs as things which they install and run on their machine, and so they’re going to feel something is missing if they can’t see how the language you’re teaching them is used to write such programs. Unfortunately, Javascript is stuck in the browser. Even if you teach Rhino, you’ll still have to tell neophytes a very strange story they likely won’t understand about how their Javascript program is executed and how this qualifies as general-purpose programming. Similarly, PHP is so heavily skewed towards its niche of server programming, it’s basically useless for client-side programming. So, with either Javascript or PHP, the instructor must make a Solomonic decision between leaving students in the dark about how their programs run or burdening and distracting students with a confusing back story.

So it comes down to Ruby and Python. Many will say the choice between the two is just a matter of taste, but I feel Ruby’s latent Perl-isms makes Python obviously better suited for neophytes. However, despite Python’s exemplary cleanliness, it’s still a quite complicated thing from the neophyte’s perspective. There’s a reason O’Reilly’s Learning Python is 746 pages long, and I just don’t think learners should be confronted in any way with subject matter like:

  • multiple inheritance
  • ‘bound’ vs. ‘unbound’ methods
  • old vs. “new” classes
  • functions within functions
  • list comprehensions
  • generators
  • packages
  • operator overloading
  • exception handling
  • creating custom iterators
  • internal dictionaries
  • a complicated hierarchy of scope with (limited) closure

Of course any sensible introductory Python course will hold off on these topics or avoid them altogether, but simply trying to ignore features of a language has costs, as the complexities and corner cases of a system have a way of intruding into the more pristine areas. For one thing, a student might accidentally write syntax which the compiler interprets as a (successful or unsuccessful) attempt to use a feature the student isn’t even aware exists; the result is mysteriously misbehaving code or a mysterious error message from the compiler. Perhaps worse, learners of a language will not be shielded from features they don’t understand when using their most important learning resource, the internet. Lastly, while Python is certainly a one-way-to-do-it language in comparison to Perl, it still offers conveniences for expert users, conveniences that will only paralyze learners with distracting stylistic decisions.

So perhaps we’d do better starting learners with a language explicitly designed for education. Yes, I did start by saying that the now-dead learner’s languages died because no one wanted to do any actual programming in them, but the main problem there was that Pascal and BASIC grew into complicated languages: they didn’t start life as explicitly learners-only languages and so ended up stuck in a no-man’s land between ‘two-week intro to programming’ and ‘full application-programming tool’. However, there still remains the problem of learners wanting to bypass learning a tool they’re going to immediately drop, so an educational language has a tricky balancing act to perform: the language should be simple enough to be fully learned in one or two lessons so that students don’t complain about learning “all this stuff” they aren’t going to use…but not so simple that the language isn’t enough like a real language to help students understand their first real language…but not too much like a real language that anyone would want to actually use the thing for real work.

Dark horses

Outside the mainstream, we have more educational language options. The most notable among them are:

  • Squeak (Smalltalk)
  • Scheme
  • Haskell
  • Alice
  • Scratch
  • Logo
  • Phogrom

And here’s what’s wrong with these languages:

  • Squeak, Scheme, and Haskell are real languages used by real programmers for real work. This is bad. Real means complex. Annoyingly complex in annoying ways. No matter how elegant in conception these languages may be at their core, their corners lurk with ugly realities, and you can’t assume that learners can’t see the corners or can just ignore them. For the learner, more corner cases means more possibilities to consider, more mental dead ends, more detritus to sift through to establish a clear picture. Sure, you could teach a relatively clean subset of Java, but the subset you teach will be scattered here and there in the 1200-page Java book your student picks up. Sure, you could teach Haskell while ignoring its convoluted syntactical conveniences, but the compiler’s warning messages won’t be so friendly to your student. Sure, you could stick to just one dialect of Scheme, but Dr. Scheme will confuse your student with a list of umpteen different dialects from which to choose. For learners, these 1200-page books, cryptic error messages, and fractured sets of dialects are frightening and discouraging.
  • Squeak has a problematic relation with the operating system: Smalltalk has never reconciled itself to the OS, stubbornly refusing to let the programmer create programs that take advantage of the OS’s already existing mechanisms for interfacing with users: the filesystem, the console, and (proper) windowed applications. Whatever the merits of this kind of programming, like with Javascript, Smalltalk presents a very confusing situation to learners, most of whom are hoping one day to write Doom 8; Doom 8 is not going to be written in Smalltalk, and even the greenest newbie programmer will be able to smell that about Smalltalk. Furthermore, I believe that a learner’s language should partly disregard files and entirely disregard consoles and GUI’s; Smalltalk does that, but it does so by replacing those things with its own complications, complications which end up as just more stuff to sift through in the documentation (see above).
  • Alice and Scratch attempt to sidestep the syntax issue in a novel manner: rather than using text for code, the Alice and Scratch editors have users drag code fragments and fit them together like puzzle pieces: the pieces only fit together in syntactically proper ways, so syntax errors aren’t possible. I actually think this might be a great idea for training students in the syntax and semantics of real languages, such as Java. However, this does mean that the Alice and Scratch dev environments feature a lot more buttons than they otherwise would. More importantly, if these languages’ syntaxes were simple enough in the first place, the benefit of drag-and-drop editing would be negligible.
  • Alice, Scratch, and Phogrom all suffer to one degree or another from the “naturalistic language fallacy“: by attempting to have their code read like English, they end up greatly complicating their languages and obscuring the underlying formality, thereby failing in an important regard to prep students for real languages. There’s a reason most English-speakers struggle to learn English grammar: it’s an awkward attempt to fit formal rules on a complex, organic system. Doing the opposite—massaging a formal system into English—doesn’t clarify anything, either. (The biggest offender in terms of naturalism is actually AppleScript, a language some misguidedly hold up as appropriate for learners. Like Dylan, AppleScript, is an example of Apple favoring apparent simplicity over actual simplicity; such bargains are sometimes worth it, and more often than not Apple finds the right balance, but the result with AppleScript is disastrous.)
  • Explicitly educational languages present themselves as intertwined to a particular API: Logo is the language in which you do turtle graphics; Alice, Scratch, and Phogrom are languages in which you do simple 3D- or sprite-based graphics and sound. Simple graphics-oriented API’s are a great idea, especially for teaching programming to younger students, yet there’s something wrong when the API is presented as indistinct from the language proper. In real languages, everything useful aside from basic arithmetic and logic is punted into libraries, and this is how it should be. First, multi-module programming brings with it the essential concept of namespaces. Second, without the barrier between core and domain-specific functionality, the distinction gets blurred in students’ minds.

Here there be dragons

Some topics should simply be avoided in a learner’s first exposure to programming, whatever the language. These topics include:

1) Inheritance and other static-y object-oriented features

Java and C++ support OOP the way they do for the sake of compile-time checks and efficiency (relative to languages with dynamic object systems, at least). These features introduce a plethora of rules in those languages, the sum complexity of which distract from the essential ideas in OOP: encapsulation, polymorphism, and inheritance. In a dynamic language, these ideas can be conveyed by convention using regular functions and dictionaries: plain functions are used as constructors and methods; dictionaries are used as the objects; methods take the object as their first parameter; and constructors return a dictionary with the right instance and method members. For example, a method call ends up looking like:

obj.foo(obj, 3)  // call the foo method of obj with an argument 3

This may be more verbose, but it’s explicitly constructed out of already existing mechanisms. Inheritance relationships would be ‘faked’ by simply giving one type all the same methods as another, e.g. A is a subtype of B because it has all the right fields and methods. Duck typing, essentially. A student introduced to OOP as a set of conventions rather than new language mechanisms has a better chance of seeing the point of the whole thing and so is less likely to fall into common newbie traps, such as using inheritance for the sake of using inheritance.

2) Shells

Shells seem to be problematic in programming education. For one thing, every shell tutorial I’ve ever seen outright fails to make clear the distinction between shell code and program invocations in the code. For example:

ls -a > foo

While “> foo” is part of Bash syntax, Bash doesn’t see “ls -a” as anything but a command it doesn’t recognize, so it looks for a program named “ls” in its search path, and it loads and executes ls, passing the string “-a” as the argument fed to the char* args parameter of main() of the ls process.

Got that? Well, if you don’t understand this, you don’t understand the first thing about shells. But it’s REALLY FREAKING HARD to start learners off by explaining all this. So we don’t explain it. Rather than really teaching Bash or other shells, we just give students a few example shell commands, wave our hands, and trust that students will eventually figure out what’s really going on. Few students catch on quickly, and many never do, including some that go on to program professionally.

The solution to this situation is to formally cover shell languages as topics in their own right rather than as incidental to instructing students in how to use a compiler. At the very least, then, shells should not be introduced at all until it’s time to give them proper treatment.

(Not only are shells conceptually tricky to explain, the complexity of Bash syntax distracts learners from the essential concepts. The long term solution is to replace Bash as the default shell with something with a proper expression-based syntax—something like Python or Ruby, perhaps—rather than a command-based syntax, even if it means some common tasks would be a bit more verbose to type. Bash is a horribly twisted pile of historical happenstance that is just no longer worth its few minor typing-efficiency advantages.)

3) OS concepts

Key pieces of every language’s standard library deal with operating system matters like files, processes, and threads. Like with shells, these are complicated subjects in their own right: by introducing these OS concepts intertwined with a language, you’re muddling the clear presentation of both.

a = new Hope()

Enough about how to do programming education wrong. What about getting it right? Well, I have a lot of opinions on that front too. So many, in fact, I created my own language, Pigeon. The design philosophy behind Pigeon can be summed up by a few slogans:

  • Get in, get out. Pigeon is designed to be fully learnable in 3-4 hours. Once the student fully understands every rule of Pigeon, they should write trivial programs in it for maybe 4-8 days, and then they should move on to learning a real language (especially Python). Pigeon is simple enough that it would be ridiculous to offer a full term course devoted to it, even at a high school or middle school. (At the very least, you should be embarrassed to attend an institution that offers a programming course with Pigeon in the title.)
  • The explanation is the design. No other consideration is as important as bare simplicity—both syntactical and semantic—and simplicity is best measured by asking the question, ‘How must this be explained?’ The shorter and clearer the explanation, the simpler the language*. Currently, the Pigeon tutorial is just over 20 pages; I don’t foresee it ever growing past 30.

(*Of course, the simplest possible language would be a minimal notation for a Turing machine, e.g. Brainfuck. While that might actually have educational value, the goal here is to set learners on the path to learning real-world languages.)

Pigeon sticks to the features common to almost all modern languages:

  • expressions
  • functions
  • local and global variables
  • branching and looping
  • recursion
  • arrays and associative arrays
  • modularization across files

(Global variables and recursion are not themselves essential at this point in the learner’s education, but they help establish the concept of local scope.)

The Pigeon program is a bare-bones text-editor window with a sub-window for printing standard output. Clicking ‘Run’ translates the code currently in the text-editor window into a Python module and then executes it. This is all done in about 1,000 SLOC using Python 2.5 with wxWidgets.

Currently, the only output accessible in Pigeon is the standard output window, and the only input is a bare bones pop-up dialog. As explained above, the decision to omit file handling is deliberate. However, one thing I would like to add is a simple interface to wxWidgets’s canvas to allow learners to play with simple 2D drawing. If you’re interested in contributing code to the project, that—or some other kind of simplified input/output mechanism—would be a good place to start.

Another big way to help the project is to concoct simple programming exercises, as I’ve neglected this important area.

If you’d like to contribute, ask for project member status in the comments here so you can edit the wiki. (You must have a gmail account for this.

Learn more about Pigeon:

The current Pigeon download is not usable, so don’t bother with it yet. Something apparently got buggered when I packaged the zip together (hey, it worked on my machine!). I’m putting off a fix until I get the time to add cross-platform filepath support (I developed on Windows without bothering about Unix) and also the time to update the language to match the documentation (I’ve neglected the code since I posted 0.1 in October, for I’ve been focusing on writing docs instead, over which time I changed my mind about a few things). Aside from those few things, I’m sure some things in the code will look hideous from the perspective of a three month hiatus and will demand refactoring. I also haven’t gotten around to putting my svn repository on Google Code, so that will be the first thing I do when I tie up these loose ends sometime this February.

Gutsy Gibbon: the first real desktop Linux

15 Nov

Ubuntu 7.10 (codename “Gutsy Gibbon”), released last month, is for me the first really usable Linux, which is saying a lot considering I’ve made a serious attempt to switch to Linux about once a year for the last six years. The last 3 of those attempts have been with Ubuntu, and while I could always get my system dual-booting into Ubuntu, there was always some essential functionality I couldn’t get working such that, when the GRUB menu came up, I would always choose to boot into Windows. With Gutsy, I can finally say that the only compelling reason I have for booting into Windows is to play games.

What follows is a rundown of various issues hindering Linux desktop adoption, most of which I can happily report are solved–or on their way to being solved–in Ubuntu.

For reference, my desktop specs are:

  • MB: Asus P5NSLI (nvidia nforce Intel Sli)
  • CPU: Core 2 E6400 (LGA775)
  • RAM: 2 gigs
  • HD: Western Digital 7200 rpm 250gb SATA
  • Sound: Creative Labs X-Fi Gamer and ADI AD1986A onboard audio
  • Video: geforce 8800 GTX 768mb
  • Monitors: Gateway FPD2485W (24″ 1920×1200) and Samsung 215TW (22″ 1680×1050)

My laptop is a Gateway M-6816, which has Intel PRO/Wireless 3945 and Intel Graphics Media Accelerator X3100 (up to 384MB shared).

Installation media

I start with the issue of installation disc integrity because, in my experience, it is not a rare problem. My first torrent of the Gutsy amd64 DVD was faulty, apparently, and this caused the live CD boot to hang early in its process. I’ve experienced similar problems with previous releases. I suggest always running the media check (an option in the boot CD splash menu) before installation.

386 vs amd64

The 386 DVD version installed without a hitch, but sadly, I’ve yet to get the amd64 version to work. The trouble seems to be graphics related, as the boot CD stops before it gets to the graphical login screen. I successfully installed in text mode, but booting from that install exhibits the same problem.

Partitioner

A non-destructive partitioner is essential for Linux’s success on the desktop because most users coming from Windows wish to dual-boot and don’t want to reinstall Windows or lose any Windows partitions. Also really important is a smart installer that helps users pick the right set of partitions to create for Linux. With previous releases, I’ve had to turn to external solutions, like GParted and the Ultimate Boot CD, to mixed results. With Feisty, Ubuntu started to integrate GParted into the install process, but the result was still sketchy. When installing Gutsy, I already had free space on hand for a new primary partition and so basically by-passed the issue, but I’d be very interested to hear how others fared with setting up partitions for Gutsy where they had to resize NTFS. One thing I’d like is a manual/auto mode so I can have the installer recommend a partition layout but still see what exactly it’s doing and modify its plan.

Reading and writing NTFS

Just as important as easy non-destructive partitioning, users coming from Windows want to read and write their NTFS partitions. (Reading and writing Linux partitions from Windows is less pressing, but can be done with explore2fs.) With Feisty, users had to know they needed to install a package to get NTFS support, and I myself couldn’t get writing to NTFS to work, only reading. With Gutsy, my 3 NTFS partitions are readable and writable out of the box in Nautilus just by double clicking them and entering my password (this just mounts the partition: you must click again to view the root of the partition, a behavior which should be changed or made clearer with user feedback).

Boot loader

On the laptop I bought a few months ago, the first thing I did was make room for Linux by clean re-installing Vista from the included install disc into a smaller partition. Gutsy installed with no hassle, and GRUB allowed me to boot into Vista. On my desktop with XP and Vista already installed, installing Gutsy replaced the XP loader with GRUB, but strangely this left XP bootable from GRUB but not Vista. My guess is that GRUB tried starting Vista as if it were XP because that’s how it listed the partition in the menu; this may have arose from the unusual case of a Vista partition existing on a drive with the XP loader installed (it got that way because I installed XP after Vista). Only after reinstalling Vista and then a second install of Gutsy (amd64) could I boot into any OS from GRUB (even though, as mentioned, Gutsy amd64 won’t boot). Hopefully my unusual case will be accounted for in future releases.

GRUB could stand a few basic improvements. First, the default names given to the Ubuntu boot options should be simplified, as they are currently quite scary. Second, there should be an obvious GUI way to edit the boot menu, especially for changing the default partition.

Boot time

From hitting the power button, it takes Windows XP 60 seconds before the desktop appears. From that point, it takes another 90 seconds before Firefox will open and I can interact with it.

On the same machine, booting Gutsy cold also takes 60 second before I see the desktop. However, at that point, it only takes 5-7 seconds to fully load Firefox.

(I’m sure a few programs I have installed on XP hinder it compared to a clean XP install’s baseline performance, but I don’t have anything that major loading with XP; the only significant startup daemons I have are nvidia’s ntune panel, dtools daemon, and Valve’s Steam.)

Ethernet and Internet connectivity

In previous Ubuntu’s, I had issues getting wired and wireless internet connectivity, and I don’t think I have to tell you how useless a system without an internet connection is. Thankfully with Gutsy, I haven’t had one problem whether wired or wireless. I’ve yet to try networking to other Ubuntu installs or to Windows, so I can’t speak to those issues.

Pointer feel

If your mouse doesn’t feel right, your whole user experience is severely degraded. For instance, I probably wouldn’t dislike Macs so much if it weren’t for the fact that every time I’ve ever used one, the mouse motion was way off (and lets not even mention Apple’s “innovations” in mouse body shape and clicking mechanisms). Even when configuring my MacMini (the first and last Mac I’ll ever own) with mice of my own choosing, I’ve never gotten close at all to the quick, accurate control I’m used to in Windows, where I have a high DPI mouse (the Logitech G3) set to high sensitivity and low acceleration with “enhanced mouse precision” enabled. (Jeff Atwood ellaborates on mouse acceleration in Windows vs. Mac.)

The mousing in previous Ubuntu releases was similarly unsatisfying (though Kubuntu was considerably better). Compounding the problem in Ubuntu, the sliders for acceleration and sensitivity in the Gnome mouse control panel never seemed to do anything, as if they were just included for placebo effect. Well, in Gutsy, I still can’t tell if the sliders are doing anything, but happily the mousing feel out of the box is nearly up to par with Windows. My laptop’s touchpad is similarly satisfactory. While still not perfect, the mousing in Ubuntu is sufficiently good I rarely notice it (unlike in OS X). Still, the fact that the motion adjustments don’t seem to work worries me: I could have just gotten lucky this time with my choice of hardware while other people might not be so lucky.

[To be fair, after a few minutes spent playing with a new model iMac, I must confess the mousing was quite good, even with the gimicky mouse (the fact that I was using a fast, responsive system rather than the under-powered MacMini probably made the difference here). Also, Apple's new ultra-thin keyboards work surprisingly well considering they appear horridly anti-functional.]

Graphics driver, 3D acceleration, and multi-monitor

Unlike in previous Ubuntu’s, installing working 3D drivers in Gutsy for my latest and greatest nvidia card was effortless. On the downside, the “new” nvidia driver is proprietary, but I’m OK with this, as I don’t think the strategy of boycotting proprietary hardware will pressure the graphics chip makers to release open specs or drivers. Features like Compiz need to get in front of users for proper attention to be paid to 3D among the develeper community, let alone the chip makers, and as long as no one is actually using 3D hardware on Linux, nvidia, ati, and intel will feel little pressure to advance the platform. Hopefully, ati will fulfill their promises of open source drivers and specs for R500 and later hardware, and hopefully success there will prompt nvidia to do the same. (Like with Samba and proprietary multimedia codecs, the basic strategy here needs to be the FOSS version of “embrace and extend”: supporting proprietary technologies gets Linux out of the gutter while interoperability increases use of free technologies. FOSS needs market power first before it can make demands. But that’s a whole post unto itself.)

Getting my second display configured was frustrating at first, but running ‘nvidia-settings’ got everything in order (run it as root so that it can overwrite xorg.conf). The Linux multi-monitor situation is a bit confused at the moment because of limitations in the underlying X window system that have yet to be corrected or worked around. This results in some unsatisfactory behavior: currently, my desktop is a 3600×1200 virtual desktop such that it extends off the top and bottom of my 1680×1050 display; while maximization on that display thankfully works correctly, some oddities occur, such as desktop icons hiding off screen.

Sound

My Audigy X-Fi is not supported in Linux except by proprietary beta drivers from Creative Labs for 64-bit Linux only. As I have yet to get 64-bit Gutsy working, I can’t report on that support. Rather than swap back in my Audigy 2 ZS, I turned on the onboard audio in my bios. This got sound working, though I did have to fiddle a bit in the sound panel. Also, I can’t get anything beyond 2-channel sound to work, likely because the onboard audio’s jack sensing is not supported by the drivers, so the 3 jacks from my motherboard are stuck as line-in, line-out, and microphone (hmm, except then you would think I could get sound to record, though I can’t).

These driver issues are understandable considering I’m using a relatively new proprietary sound card and a not-so-common generic onboard solution. Really though, the biggest failing of Linux sound-wise at this point is not any lack of hardware or lack of auto-configuration but simply that the sound situation is so damn confusing. In trying (and failing) to get 6-channel sound working and in (successfully) fixing the lack of sound in Flash on my father’s system, I was confronted with a mess of OSS, ALSA, ESD, OpenAL, PulseAudio, and a whole array of opaque options I didn’t understand. Hopefully these projects will coalesce or at least learn to better exist side-by-side so they can be configured to work simultaneously on the same system. The situation feels like GNOME vs. KDE of several years ago when getting KDE apps to work in GNOME and vice versa was tricky.

Font rendering

In previous releases, smoothed font-rendering was tricky to get working, but now it is turned on in GNOME by default. You can even select between “best shape rendering” (OS X -like rendering) and “subpixel rendering” (Windows-like rendering). (Here’s the difference between the two.)

On the downside, the selection of fonts out of the box is a bit lacking: too many almost identical sans fonts, not enough quality serifs, not enough monospaced fonts. On the upside, most of the included fonts are quite good, especially the great Monospace, which is very similar to Microsoft’s new Consolas font but with a few changes that make code even more readable.

Multimedia codecs

On all Windows installs, I install mplayer, vlc, and the K-lite mega pack because doing all that seems to cover all bases, codecs-wise. In previous Ubuntu releases, I’ve been lucky to get MP3 support working, but in Gutsy, I finally don’t have to worry about codecs. I simply open any media file in mplayer or vlc, and GStreamer detects which codec I need and downloads it, and then the file plays (though sometimes only after restarting the player). Dubious legality aside (OK, not so dubious illegality—I’m in the US, and it definitely ain’t legal), the only way for codecs to work better is to simply have the whole lot installed by default.

Portable music players

My Creative Labs Zen Microphoto (8gb) used to work fine on Windows XP before Creative discontinued its original drivers (which they pig-headedly don’t offer for download) and upgraded its firmware to use Media Transfer Protocol. Now, Zen users on XP must use Media Player 10 to interface with their device, but it’s never worked for me. Since then, I have had to use my laptop to charge and interface with the device.

In Linux, applications can use libmtp to interface with MTP devices. Ubuntu installs by default Rythmbox, a stripped-down but slick iTunes-like player, which supports libmtp via a plug-in. I just wish it were clearer that you must enable the MTP plug-in (in the plug-in preferences) before your device will be recognized, as it was days before I noticed the option.

So here’s a case where something works for me in Linux but not Windows (XP).

(I should also remark how much I like Rythmbox, which is surprising considering I dislike iTunes. The key thing that makes Rythmbox acceptable to me is that it keeps your music files in place rather than presumptuously duplicating and re-encoding your entire media collection the way iTunes is wont to do.)

Package management and application installation

In the previous Ubuntu, I had trouble with Apt (the package manager) getting buggered right out of the box such that its database got locked, causing Apt and Synaptic (the GUI front-end) not to work at all because they couldn’t access the database. This happened consistently immediately after a clean install, rendering Ubuntu basically unusable.

It’s annoying that many packages in the repository are for old versions, even for major programs, like Eclipse and Azureus. Azureus, for instance, wouldn’t work for the version I got from Apt; only the latest version, gotten manually from the Azureus site worked. So there are many cases where you must go fetch a lot of apps by means other than Apt.

Java

Now that Java is free, I assumed it would be included by default, but that didn’t seem to be the case (or at least, I had to manually install Sun’s Java 6 to get Eclipse and Azureus working). It’ll be nice when this situation gets resolved so users can simply have Java apps working out of the box.

Web browsing

Firefox in Ubuntu is much slower at rendering than in Windows. In Windows, my habit is to ctrl-mousewheel to change font size, and Firefox resizes in real-time as I scroll the wheel with all but the most complex pages. In Ubuntu, even simple pages can take a moment to resize the text, so I had to train myself not to reflexively resize pages. You can also see Firefox’s slow rendering in pages like Google Maps, where dragging the map is far from smooth. It’s likely this slow rendering is tied to inefficiencies in GNOME, X, or maybe the new font rendering, as I can’t imagine that Firefox’s rendering path changes much between Linux and Windows. It’s possible the new font rendering is causing this slow down, ormaybe something similar is the culprit, but I see the problem on all machines I’ve installed Gutsy. Hopefully Firefox 3′s new rendering engine (with a Cairo backend) will bring this back up to par.

(Sadly, my favorite Compiz plugin, Enhanced Zoom, causes animated cursors to disappear after the first time you zoom in, and this is most aggravating in Firefox, where the cursor animates as pages load; the only fix is to restart X (by ctrl-alt-backspace), but this closes all your programs, so the only real solution for now is to just disable Enhanced Zoom.)

User switching

A panel widget included by default is “fast user switching”. I’ve experienced debilitating bugs with this widget, so I suggest you not use it.

Gnome desktop

Finally, I have some assorted thoughts on GNOME:

Thankfully, the application menu has been cleaned up since Ubuntu’s last release: rather than listing apps by their project names—names which are meaningless to most people—most apps now are just given simple descriptive names that reflect their functionality. The menu editor, however, could stand some more work, as it’s a bit hard to discover and awkward to use.

In previous GNOME’s, the icons ranged from acceptable to ugly turd. Now, the default set of icons in the menus and file browser not only do not look like crap, they are actually very attractive and exemplary models of clean design, better even than many icons seen in OS X. And speaking of bling, I do wish there were more color themes and bundled wallpapers with the stock system in the vain of Windows. It would be neat if they included some of the great photos from Wikipedia’s photo of the day, which includes some very neat panorama shots.

The default panel config of Gnome is a silly attempt to split the difference between the Windows / Mac desktop, and too many unnecessary panel widgets are included by default. At the very least, a quick panel config wizard should allow me to choose the standard Windows taskbar layout.

Unfortunately, my biggest irritations with GNOME can’t be fixed with a lick of paint. First, windows with scroll panes inside open too small to see the content of the scroll pane, forcing me to resize or maximize these windows to properly see this scrolled content. This problem is exasperated by my other grievance: grabbing window corners is too tricky, and I often accidentally click with the horizontal or vertical resize cursor when I wanted the 2-axis resize cursor.

Idiots at the Gates

4 Nov

In discussions of programming education, the argument is often made that learning to program shouldn’t be made easier. This is the Let’s Filter Out the Idiots argument, common also to the fields of law and medicine (or so I’m told). The idea, basically, is that the discipline must retain a face of esotericism to the outside world as a barrier, the passage through which marks a rite of passage for initiates, thus preserving standards within the profession. I’ll concede that there are actually a couple good justifications for a general attitude of anti-idiotarianism:

  • First, law, medicine, and computing are genuinely complex fields, so a large degree of esotericism is unavoidable.
  • Second, in these fields, a little knowledge can be a dangerous thing. In fact, in the case of doctors and lawyers, the purpose of the face of esotericism is likely not at all to avoid creating bad doctors and lawyers—their certification processes are sufficiently rigorous to avoid that—but rather to discourage laymen from thinking that they can practice amateur medicine and law. There may be an element of protectionism to this, but it’s mostly a good idea. Even programmers have legitimate cause to fear amateurs, for amateur programmers tend to create Frankenstein systems, messes which create problems for everyone involved (see this example of a near miss).

However, the anti-idiotarian arguments for maintaining educational barriers to entry are bogus:

  • First, keeping the first phase of education difficult is supposedly necessary to weed out the incompetents, but this is backwards: if people are getting certified who shouldn’t, the problem lies with the certification standards, not the number or quality of the people pursuing certification. (Of course, programmer certification remains problematic, but that’s a whole other issue. See here and here.)
  • The second bogus argument goes like this: in any field, to be much good at what you do, you need a solid grasp of the next two or three layers of abstraction beneath where you primarily work, e.g. decent web developers understand the basics of HTTP, DNS, caching, database performance issues (if not the implementation details), etc, and beyond that they have a working conception of operating systems and general programming tools; essentially, you can’t be a good programmer if you treat your tools and development platform like magic. But, if the technoratti consensus is correct, this, sadly, sums up what’s wrong with a very large percent of people out there who call themselves programmers. So far this is all very true, but then some go on to claim that enabling easier entry to the field necessarily means enabling the next wave of push-button “programmers”. This is wrong. What makes such people bad or “fake” programmers is that they don’t understand essential aspects of programming and computer science, not how they acquired what knowledge they do (or don’t) have.

The zealous anti-idiotarians are missing the point. Making the basics of the field easier to learn benefits everyone, sparing pain for the incapable and hyper-competent alike: those who lack the disposition can get out earlier while those who stay can cover more material in less time, and just maybe a few capable students won’t get discouraged as they otherwise might by the overwhelming minutia of the practice of programming.