Thursday, April 11, 2013

The Situation (Day 32)

My wife and our two youngest children have been approved for WIC. We have a debit card. That was an interesting process. It's not food assistance per se, it's just _supplemental_ food assistance. It's a relatively small amount of assistance, with some extremely complicated and arbitrary limitations on what you can purchase. The idea is to get very young children and pregnant mothers extra nutrition. I think Grace and I will be recording a podcast about the process and what they cover because it is really revelatory, about the clashing priorities of the social safety net and corporate food vendors.

I'm talking to more recruiters. That's encouraging. There is actually a fair amount of software development work that I could probably get. The difficulty is that much of it is in the Detroit area. So we are considering how we might make that work, perhaps with an alternate living arrangement where I spend the work weeks in a small apartment nearer to the job, rather than drive 3 hours a day. But I'd have to earn enough to help pay for that. The salary numbers the recruiters have been mentioning are not stellar. In fact they're pretty average. I wonder if that's because, in part, that the companies have factored in what they have to pay the recruiter? And on the one hand, I can't be too precious and hold out for a salary that just isn't realistic at all. But I also don't want to take a job that will pay just enough to allow us to slowly crash our finances while being unable to pay for things like home repairs.

One recruiter asked me to fill out some interview questions via e-mail. One question in specific caught my eye. She wrote "What are you best at in your profession or most importantly WHAT DO YOU ENJOY DOING? Please be detailed."

Here's what I wrote back (well, I'll edit slightly).

OK -- you said detailed, right?

I like to solve problems through software design, and I like to learn. The quality of a job for me is directly related to how much I can learn while doing it. Over the course of my career I have taught myself many new programming languages as well as design tools such as object-oriented programming, hierarchical state machines, UML, etc. I also have an ongoing interest in digital audio, which is related to my hobby as a musician and producer. At Lectronix I was primarily responsible for the code that handled audio, from IIS inputs and sample-rate conversion and mixing, through to the high-level control interfaces for controls like bass, treble, balance, and fade. I also have an ongoing interest in designing good user interfaces.

A lot of software is unreliable and hard to maintain because there is no clarity to its design; the design has grown over time with contributions from different programmers of different skill levels and might contain problems like: un-handled input conditions; hard-coded timings that are not reliable; race conditions; support for vestigial features; poor functional or object decomposition.

Sometimes moving from an excess number of threads to an event-driven model can dramatically simplify code. Sometimes splitting code _into_ multiple threads, that then serialize inputs and outputs through shared event queues, can dramatically simplify code. Sometimes moving to an explicit state machine, flat or hierarchical, can dramatically simplify code. I recently worked on a design where there were a number of instances of a hierarchical state machine running in separate threads, consuming serialized inputs and producing serialized outputs via message queues.

I like designing software from scratch, but I also like handling legacy code -- studying, documenting, refactoring, and debugging it. I consider it to be time well-spent when I can _remove_ hundreds or thousands of lines of code from a program while also fixing bugs and improving readability.

I have also been pushing for the use of advanced languages: languages such as Dylan, which I've used for modeling object-oriented designs that use multiple inheritance, since it was simpler to model the design in Dylan, test it, and then port it to C++ than it is to write it from scratch in C++, and Haskell, which may not run on the target but can be useful for generation of code and validation of algorithms, and lightweight scripting languages such as Lua or Squirrel that can be embedded as interpreters, allowing the non-time-critical "business logic" of an embedded system to be written in a more expressive way, perhaps by domain specialists. While working with the Health Media Research Lab I did this sort of thing using Kawa (a Scheme implementation that executes on the JVM) and also used NewtonScript as a dialect of Lisp where the blurry distinction between data and code allowed me to create a script "engine" that could execute different "scripts" to administer surveys. NewtonScript is sadly dead and buried but the principle survives in the use of domain-specific languages like Ruby on Rails.

Years ago I read about the phenomenon of "Greenspunning." If you're not familiar with that idea, you can read about it here.

I've seen engineers essentially implementing interpreters in C++. This sounds like a good idea, except that these engineers typically have no experience in language design, and may even never have _used_ a language such as Scheme or Haskell. They start with something very simple. Sometimes it's based on byte-codes, or XML, or even objects (if they are new to C++ and want to play around with class hierarchies). But inevitably they find that they need to handle iteration, and numbers, and pretty soon they have something that is a horrible mess, built entirely in an impenetrable heap of C++ instead of just writing in a simple language. Sometimes, as far as the code design goes, it looks like BASIC circa 1977: spaghetti code.

There's no syntax. Lisp would have been easier to understand. And the company's critical business logic is implemented in this horrible, over-engineered, buggy mess. Sometimes the "not invented here" syndrome is a part of it (see http://c2.com/cgi/wiki?NotInventedHere). Sometimes it's a pet project. It's usually something that has to be thrown away completely when the key engineer leaves.

C first came into popularity around the mid-1980s. That's a long, long time ago in computer years. C is incredibly useful but our processors have increased in speed by many, many powers of ten. Some applications will continue to need strictly optimized C or assembly language for performance, but in many other cases this abundance of cycles and memory gives us great opportunities to use other languages for business logic and graphical user interfaces. I am an expert C (and C++) programmer but I would consider a work situation that allowed me to also work with languages such as Scala, Python, Lua, etc. For what it's worth, game designers have figured this out, and a lot of game engines are scriptable in the way I just described. No one could say they don't worry about optimization.

I realize this isn't the type of thing that a typical warm-body-in-a-cube embedded software engineers often get to do. They want someone to implement code in C on an RTOS and they honestly spend more time writing specs and making sure things are MISRA or AUTOSAR- or whatever- compliant. I'll do that sort of work if it is all I can get but if there was something that looked more like "software architect" designing _systems_ across multiple languages that would be far more interesting.

So -- where can I find a job like that? Oh, the truck's "check engine" light is now on. Ugh!

No comments: