Software Developer and GNU/Linux specialist

Choice overload

Have you ever gone to a library with no idea what you’re looking for? That’s how I feel when I consider what has happened to the computer industry since I first became aware of it (I was five years old when my dad started teaching me BASIC on a VIC-20 he set up in my room. Can you say “doomed”? I knew you could.)

3-tiered book rotunda

When you look at the menu of choices for technologies with which to engage as a hobbyist or professional, being proactive is a truly daunting challenge. The problem is that there are so many choices. If you’re involved in software development, you’re already past some major decisions. You’ve chosen a specialty. Or have you? When computing was still a young practice and computers occupied whole buildings or at least whole rooms, to be a computer programmer meant you were indeed a specialist. A specialist in computers. But as one could reasonably expect, the field has blossomed and expanded with the ever-increasing adoption of computers in every aspect of human society. So “computer programmer”, “software developer”, and other semi-interchangeable titles are no longer specialist titles in computing any more than “doctor” is in medicine.

How many programming languages are there? Probably over 750 that have actually been published and used widely enough for inclusion in this list. And that’s not the comprehensive list, because such a list cannot be made. People create their own languages for special applications all the time.

You can probably throw out the bulk of the options on that list when considering languages to learn. Experts such as Larry Wall and Bjarne Stroustrup sometimes recommend learning about five programming languages. I know what you’re thinking. “Five? But there are hundreds, maybe thousands! That’s hardly a drop in the bucket!” Well, if you’re not thinking it, I am. That’s what brings us here. How does one choose such a miniscule fraction of the whole array of options? There’s not even enough time in one’s life to properly survey the entire thing.

There are tools that offer some help. The Tiobe Index offers some insight as to which languages are most relevant in current industry based on Web search keyword frequencies. As of my writing this, C tops the chart. (You’ll find out that C is always somewhere near the top; most developers with whom I speak are well aware of the reasons why, so I won’t parrot them here.) Another useful tool is the GitHub language list, which ranks the languages used in active projects on GitHub. OpenHub, formerly Ohloh, follows active Free and Open Source projects and offers statistics on programming language usage.

Let’s suppose that we use these tools–or go with instincts, or draw from a hat–and decide on five languages. I’ll take Javascript and Python, for certain. C and/or C++ is tremendously useful, so let’s cover some ground there. Perl is quite popular as well, and I like Bash scripting simply because it’s ubiquitous in Linux systems and I’m a Linux guy. We won’t bother with the weird ones like Brainf**k, because we want a repertoire that’s actually useful.

Now another problem arises: what libraries should you know? There are whole databases out there just for all of the Javascript frameworks. You can do a lot with it, which is very odd considering its origins and early history. I’m not even going to try and count the JS frameworks, libraries, and toolsets in existence. There are tools for front-end Web application development, others for server side development, and yet others for neither: they’re programming and build tools that are never meant to leave a dev environment. There are many libraries for testing applications, each based on a different methodology or paradigm. The same can be said of Python. The language is over two decades old, and in that time a vast collection of libraries, utilities, frameworks, and applications has grown. Even if you do nothing but write programs in Python, there is no way to comprehend all of the existing code you could use to build new applications. The same is true, only worse, for more long-standing languages like C and C++, Java, and the like. And I’m not even scratching the proverbial surface.

If you’re already making more money than I do developing software (and you probably are), it’s unlikely that any of this is a serious problem for you. But for someone who is both curious about the vast landscape of computing and looking for a path through the complexity toward a goal worthy of his or her pursuit, the choices presented are boggling. There is something to be said for the adage that it’s best to start where you are with what you have. There’s also something to be said for indulging curiosity. Every once in a while, make like the Enterprise and explore strange new worlds.

Oh, and check out Brainf**k. It’s the most aptly named language I’ve ever seen.

Seeing context

I’m standing in a room with a lot of glass and several mirrors at different angles. Looking into a glass pane, I can see my own reflection, but at an unexpected angle. It’s not my straight-on reflection as through a single mirror; it’s very shadowy (it’s glass, after all, and not a mirror) and I can’t figure out where it’s coming from.
Then I have a minor epiphany. I’m looking at my reflection as if I were looking at myself in the flesh. But I’m not looking at myself. I’m actually looking at an image in glass. The image of me is an integral part of that image, and there are other integral parts that I’ve failed to acknowledge. Like the mirror carrying the original reflection.
Looking out from my image to the image of the mirror, I realize that my reflection is in fact a repeated reflection: I’m looking at actual glass, which is reflecting a view of a mirror, which is reflecting a view of me. The creation of that image is at least a three-step synthesis, but I have been treating it as if it were a single step. What gives away the reality is a realization of context: the context of my reflection is a mirror, and the context of the mirror is the glass reflecting it all.

Problems like this occur all the time. The human brain seems to be wired to accept unchallenged input as representative of some reality. In other words, we have a nature of trust about us. The skill of mentally stepping back and viewing the context of a trusted input is crucial in the sort of black-box troubleshooting that occurs in some technical settings. When we don’t have access to the internal structure of a library or function in a program, the output it produces may appear as a unified image. But when program functionality composes and nests results (and most complex programs do that), the ability to mentally dissect a result becomes crucial.

So how is that sort of thing done? Well, admittedly, sometimes it isn’t. In some cases it’s far more practical to just replace whatever isn’t working. Sometimes the bug or issue has been fixed by a new release of the same software package, and it’s better to upgrade. This is one example of what Steve Litt calls preventative maintenance. And there are other considerations at work as well: how broken down is the problem context? Are there still two or more discrete components to the section of the system to which the problem has been narrowed down? If so, more elimination steps are in order. Then consider the input coming to the component where the error seems to occur. It may be perfectly legitimate input, but it may fall outside the domain of the component you’re checking. Incorrect formatting, values out of range or of the wrong size, too many fields or too few, all indicate expectations of an interface unlike the one receiving the data. They may or may not cause the component under examination to fail to function; if not, they may produce anomalies that appear to be internal malfunctions.

Picking apart an output in the way I’ve vaguely and allegorically described is, as we can see, not an easy process to define. The essence of it is a way of seeing the problem, of thinking about the output on several different literal planes. It’s also not foolproof, as the only guaranteed way to get to the bottom of a system’s functionality is to see its original construction. In black-box cases, that knowledge is hidden. When documentation of program internals is available, it may be slightly less obscure. So one is left to scientifically poke at a system with hypotheses about what each poke will produce, with the expectation that sufficient input/output observations will prove instructive. This may be a slow alternative to reading the source code, but when the latter isn’t feasible, we at least have a reliable fallback.

Double- versus triple-equals comparators in Javascript

If you’ve never run across the distinction between double-equal and triple-equal comparators, don’t worry. You will sooner or later, because they appear in several languages. Here I’d like to focus on Javascript, because I believe it characterizes a common distinction between the two types.

In a nutshell (and who was it who said that anything that can be put in a nutshell belongs there?) the distinction is this:

== and != compare and contrast values, coercing data types as needed. === and !== do strict comparison, meaning data types are compared rather than coerced.

But wait, some of you are asking. Javascript doesn’t do the types thing, not really. Numbers can mutate to strings and so forth. Yes, Javascript types are flexible and often easy to translate. That means nothing; the types are still distinct:

typeof false
typeof 1
typeof "1"
typeof variable_that_doesnt_exist
typeof undefined
typeof null
typeof []

The === comparator (and its inverse) don’t compare values of different data types; in effect,

a === b

is similar to

typeof a == typeof b && a == b

Why is this important? Well, if we’re just fooling around with a prototype or POC or you have tyrannical control over a system, it may not be. But more often than not, we’re dealing with frameworks, libraries, and services that aren’t under our direct control. A library function with multiple return types may mean something very different when it returns 0 instead of false, and if a comparison doesn’t take that into account, subtle errors tend to emerge.

What does this all boil down to? I’m backing up Douglas Crockford here: use triple-equals if you’re at all in doubt. Your colleagues will give you strange looks, but your code will run predictably.


Angular.js, Select Menus, and User-configurable Option Lists

This isn’t a terribly technical jaunt, but it’s one worth writing down. I had a problem with a select menu in a web app. The problem was that comma-separated input for the options of the select was being incorrectly parsed. For example, suppose I saved a record with the list [“one”, “two”, “three”] (formatted as “one,two,three” in the input field) as the options list for the select. Instead of a select with items

“one”, “two”, and “three”,

I got items

“o”, “n”, “e”, “,”, …

and so on. One character per option. The select, which was there when I arrived, used a for-in construction in the Angular template: for each x in the values list, create with value x in the select menu. I began tracing through the code to figure out why it was splitting up the options in this very odd way, and I found that the select was being passed a string. What happens in Javascript when you do a for-in loop with a string is that it treats the string as an array—which it would be in C. Why not continue with the tradition?

If I had been programming in C, the fix for this would have been a bit more involved than it turned out to be. But where C strings are raw arrays (i.e. bare null-terminated strands of chars, which are really just ints that get treated differently), Javascript string objects are more…spiffy. They have methods attached, including a really convenient .split() method. That method takes an input. That input is used as a delimiter for the split function; every time it appears in the string, the function starts a new string. It returns an array containing the resulting segments, in a fashion similar to the PHP explode() function.

Now, the next question was this: how would I most easily get the array that I was going to create from that options string into the template where it belonged? While some think that Angular is singing its swan song—or has already sung it—criticism doesn’t negate the fact that Angular templates are very smart technology. That for-in construction doesn’t just allow iterations on scope variables; it allows iterations on the output of functions called on those variables. So instead of the options list being constructed out of

current as option for current in values

(there are reasons for that elaborate construction, but that’s another post and probably already published by somebody else), it could be

current as option for current in values.split(',')

This latter construction iterates over the output of the split() function, not the string on which it operated. The result is an array of strings, not an individual string. So instead of iterating over characters in the string (which Javascript, forgiving language that it is, pretends is an array of chars), the loop iterates over strings in the array. Hence I got the expected select, and I didn’t have to trudge through the back-end or change the way values were being saved. Which was great, because MySQL prefers strings to arrays.
Posted via UltraBlog.vim.

Toward an Abstraction of the “Facebook Idea”

The phrase “Facebook Idea” has been coined a number of times, most recently (to my knowledge) by me. Others who coined it have defined it in terms of money alone: a Facebook idea is one that will make someone rich. I believe the metaphor has a better use than that, and I want to outline it.
Some people believe that human nature is to be lazy. This common and mistaken idea probably stems from the principle that natural processes follow the path of least resistance. It is more likely the case that human nature causes us to prefer things we enjoy over things we don’t. While there may be more effort in those, we are biologically driven toward effort (survival and reproduction being the two fundamental biological drives of organisms) and will go to a great deal of trouble to follow the path of least psychological resistance. That is the path that we enjoy the most, or more likely, the one that seems most rewarding. In mature minds, those two constraints often coincide: we enjoy the most fulfilling parts of life the most.

It’s true that part of the reward I’ve suggested is a financial one. Why would we work at all if it didn’t provide us with means to live? And why would we take low-paying work if we could have higher-paying work that is equally satisfying? So part of the definition of the Facebook Idea is that it offers great financial satisfaction. I don’t believe it has to be on the same level as Facebook itself. But it has to be more than even a good salaried position to qualify. The compensation should allow one to determine one’s life with fair independence within the incident natural constraints.

In addition to being financially rewarding, Facebook was a project with broad appeal and high potential for success. I believe those principles apply to the abstract concept. A cheap and clean alternative to paint thinner is not a Facebook Idea. A cheap and clean alternative to gasoline might be one, but I also add something of a technological constraint with the notion of the choice to work. The choice to work is important to people pursuing their dreams. I believe no one really wants a boss. A Facebook Idea, if successful, can free its user from the command of a boss permanently. Someone who benefits from a Facebook Idea should be able to choose when, where, how, and even whether he works on a given day.

Final and perhaps more important is the element of personal interest. Scott Adams describes passion using unflattering terms, holding that we are passionate about whatever project or activity in which we find success. I believe that is too simple an expression to encompass the true value of what we call passion. The opposite of passion for a thing is called “burnout”, a psychological barrier to further work, arising as a consequence of any of a variety of causes. These can range from obnoxious obstacles such as office politics to years of failure, but I believe that those who become burned out most quickly are those who don’t really care about the work in which they’re involved. Resilience against adversity requires caring. And a really worthwhile idea often meets with a lot of adversity.

When using the phrase “Facebook Idea”, I am thinking of more than wild success or plenty of money. To condense the matter, I describe as a Facebook Idea any idea for a thing or service that’s interesting and enjoyable to work on, the result of which is interesting and enjoyable for others, which is consequently profitable. It can only be known for certain in retrospect, but some ideas may stand out as rare opportunities. I believe the trick to finding the right one is to pursue those rare opportunities when they come up. As Scott Adams points out, “luck” happens when you’re in the right place long enough for the right time to arrive.

Posted via UltraBlog.vim.

Test Post from UltraBlog

This is just a test post to see what comes out. I just decided to start blogging using ViM, because I keep a lot of technical journal entries here. So now we’ll see if that increases the frequency of my posts. Ciao for nao!

Posted via UltraBlog.vim.

Javascript debugging: breakpoints versus print statements

Conventional wisdom holds that print statements are poor practice for debugging code. Proponents of this view, myself included, reason that debugging code should be a nondestructive process. One should not change the code to diagnose it, only to fix it. Under normal deterministic conditions, I see no reason to say otherwise. Print statements are a poor substitute for line-level debugging and inspection. Excellent facilities for debugging, inspection, and profiling exist in most languages in current use, including JavaScript. If you’re thinking clearly just now, you probably want to ask me something like “fine, so are there circumstances under which you consider print statements a good practice?” There are, and I’ll tell you what I think they are.

Understand this first. I see no reason for print statements under deterministic conditions in which a debugger is available. In other words, I take it as a basic principle that so long as one can access a step debugger and control program inputs, and the program under such conditions exhibits consistent and predictable behavior, there is no good reason to alter the subject code. Any counterexamples of the rule must assume conditions that negate one of the premises of that principle. In the case of JavaScript programs, we have virtually universal access to a debugger. At least one browser-based debugger exists for Node.js (and, by extension, several other frameworks), and most other JS code that you will likely encounter as a developer runs in a browser, so the browser’s debugger provides the necessary facility. If you are using Chrome, you can even manipulate the code during run time and save changes to the file system. As widely used as JavaScript is, the near ubiquity of debuggers could change in the future. In that case you have a counterexample. Otherwise, no dice. And front-end developers can check academic arguments at the door.

All of the above being said, we have some other very good reasons to ignore the rule and use print statements or other code alterations for debugging. JavaScript behavior in browsers is not always deterministic, just mostly so. Timing means a lot in asynchronous systems. Suppose that an entirely synchronous local script depends on a datum from an asynchronous request to a server (the way we do most Web requests now). Prior to the receipt and processing of that datum, the local state may be called A. After the datum is received and a callback function triggered, the local state may be called B. Assume that the local script fails on line x, and I want to debug it. Being the careful and diligent developer that this writing demonstrates I am, I open my dev panel and set a breakpoint on the first executable statement in the local function, at line w (y lines before x, or line x – y). I step through the function until I hit line x. Expecting the failure to repeat (because in a troubleshooting setting I always want to reproduce the error as long as it’s not dangerous or destructive to do so), I step through the statement. It fails to fail as expected; I click the “continue” icon, and the function executes and the page displays as it is designed to. What happened?

Suppose that I am also astute enough to check the network activity panel of the browser. There I see the request in question (I can even ensure that it’s the correct one, because my favorite browser provides a stack trace for each request, though not yet for each websocket exchange). I confirm that it executed in 1.0546 seconds. But it took me several seconds to step from line (x – y) to line x, where the failure occurs under normal conditions. What is the state of the system (at least the relevant component(s) of that state) in that interval? Is it A or is it B? I can be a very fast clicker to find out using the debugger, or I can insert a console.log(…) at line x. Doing the latter causes the browser to spit out a navigable snapshot of a given datum that matches the state of the system at the moment the log statement executed. I can come back to it two days later and, assuming the computer is still running and the browser is still up, I can examine the now obsolete state. I can then make an informed decision on how to handle that state: whether to change it, provide a promise or other waiting mechanism, or something entirely different.

Depending on their content and use, print statements may be one example of what Andrew Hunt calls “tracer bullets” in The Pragmatic Programmer (49). Though not every debugging situation warrants the use of code-altering debug statements, in some cases they provide invaluable access to otherwise unreachable information about the inner state of a program. They should be among the trusted tools of any expert developer.

Smart Little Details

We eat healthy in my home. That’s why my wife and I both like to start our day with a sugary, marshmallow-ridden cereal like Lucky Charms. Today I pulled a new box from above the refrigerator and prepared to open it. The thing is that I hate opening boxes of cereal, because the lid flaps always tear on account of the glue. Then the top of the box is this crummy, tattered mess that makes me wish I could just go to the store with my own container and buy the stuff in bulk. Not so this time. I inserted two fingers under the middle of the flap and found no glue in just that spot. I slid my fingers carefully toward the edges of the flap to avoid tearing the paper as much as possible, and the flap came away clean. Underneath I found, on the other flap, two neatly cut rectangles where the printed outer layer had torn off; the glue had been placed just inside the scored areas, and the delamination of the paper had stopped at the edges. I had to smile; somebody clearly had thought about the frustration of something as simple and unimportant as a cereal box and decided that this one should open cleanly and easily.
I’ve been talking about a tangible product that’s been designed to please in a small way, a way that most people don’t think about very much. It’s one of those little details of presentation that add up to a big picture of a product. Details of this sort don’t really affect the usability or safety of a product, but they say something about what the producers think of both their product and their consumers.
Like cereal boxes and other tangibles, software is a product of human effort. It has core features (the cereal) and ancillary ones (the box and its details). It goes without saying that the core has to be solid or the product won’t be any good. But there is something to be said for the attention that designers and developers give to refining the ancillaries. Again, those extra touches are the difference between good enough and excellent. They may be the difference between something that is minimally viable and something people will enjoy using.
All that being said, the “nice points” of software products should not overrun the core functionality. Completion features are a good example for illustrating this idea. Most or all modern IDEs have extensive completion and popup documentation features, and in most cases they simply pop up. In some cases this happens at the first keypress. Even the fastest machine lags on the laborious task of loading all the data required to display those popup boxes. As a matter of course, I disable the automatic popups and set up hotkeys when I install a new IDE on a machine I intend for my own use. The whole reason for such a piece of software is to write other programs, and the code completion and documentation popups are supposed to be nice little helps. They are ancillaries, but by popping up like Web advertisements, they somewhat obscure the core purpose of the program. The key in adding nice little details is giving them just enough presence to matter without being in the way when they’re not needed.