Monthly Archive for September, 2011

RS Latches


One of my oldest memories harkens back to 1989 — I was a four years old boy in communist Romania. My mother has a PhD in biochemistry, and her father and brother both had a PhD in physics, so it might seem quite unsurprising that I followed in their rational and scientific steps, but it would be hard to put the proverbial finger on how, precisely, that happened. This is what that specific memory is about.

It all started with my frequent stays at my grandparents’ house, a conventional second-floor flat in Bucharest, where my grandmother and grandfather took turns babysitting me while my parents were out hammer-and-sickling (well, laboratory-and-architecturing) the socialist ideal. My grandfather was intent on turning me into a bright scientific mind, so he asked my uncle to build me a computer. Nothing fancy, mind you : it had no operating system worth mentioning, no hard drive, and depended on magnetic tapes and 8″ floppies to actually work. My grandfather showed me a standard BASIC interpreter, and had me type in a program that displayed, line by line, an analog wall clock.

Fascinated, I started spending my days on that thing writing BASIC code, learning how to build increasingly complex programs, and starting my career as a programmer. Or so had my grandfather hoped. A few seconds after discovering computer programming, I discovered computer games, which were a far more fascinating novelty than displaying wall clocks on a screen. I promptly forgot about the BASIC interpreter and for nine long years, I assumed that programming computers was some sort of esoteric arcane art, invisible to the uninitiated, and remained entirely uninterested in it.

Instead, my breakthrough as a rational mind was triggered by the close proximity of two unlikely catalysts : one was a frequent diet of mecha anime (the quality of the Romanian dubbing was hilarious), and the other was a cupboard drawer full of bits and pieces that could, to a child’s mind, be spare parts out of which a robot could be built : wheels, small electrical engines, cables, batteries, microprocessors, light bulbs… as a matter of fact, once I had the basic understanding of how a batteries + cables + engine setup worked, I did build small uninteresting contraptions.

I became intensely interested in building a robot myself. Obviously, I did not have the technical skills or the willpower to follow through with this plan, but I would listen, entranced, to any explanations I would receive that were related to robot-building. My grandfather was writing a book on semiconductors at the time, so he showed me a large digital circuit and let me understand that this is what the brain of a robot would look like — only quite larger !

And so he started teaching me the elementary principles of digital circuits. We spent little time discussing the underlying technical details, and instead concentrated on the simpler abstractions of logical gates. This time, I was fascinated. I would grab a pen and paper and draw circuits for fun. The meaning of AND, OR, NOT, NAND, NOR and XOR are imprinted in my brain ever since I was five years old… there are few concepts remaining in my brain that have been there for so long.

My circuits behaved like mathematical functions : I would mentally set the input bits, and the output bits would contain the result, so I could build the truth tables that mapped input combinations to output combinations. I experimented with basic arithmetic functions, learning binary as I went. And then one day my grandfather showed me a circuit that I could draw from memory to this day : the RS latch.

The fun thing about the RS latch is that it cannot have a truth table. It is an entirely different beast from arithmetic “write input bits, read output bits” circuits in that it has a state. If you write 1 to the S input bit, the output becomes 1 and remains 1 until you write 1 to the R bit, at which point the output becomes 0, and so on. To say things differently, the S input bit stands for “Set” and sets the output to 1, and the R input bit stands for “Reset” and sets the output to 0. When both R and S are set to 0, then the latch output bit is equal to whatever it was previously set to.

The RS latch is a versatile little thing. It can be used to implement RAM (one of the first things I did with it), or it can be chained to create an incrementing counter.

After a while, my interest in digital circuits faded, but the effects it had on my character were permanent : I now had experience applying abstract rules to abstract concepts, and it was fun.

Article image © Cornelia Kopp — Flickr

jQuery Datepicker – the Instance Data bug

The jQuery UI datepicker does strange things with the DOM, which causes undocumented brittleness. For instance, consider the following operations on a page that contains a single input element:

$('input').datepicker().attr('id','the-input');

This will cause no error, and clicking on the input will correctly summon the date picking dialog, but clicking on a date in that dialog will fail with the following error:

missing instance data for this datepicker

The diagnosis is quite simple: the jQuery UI datepicker stores additional “instance data” based on the id attribute of the element, so changing the id attribute manually causes that instance data to be lost. This unexpected brittleness forced me to spend some time hacking my code so that the identifier is attributed before the datepicker is enabled, but at least this solved the problem.

Two related problems would be:

  • If you have several input elements with the same identifier, and apply the datepicker on the second element, the search-by-id will return the first element and cause the same error as above.
  • If you apply the hasDatepicker CSS class on an element, and then apply the datepicker plugin, it will assume that the instance data has already been initialized, and will fail.

Having a Strong Opinion

Many blogs about technical hiring will at one point state something about buzzwords and programmer flexibility. One of the original trendsetters, Joel Spolsky, said:

The recruiters-who-use-grep, by the way, are ridiculed here, and for good reason. I have never met anyone who can do Scheme, Haskell, and C pointers who can’t pick up Java in two days, and create better Java code than people with five years of experience in Java, but try explaining that to the average HR drone.

And this is not only a point about elite languages like Scheme-Haskell-C versus mundane languages like Java-PHP-whatever : flexibility, the ability to switch languages and to adapt to new interfaces and libraries, is almost always presented as a prerequisite to being competent. John can perform miracles with PHP but cannot easily learn Ruby ? Then John is not a competent programmer, he is just a competent PHP programmer.

Maybe there is some truth to this characterization. Maybe there is indeed something about good programmers that lets them shine in a language-independent way, with languages as mere details of their day-to-day miracles. But I am vaguely uncomfortable with that notion. And not for personal reasons — my current language of choice is one of those elite functional languages that would hypothetically place me at the apex of the competence food chain.

I believe the critical element of programming competence is not ability but passion. What makes you a good programmer is how much you care about software development. Does John have a nine-to-five PHP programming job and hardly touch the computer outside of work, or does he do small projects on the side, or contribute to Open Source PHP software, or answer technical PHP questions on Stack Overflow, or perform any other number of PHP-related activities that do not have professional rewards as their main objective? Does he unconsciously try to do the right thing in his code, even though it will be harder than writing a dirty hack to make his boss happy?

I have seen people, many of them high-ranking academics, with the intellectual firepower to outgun me in any programming-related endeavor, but a striking lack of passion that let their applications crippled, hideous and unreliable. And I have no doubts that, had they cared about those things, they could have done better.

I have seen people, many of them students, with a genuine passion for software development, who would spend their free time hacking together video games or dynamic websites or clever hacks, who would notice after a while that their abilities were stagnating and, unable to improve, would give up programming rather than live with the frustration of writing software worthy of their expectations.

And when you care about programming, you tend to have strong opinions about how it should be done.

Some of these opinions are trivial. My hair stands on end whenever I have to read badly formatted code — I don’t care about the opening-brace-position flame wars, any convention is fine by me as long as it is consistently followed — and the authors often wonder why I would care about such a silly thing. I have a strong opinion about how code should look like, and I dislike working with people who do not share that opinion.

Yes, I am one of those Scheme-Haskell-C elite programmers, and I can pick up Java in a few days and outperform experienced Java-only programmers. I have done it several times in the past. And every single time I did so, I felt dirty and miserable, because Java goes against several of my opinions about what software development should be like.

In fact, I am not really surprised about the popular success of Python and Ruby on Rails — not in terms of how many projects are written, but in terms of how outspoken the technical advocates are. This is because those two have something that appeals to people who can become passionate about them : a clean core philosophy you can agree or disagree with.

Python zealots flock around the Zen of Python :

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!

Ruby on Rails fanboys have a similar set of core beliefs, the Rails Way:

DRY – “Don’t Repeat Yourself” – suggests that writing the same code over and over again is a bad thing.
Convention Over Configuration – means that Rails makes assumptions about what you want to do and how you’re going to d o it, rather than requiring you to specify every little thing through endless configuration files.
REST is the best pattern for web applications – organizing your application around resources and standard HTTP verbs is the fastest way to go.

So, if you happen to wholeheartedly agree with the Ruby on Rails way, then by using it you are certain to find both a technical environment in which you can feel happy, and a community that shares you strong opinions about software development. It is any wonder, then, that people passionate about the RoR values would flock to RoR and, inevitably, start advocating its use?

Going a little bit further, if you are hiring for your software company, would you rather hire someone with weak opinions on most topics because they are «flexible» or someone with strong opinions that match the strong opinions of your company? Given the choice, I would certainly hire the latter.

I have my own «core philosophy» that I apply to the way I write my own code. These would be, by order of decreasing importance:

  1. It is better to have a correct program with few features, than a buggy program with many features.
    If possible, take the time to design your code and your interface so that errors cannot happen. If not, explicitly detect and display all errors as they happen. If possible, have a programming language and a programming style that can eliminate by design many errors, rather than a programming language or programming style that improves productivity at the cost of having more errors.
  2. It is better to prove the correctness of a program, than to test for the existence of bugs.
    Tests cannot prove that the software is correct, they may only prove the existence of bugs. A proven program contains no bugs, there is no worry about having enough code coverage and enough test cases. This is a special case of “fail early” : better to fail at the compilation stage, than to fail during tests or at runtime.
  3. It is better to accept that code will have to be rewritten, than to future-proof a complex design.
    Future-proof code will likely be larger, and contains more untested pieces, than normal code. This increases the probability of bugs, without completely eliminating the possibility of a completely unforeseen design change that still involves a rewrite. Preparing your code for a rewrite, by splitting it up into clean independent self-documenting modules and creating automated correctness checks for these, is the best way to make it flexible.
  4. It is better to enforce data constraints through types, than to enforce it through code.
    Attempting to store data that violates the constraints fails earlier if the type cannot represent that data, especially in a statically typed language. Doing things this way might take longer than just keeping a flexible data type and performing the constraint checks in the code, but the odds of it being correct are higher.
  5. It is better to have the computer do work for you, than for you to do that work yourself.
    Why write trivial unit tests when you can harness the type system to perform those checks? Why define or configure things by hand when your framework could define or configure them for you?
  6. It is better to rewrite your code using new concepts, than to insist on using existing but ill-adapted concepts.
    Concepts improve productivity and readability, and by design will prevent some kinds of incorrect usage, but only as long as they match what the software is expected to be doing. Otherwise, at best they will be a useless weight and at worst will have to be tediously worked around to achieve anything. The size of the refactoring is no obstacle: if half the application needs to be adapted to the new concept, then so be it.
  7. It is better to repeat yourself from time to time, than to introduce too many concepts.
    Any repetition can be eliminated by adding a new abstraction through refactoring. That abstraction is usually a mere application of an existing pattern or concept, but might sometimes give flesh to a new concept. While that concept arguably already existed in the non-refactored code, it is easier to understand uncommon concepts by looking at their repeated code, than to give them a sufficiently understandable name.

I don’t know. Maybe someone might agree with me one day.
Article image © Timo Newton-Syms — Flickr



1342 feed subscribers
(readers who polled a feed this week)