An addendum to my so-called expertise

In August I delivered a presentation called “Mastering Asynchronous Flow Control in JavaScript” at devLink 2014. To illustrate how tricky mixing asynchronous and synchronous code in JavaScript can be, I gave the following example:

bad, bad example

I claimed, incorrectly, that the error thrown in the callback would cause unintended consequences when it re-entered the catch block (well, beyond just crashing the program).

I have since had a chance to re-visit this code and realized that this example is not representative of the point I wanted to make, which is actually represented by this gist:

In this example, an async function is invoked with a callback. Inside that function a try/catch block is executed, and when successful, invokes the callback within the try block. When the callback itself throws an exception it bubbles back up into the try block and then gets caught in the catch block, invoking the callback a second time. You can see this in the console output, where the first logged arguments object contains a null error and the second contains the error thrown in the callback itself. To avoid this situation simply invoke the callback outside of the try/catch block altogether:

Now I shall go into the East and diminish.

A really good second pair of eyes

This month (October) is my two-year anniversary at appendTo. Two years may not sound long to you but in the tech world it is a bit of an eternity. My wife Brittany still can’t believe I’ve stayed that long–most of my other jobs have been project-based and have lasted a year or less. When I started with appendTo my desire was to find a place to hang my hat for a while. And here I am, two years later, and the hat is still on the hook.

I flew to Tacoma with a co-worker, Matt, a few weeks ago, to help a large, enterprise company conduct an internal hackathon for their IT support team. We functioned as technical coaches, helping each of the five teams participating to make decisions about technical trade-offs (they had two days to finish their projects), and to help mitigate any technical obstacles that arose. It was a marvelous, albeit exhausting experience. When we met with this company’s leadership for the first time I was asked to describe what appendTo is all about, and this is what I said:

appendTo’s name is a play on the the jQuery function of the same name. In JavaScript we often want to take an element, say a hyperlink or a some emboldened text, and append it to some other element, like a paragraph. Our company has a similar relationship to the clients it engages: we append to that client, becoming a part of its team, to help accomplish its goals with our own expertise and values. We are very fast, and very effective.

I was then asked about my personal qualifications as a technical coach. Each team, in theory, could choose any technology stack for their project (though each project had to function on mobile devices), but in reality the company had a significant Microsoft infrastructure. Matt and I had spent a good deal of time discussing the potential technical avenues each team might take, and we had concluded that, given the time constraints and culture of the company, Microsoft-based, cloud hosted solutions were likely candidates.

Fortunately I have experience with the .NET stack, which put the client at ease. But I also stressed that my career has spanned many stacks, languages, frameworks and paradigms, and that I had sought from the beginning to be a generalist, not a specialist. To me, understanding problems is more important than particular solutions, which may be myriad. Problems are always contextual.

The leadership team then asked what I thought about my role in the hackathon. I replied: “I am going to be a really good second pair of eyes.”

It was a decent elevator pitch.

Each team ended the week with polished projects, and though we were all tired and giddy from the process, an intense camaraderie emerged. Both Matt and I lived up to the promises we made and the client was very pleased.

I’ve since reflected on the claims I made in our initial meetings (all of which I believe), and projected them onto the backdrop of my experiences at appendTo. I’ve worked with a lot of clients, on a lot of projects, with a lot of different technologies. I’ve produced code, written articles, coached a hackathon, given presentations, migrated a mountain of WordPress data (a task I would not wish on my enemies), created and contributed to open source projects, and so on. For each client engagement I straddled the line of being uniquely me, and being that second pair of eyes; of maintaining my own personal boundaries and standards, while appending to an existing team or management structure with their own goals and values. I’ve seen my co-workers do the same, time and again, in development, design, and management capacities.

There is a time for modesty, but this is not it.

appendTo harbors amazing people with amazing talents. Moreover, it treats its employees like entrepreneurs, free to grow their ideas and visions and passions while serving clients. It’s a petri dish for excellence. And this characteristic is intentional.

When I was first hired, I was told that appendTo was a place for recovering developers who had been abused by the corporate world. And though the journey is not always smooth (no good journey is!), the work I do here and the relationships I make are, and will continue to be, some of the most significant in my life. And for that I am both grateful and humbled.


gogrep: Exploring go

I’ve been learning Google’s go language and I put together a fun, trivial implementation of grep (gogrep!) to explore some of the language packages. It’s not complicated; the command is invoked with a regular expression pattern and a file path, and iterates over the file, line by line, attempting to match the pattern. Lines which match are then sent to STDOUT.

Go is an interesting language, and I like a lot of its features.

Having a unified workspace for both writing code and building binaries is quite nice, though I am puzzled at how specific versions of dependencies are specified for projects, as the organization of the workspace doesn’t seem to allow for this.

Method implementation for go objects behaves in a similar manner to extension methods in C#, in that methods are not defined on a specific object, but rather as standalone functions that receive, as their target of invocation, an instance of a particular type of object. These “methods” may then be invoked on any object of that type, much as extension methods in C# may be invoked on objects to which they are not really attached, by a trick of the compiler.

Go is type-safe and uses compile time, static type checking. I rarely find myself declaring types of variables, however, because go also uses type inference to make assumptions about the types in my code. The language also supports a special kind of type-safe duck typing in which objects that conform to declared interfaces implement them automatically. Because of this you can define interfaces for external libraries and the compiler will enforce your interfaces.

Go types don’t use type system inheritance; they use embedding instead. Object embedding reminds me of prototypal inheritance in JavaScript, where an invoked method that does not exist on an instance, but does exist on the instance’s prototype, will be invoked. A key difference between the two, however, is that in JS the target of invocation (the value of “this”) will be the object at the top of the prototypal chain, whereas in go, the target of invocation is an instance of the embedded object not the object embedding it! This is not as unusual as it sounds; it is a way to extend behavior through composition rather than inheritance. (Embedding objects can “override” the methods of their embedded objects, however, providing their own implementations.) Not only does embedding grant objects the behavior of other objects, it also means that objects satisfy the interfaces of their embedded objects as well. Epic.

I’ve read a little about the go concurrency model (Goroutines and channels), and I’m eager to jump in and play around with it but haven’t yet.

Overall I’m very impressed with go as a language. Many articles I’ve read almost exclusively relegate it to system-level development, though I hope it creates a much wider footprint.

Use node to change your bash prompt

I use the bash shell with git completion on my Mac. It’s awesome except it makes my bash prompt (PS1) kind of long and ungainly:

I wanted to optimize space in my terminal, so I searched for alternative ways to display the bash prompt and found an elegant solution on that reduces each directory in PWD to its first letter by evaluating the output of the `pwd` command and piping it through sed (streaming editor).

It works really well, but I wanted the last portion of the path displayed as the full directory name. I’m not familiar with sed syntax, and found myself thinking: I know how I would do this in node.js. So I copied the example, opened `.bash_profile`, and hacked up some code.

Turns out that when you invoke node with the `-e` parameter it will evaluate the string that follows. That gave me the exact prompt that I wanted:

Is it elegant? Not really. Is sed syntax more terse? Absolutely. But you know what, I do what I want and I had fun doing it. 😀

And yeah, I know, zsh.

All good things

Hello STL ALT .NET friends,

I have decided, after four years of running the STL ALT .NET meetup group, to step down as group leader. It has been a great four years. I’ve learned much and I’ve met many talented developers and speakers, but it is time for me to move on to other things.

What does this mean for the future of the group?

Our last scheduled presentation will be next month, on June 25th. I will be facilitating this meeting as usual, but will cancel all successive meetings unless one or more people want to adopt the group and step in as organizers to keep things running. If this interests you shoot me an email or leave a comment on this post — I’d be happy to meet with you and discuss what this entails.

I want to thank everyone for your support and participation in this group. It has been a fun ride, and my hope is that my primary goal for this group has been met: to help .NET developers grow beyond their comfort zones and broaden their horizons, adoption solutions within and outside of the .NET ecosystem for the technical problems they face every day.


“The future belongs to those who show up to build it. Shut up and show us the code.” — Eric Raymond

How to be a sane programmer

Business Insider published an article today called The Stress of Being a Computer Programmer is Literally Driving Many of them Crazy. It covers the typical culprits: Imposter Syndrome, long work hours, burnout, etc., and points out that while job stress has been traditionally laid at the feet of bad management, it is increasingly coming from within the programmer community itself, as a kind of culturally imposed litmus test for determining the dedication level of any particular programmer. In other words: if you aren’t slinging code in your spare time, you just aren’t going to cut it. Coupling this pressure with the speed at which new technologies, libraries, languages, platforms, frameworks, SDKs and text editors are released is like dousing a bonfire with jet fuel.

But here’s the rub. Programming, like writing, painting, and music, is chiefly a creative endeavor not a technical one. Practice with any technology or language is useful as a means of learning tools and techniques, but it will not make you a substantially better programmer. It will just make you more efficient with your tools. What makes you a better programmer is learning how to think about problems, since you are ultimately encoding your own thought process into a series of instructions the computer will follow in an attempt to solve problems. And learning to think properly–about abstractions, about composition, about information, about thinking itself–can come from many sources other than programming. Paul Graham observed this in his amazing essay Hackers and Painters:

I’ve found that the best sources of ideas are not the other fields that have the word “computer” in their names, but the other fields inhabited by makers. Painting has been a much richer source of ideas than the theory of computation.

Branching out into other fields, having hobbies other than programming can be a tremendous benefit to your day job. You don’t need to burn a bazillion hours writing code. Burn that time writing, or reading, or arguing with someone over coffee (or your favorite scotch!). Burn that time running, or lifting, or both. Physical activity pumps oxygen to the brain, nurturing that wonderful organ that is you. I started running 3 years ago. Actually getting fresh air and sunlight makes me a healthier person, and also gives me time to bounce around ideas in my head while I’m passing the miles to dropped beats and house vocals.

The point is that investing in your own mind for its own sake will make you a better programmer. You can always learn new syntax, or tools, or whatever, but if all you do is program, you’re actually working against yourself. Sometimes you have to put in the hours, when the barn is burning, but this should be the exception not the rule. If the barn is always burning, you need to find another barn. Sometimes you need to go heads down, for weeks or even months, to make your personal passion a reality. Then take a break. Constant, unvaried exertion will only lead to diminishing returns, the exact opposite of making you a better programmer. Last November I participated in NaNoWriMo (National Novel Writers Month), an informal contest where participants write a 50,000 word book in 30 days. I woke up early, spent a few hours writing, worked my 8+ hour day job, then spent my evenings writing as well. Every day. For 30 days. I started getting sick at the end of the month from that exertion, but it was necessary for me to accomplish an item on my bucket list: to write a novel. And I haven’t written a thing for several months. I needed a break, a change of pace, to make me better. Developing software is no different.

The BI article also makes the fascinating observation that “Women programmers frequently confess to suffering from imposter syndrome… But a lot of male programmers increasingly say that that they feel it, too.” The gender role fluctuation that has characterized the 20th and 21st centuries is  finally catching up to men. Women are seeing, first hand, the “disposable male” mindset enshrined and foisted on men, especially in the (traditionally male-oriented) workplace, a role which I believe arose from the necessity of survival but which is obsolete in a more affluent and flexible society. And men are seeing the reaction of women to the dehumanizing aspects of the male gender roles and are joining to express their dissatisfaction with the status quo. As more women enter technology fields, they bring an outsider’s perspective to which men need to pay heed, and women need to understand the system they find so unappealing is what men have had to live with and accept for a very long time. But together we don’t have to any longer, and that is powerful stuff.

Don’t burn yourself out to be a better programmer. Do what you love, and love many things. You will be better for it.

You won’t find bugs you aren’t testing for

I bought a game recently called X Rebirth, a long-awaited sequel to a series of “X” games that have been released by Egosoft over the last decade. Fans of the “X” series have really been psyched about what the screenshots and videos promised from X Rebirth. A lot of people pre-ordered the game. I bought the collector’s edition because it came with the game soundtrack as well as a few other goodies.

Unfortunately the game launch in mid-November was a complete disaster. The game is so riddled with bugs that it has garnered a 34/100 rating on metacritic (that’s bad), and reviewers have not been kind. The devs have been working hard, releasing patches almost weekly. For the most recent update, this paragraph in the release notes really caught my eye (emphasis mine):

It turned out that the issues many of you are seeing with trade ships not working correctly is not one bug but a whole series of connected problems… I do not want to give silly excuses here. Of course you deserve a bug free game, but you may ask why these trade problems were not uncovered during testing: We had a group of testers dedicated to testing our economy over a long period of time. These guys used a special version of the game which allowed them to run the entire economy at a higher speed. It seems that most of these problems we now see did not happen with this time acceleration. Meanwhile these problems also do not happen early on in the game or if you (like most testers do) have to restart the game frequently.

Note that they made two fundamental testing errors that cost them big time:

  1. Their testers use a “special” version of the game, meaning a version that the end-user will not actually be playing. In their case it was necessary but still dangerous as it does not simulate the conditions under which a normal user will play.
  2. They did not take into account prolonged periods of play, where the state of the game can be compromised by small bugs compounding over time.

I wish I could say that I haven’t made these same mistakes in my own career, but that would be a lie.

I’ve learned the hard way, as the Egosoft devs have, that the best way to test software is to use it myself, as my customer will use it, under conditions that approximate, as close as possible, my customer’s environment and usage habits. It is especially easy as a web developer to “bounce the server”, or “clear browser cache”, or “fake a dependency” while running my application, but in production, when my app is serving my customers and their needs, they (likely) won’t be able to do these things. And even if they can they shouldn’t have to.

So even though Egosoft still owes me USD $60.00 worth of gaming, at least I have learned a good lesson: always wait for reviews before I buy, and deliver the software I actually did test to the customer.