Friday, October 28, 2011

Simplicity: We have a long way to go

My mother-in-law called me early the other morning with a new helpdesk request. When you're a computer geek, you get to play IT for your whole family, the neighborhood, your friends, your son's girlfriend, the local elementary school...guess I should take The Oatmeal more seriously. My mother-in-law's latest problem? She pressed "channel up" on her remote and the TV thusly displayed "no signal". No amount of further button pressing would restore her morning news.

Of course, I immediately knew what happened. She has cable and uses the cable box's remote control to do only three things: turn the TV on and off, change channels, and change volume. The cable box is also a DVR, and I set it up to record her favorite shows, but despite numerous training sessions, my mother-in-law has not yet passed the "how to watch recorded shows" lesson. But she's 78, so I'll give her a break -- I'm proud she bought an HDTV, subscribed to cable, and learned how to do the three things above. And the three things work just fine 99% of the time. Until you press the TV button.

The simple three things only work if the remote is in "cable mode", meaning the Cable button is the last device button that was pressed. When this is the case, it is smart enough to turn on and off both the TV and cable box when you press Power, send volume up/down signals to the TV, and send channel up/down signals to the cable box. But if for some reason you press the TV device button, when you press channel up/down, the signals are sent to the TV. But the TV's input is normally set to HDMI 1, for which there are no "channels". So what does the TV do when it gets a channel up/down signal? It changes its input to Antenna and looks for a signal. Which isn't there. Which is why it now displays "no signal". Which is why I was called early in the morning.

Just to make things a little more fun, the cable remote has no button to change inputs on the TV. (And we have no idea where the TV's original remote is. Probably in the same place as all the missing socks.) So our helpdesk phone call next turned into a hunt for the TV's input button. Which involved putting the phone down, finding a flashlight (since the TV sits in a dark corner), pressing some of the wrong buttons, "HID what?", "no, HDMI 1", "it says Component 1", "keeping pressing it", and finally, the morning news is back. Of course, due to erroneous button pushing, the volume is now so loud she can't hear me, so she has to move to another room. I tell her to use the remote to turn the volume down and be sure to press the Cable button, but she left the remote in the other room, so it takes another another minute or two, but we are finally back to "normal". Helpdesk case closed.

In my mental postmortem, I thought: who on earth would design a TV so that, when channel up/down is received while using an HDMI input, it would switch to Antenna input? What was the use case scenario in which that made sense? As a software engineer, I have to believe that someone deliberately added that feature but with no obvious sense of usability. I can just see Steve Jobs screaming at his engineers whenever they attempted to add such a lame, user-unfriendly feature. Though Apple's venture into television are strictly rumors for now, and Jobs won't be around to veto dumb features, I'm sure Apple's TV won't have the same flaw as my mother-in-law's TV. We have a long way to go to make everyday consumer electronics more friendly. Let's hope Apple continues to push the envelope.

Back at home, my wife is trying to print something on her laptop, and she's asking me, "Why won't this print? Does it have something to do with 'Print Spooler Crashed'?" Sigh.

Friday, October 21, 2011

Erlang: Not Today


In the last few years, I’ve been thinking about concurrency limitations with traditional programming languages and locking techniques. Increasingly, this has drawn my attention to functional programming languages (FPLs) that, among other things, employ immutable state, which means a variable can’t be modified once it is assigned. Even collections can’t be modified: you can create a new list by concatenating two existing lists, but the new list thereafter is also immutable. (Under the hood, compilers don’t really copy entire collections with every operation: sometimes they merely move pointers around or pre-pend a value to a list.)

The immutable state approach requires programmers to decompose problems in new ways, such as creating actors (lightweight processes) that communicate via messages. Recursion – especially tail recursion – is also a major weapon of choice. The resulting applications are easier to parallelize without synchronization primitives (mutexes, semaphores, etc.) and the corresponding dead locks, race conditions, and other nasty things that ensue. In fact, parallelization is sometimes handled completely by the runtime, which launches the optimum number of worker threads based for the underlying hardware.

After doing some research, I decided to try Erlang as my first FPL. (I discount the Lisp class I took in college since I have long since forgotten it.) I started with the usual approach: bought some books, ran through some tutorials, and wrote some “hello world” apps. Since I was fortunate enough to attend the StrangeLoop conference this year, I signed-up for the two Erlang pre-conference sessions to get some tips from the authors of Erlang and OTP in Action. Being further inspired at the conference, I plunged a little deeper into Erlang and created some simple apps demonstrating tail recursion, processes and messages, higher-order functions, and other functional concepts. I ended by employing the gen_server behaviour (yeah, they spell it with a u) to create an RPC server (using the example from the book). It's cool: you can connect to the RPC server using Telnet and call any public function in the entire Erlang runtime, including init:stop(), which shuts down the runtime! (Security wasn’t a goal of the example.)

I continue to be impressed with the power of Erlang, but I also came away thinking maybe this isn’t the best FPL to go further with, at least for now. Here are my reasons:

       Tool support: Emacs is the “official” IDE for Erlang. I’ve used a lot of IDEs, but I never learned Emacs, so I opted for Eclipse and the Erlide plug-in, which is awful. It crashes a lot trying to open files, displaying tool tips, etc. Eclipse becomes unusable after laptop suspend/resume cycles. The debugger is worse than the command-line “erl” app. Refactoring is so slow and inconsistent it’s unusable. I read about alternative IDEs, and it appears that I’d be better off with UltraEdit or TextEdit.

       Debugging: As far as I can tell, there’s no step-wise debugging. I don’t see why not: even though Erlang is an FPL, it calls functions and executes statements serially. Stepping through multi-process apps should be no more complicated than stepping through multi-threaded apps, for which debugging has become pretty mature. Debugging appears to be mostly writing your own diagnostic “printf’s” and learning to decipher the strange errors that the runtime throws.

       Transcribability: Keep in mind that Erlang was started 20 years ago. It makes sense then that it has its own solutions for common programming problems such as scatter/gather I/O, asynchronous RPC, complex collections, interface/type inheritance, etc. My complaint is that solving these things has evolved in recent years, as evidenced in the rich libraries available in the .Net and Java ecosystems. But if you’re a master of one of these common idioms, Erlang has invented its own wheel and you may have to completely re-learn it. Some concepts transfer 1:1 (e.g., scatter/gather I/O -> I/O Lists), but some concepts such as interfaces and type reuse are very different, yet not really better. You’ll spend a lot of time re-learning stuff that has little to do with the FPL nature of the language.

       Anachronisms: Also probably due to its age, Erlang has things that, if they invented the language now, they’d undoubtedly leave out. Such as a C-style preprocessor (ifdef’s, define’s, and endif’s – oh my!) Some features such as catch expression are allowed but the OTP book warns not to use them – they don’t work properly or are replaced by better methods. Some features such as “-behaviour” are compiler enforced, yet others such as “-type” are more like documentation, and errors are found only if you run the Erlang dialyzer tool. The language has many hints of a patched history and uneven features.

       Ant turd syntax: I came to understand why others have complained about Erlang’s syntax, which requires very carefully placed commas, semicolons, and periods. You have to use these carefully: mistakes cause strange errors that can be difficult to understand. Minor differences in syntax (= vs. == vs. =:=) can cause a program to compile and run but produce unexpected results. You have to be very aware of little things like arrows made with a dash (<-) versus arrows made with an equals (<=). Given list comprehensions and other features that are dense with punctuation, it’s easy to mistype something that may even compile but won’t do what you think it should. (Another silly example: less-than-or-equals is written =< so that it doesn’t look like an arrow!)

Many of these are personal quibbles, and I’m sure I’d get over them in time, but that would take a lot of time. Using Erlang requires knowledge of not just the language but the whole OTP runtime and its huge library of modules and functions. (BTW, I find the online Erlang/OTP documentation difficult to navigation: if you don’t know what library has the to_atom() function, good luck finding the documentation for it. For most functions, I started with Google.) Given the poor IDE support and lack of interactive debugging, my sense is that mastering Erlang and its ecosystem would take 6 months of real application development (for us mere mortals, anyway). Maybe I’ll have 6 months to dedicate to it some day, but not today.