charlie's blog

Saturday, July 15, 2017

traveling the west

Roughly twenty years ago, I took a long camping road trip with my Grandma (Mary), covering almost every state in the western US. We drove, camped, hiked, and explored for three weeks. We also watched birds and saw more than a few prairie dogs. When we got back we had traveled 7000 miles, visited 14 states, and seen more than I've seen in any trip before or since.

A few weeks ago Donelle and I took a road trip to Nebraska and the Dakotas, and we saw some of the same places Grandma and I visited (including the Badlands of South Dakota and the mammoth dig in Hot Springs). Seeing those places again brought back so many memories it was almost overwhelming. It made me realize how lucky I am to have had such an amazing grandmother, to have learned so much from her, and to have spent that time with her.

It turns out I remember a lot more of the trip than you might expect after twenty years, so I decided to write those memories down for posterity. I'm including some of the photos we took as well, scanned from a very old photo album.

----------

We started from San Antonio and took US 183 north through Oklahoma, Kansas, Nebraska, and into South Dakota. We didn't stop much along the way and I remember being really surprised that 183 went so far. Looking at a map now I see that US 281 (running parallel to the east) actually goes all the way to Canada.

Unidentified rock formation from early in the trip

I don't remember much about this stretch other than one night of camping. We stopped at some kind of reservoir in Kansas or Nebraska and pitched the tent, and it was so blustery that we finally moved the car directly against the upwind side of the tent to block the wind. I also tied a rope from the roof of the car to the top of the tent. In retrospect I think this was all probably for my benefit; Grandma was an experienced camper and had probably seen much worse.

Prairie dog (I think) from South Dakota

In South Dakota we visited Badlands National Park and camped overnight. The next morning we hiked the Saddle Pass Trail (a steep uphill climb) and part of the Castle trail. I remember it as pale, jagged, and moon-like. For some reason I was fascinated by a car we saw in the parking lot at the trailhead, and took a picture like you might see in an advertisement.

Unidentified car at the Saddle Pass trail head

Heading northwest from the Badlands we visited the mammoth dig in Hot Springs, drove past Mt. Rushmore, and took a tour of Jewel Cave. I don't remember the cave but I can still picture the visitor center and parking lot in my head; it was cool and surrounded by tall evergreens, like Oregon or Washington.

Unearthing mammoth bones in Hot Springs SD

The last stop in that vicinity was Devil's Tower in northeast Wyoming. We camped there, and I took lots of pictures. Pictures back then were on film (we took seven rolls of photos), so we didn't see any of them until we got back, but I was thrilled to get one great shot of the tower. For a long time after that I had the idea that I might sell it to be put on a postcard, but I never did.

Devil's Tower, as never seen on a postcard

We drove straight west from there towards Yellowstone National Park. I don't remember much of the drive but I remember it being beautiful, and I remember seeing yellow-winged blackbirds by the road. That was really exciting and felt like one of my first real birding finds.

Of Yellowstone I remember the entrance station (evergreens, winding road, and a view of the park), driving around the edge of the massive lake (there was a white wood fence in one part), and seeing an osprey with a fish. I was so thrilled to see the osprey; it was the first big raptor I had ever seen and identified. I didn't see one again for over a decade, but since Donelle and I have started birding I feel like we see them everywhere. They are still huge and beautiful.

One of the many hot springs in Yellowstone

Leaving Yellowstone to the west we drove through the corner of Montana - we got out of the car briefly so we could officially give ourselves credit for visiting the state. Then it was on to Idaho and Craters of the Moon National Monument. We camped there and explored some of the lava caves, which were fascinating and a major draw for me. I don't think they were particularly exciting for Grandma but she humored me. We also went for a reasonably long hike; to balance out our age difference and substantial height/stride difference I carried a backpack and filled it with books and canned goods.

Further west we stopped briefly in the Snake River canyon to look for raptors (I don't think we saw any), and then headed north to camp in Hell's Canyon. The road to the campsite was a steep dirt mountain road, and part-way up was still covered in snow, so we had to give up and turn around. That was one of only two nights we didn't camp; it was too late in the day to find another campground.

From there we drove north and west across Washington to Seattle. We stayed with some extended family (Aunt Frances maybe?) in a beautiful house east of town. I remember the area as undeveloped and heavily wooded. My aunt worked at Microsoft at that time and took us to the campus the next day, which was really exciting to me. We got an oil change in town (we were already 3,000 miles in to the trip) and to round out the visit we got a speeding ticket on IH-5. It may have been Grandma's first ticket. She was *pissed* at the officer and only got angrier when she found out he had followed us past three speed limit signs before pulling her over. She was a very conscientious and law-abiding person, so I think it rankled her to get in trouble.

That night we camped at Mt. Rainier, although it was mostly still snowed in, so there wasn't much hiking or sightseeing to do. My only real memory from this stop is a disappointing one. After we set up camp I walked back to the camp store to call my girlfriend from a payphone, and apparently I didn't explain my plan to Grandma, so she had no idea where I was. When I got back (probably 30 minutes later) she was really worried and angry. I still feel bad about that.

I forgot until I was looking at the photos, but after we left Mt Rainier we drove to Mt. St. Helens, which still showed (and today shows) the scars of the most recent eruption. There are thousands of bare trees and Spirit Lake is still clogged with logs.

Mt. St. Helens from the road to the viewpoint

Heading south from Washington we stopped at Crater Lake. We never actually saw the lake, because the top of the mountain was covered in clouds. I remember driving up into the cloud from underneath as we made our way to the campground. We only had one evening and morning there, and the clouds never lifted, so we moved on without seeing much. Years later my mom and I took a trip there - it was beautiful and worth the wait.

South again and into northern California - the next stop was Lava Beds National Monument. The lava tubes at this park were particularly well developed, and I really wanted to explore one, so Grandma agreed to wait for me. I don't remember if she wasn't interested or if the trail was too challenging or what. I remember being exceptionally geeky and deciding to do a battery-replacement drill with my flashlight in an unlit section of the cave. This was probably not a good idea.

From there we drove east across Nevada, and I don't think we stopped for much. My only real memory of that section was the thrilling sight of a huge raptor perched on a sign by the road. We slowed down to get a better look but it flew away before we could see it very well. At the time we decided it was a golden eagle, and it was another first for me.

In southern Utah we visited Bryce Canyon National Park, possibly Arches National Park (I don't remember), and drove through Zion National Park. Of this I only remember the beautiful sculpted sandstone features from a hike in Bryce Canyon.

Bryce Canyon, or maybe the Grand Canyon

We left Utah to the south and in Arizona we found Grand Canyon National Park, Meteor Crater, and Petrified Forest National Park. I don't remember any of the Grand Canyon, but Meteor Crater was massive and sobering. From the Petrified Forest I remember two things: firstly, I saw a raven close up in the parking lot, and it was huge. That was another first-sighting for me (what Grandma called a "lifer"). Secondly, I remember talking with another visitor about his car and realizing that you can talk with just about anybody if you want to, and people are pretty friendly in general. As an older and more aware person I now realize that my experience was heavily influenced by being white, male, straight, and middle class. Even so, the experience had a real effect on me, and after that trip I have always felt much more at ease interacting with strangers.

A friendly lizard I found in the Petrified Forest

The same lizard, showing off

One of only two pictures of me in the album

The only picture of Grandma from the album

I don't think we stopped for much in New Mexico, but if I recall correctly we did visit White Sands National Monument. It was and remains a beautiful place.

From there we made our way back to San Antonio, and to our regular lives. For me it was summer and a part-time job, and for Grandma it was church, charity work, quilts, and probably twenty other things. I will always be grateful for her time, her teachings, and her love. She passed away in the spring of 2015.

Grandma around 2014
Photo credit Mareena McKinley Wright (I think)

Saturday, July 8, 2017

if software development was like bridge-building

I was thinking recently about metaphors for software development. There are lots of metaphors, my favorite being the garden metaphor, but I've also heard software development compared to bridge-building. To me the comparison is wildly inaccurate, and for fun I decided to develop the analogy farther.

Building a typical enterprise software tool as a replacement for the Golden Gate Bridge:

  • Before building starts, the designers debate for weeks over whether the bridge should be made of steel, plastic, or air gel. The virtues of air gel are touted with great smugness and the steel advocates are shown to be woefully behind the times. Nobody takes the plastic advocates seriously.
  • A month into construction, the width of the Golden Gate channel doubles, and the rock underneath changes from granite to crushed gravel. Construction is delayed for a month while the bridge is redesigned. Air gel is found to be inadequate and the builders switch back to steel.
  • Two months into construction, a freak electrical storm causes the bridge to entirely disappear. Construction resumes again after much wailing, finger-pointing, and an off-site backup bridge is created in Oakland.
  • A week later another freak electrical storm causes the bridge to disappear again, but it's restored from the Oakland backup without mishap.
  • At 75% completion it's discovered that the road bed will collapse whenever a Toyota drives on the bridge. The builders explain that Toyotas were never meant to cross bridges in the first place. Toyota drivers are directed to the Sausalito ferry.
  • On the first day of active service, a last-minute Beatles reunion concert is scheduled in Napa Valley, causing the entire population of San Francisco to mob the bridge all at once. The bridge disappears and reappears four hours later. Everyone misses the concert.
  • A year after the bridge is completed, the rock under the channel is upgraded from crushed gravel to decomposed granite. The bridge sits at a funny angle for six months until the foundations are rebuilt.
See what I mean?

Thursday, May 22, 2014

identity is hard

Equivalence

Take a look at the following pairs and decide whether the two things are equivalent (the same):

"cat" vs. "cat"
"dog" vs. "Dog"
4 vs. 2+2
"color" vs. "colour"
"wanna" vs. "want to"
1+2 vs. 2+1

Your specific answers probably differ from mine, but I bet you said "the same" for some, "different" for some, and maybe "it depends" for some.

For instance, I'm sure we agree that "cat" and "cat" are the same. We would probably say that "dog" and "Dog" are the same thing too, at least most of the time. What about "color" and "colour"? I'm betting that most English speakers would say they're essentially the same thing, just two ways of spelling the same word. An etymologist might disagree and say that they differ in some interesting technical sense. Someone with strong American or British pride might give you an earful.

Likewise, the difference between 4 and 2+2 is arguable. In some senses they are the same thing, since they can both be seen to represent the quantity 4. However, if you wanted to tell someone what time your kids come home from school, you probably wouldn't say they come home at "2 plus 2 o'clock", so they obviously aren't totally interchangeable.

The crux of the matter is that equivalence is context dependent. Whether 4 is the same as 2+2 depends on whether you're in a mathematical context or a social context. The equivalence of "dog" and "Dog" might depend on whether you're typing the words into a search engine, where you'll probably get the same results for both, or using them to start a sentence, where one is correct and the other is wrong.

So why do I care about equivalence being fuzzy? Mainly because computers aren't very good at "fuzzy".

Fuzzy problems

One of the most common things computers do is compare things. For instance, a tax program might compare your income against some threshold value to determine whether you owe more or less money. Or it might check to see if your age is greater than 65, to help determine eligibility for retirement benefits. Comparisons that involve numbers are generally pretty easy, so computers do reasonably well at this. But what happens when we try to compare something like a name?

Imagine you have a customer account with www.bunnyslippers.com. When you registered the account last year, you provided your name (Fred Flanders) to create a customer account. Each time you log in, the server looks through the list of known customers and decides whether any of those names matches "Fred Flanders". If it finds one, it can verify the associated password and allow you to proceed.

Now what happens if you try to log in and accidentally type "FreD Flanders" instead of "Fred Flanders"? If it was a human handling this sort of request, they would probably not even notice that you accidentally capitalized the D in "FreD". On the other hand, a computer might or might not see the two as the same, depending on how careful the programmer was being. By default the computer actually sees the letters as numbers; 'd' is 100 and 'D' is 68. So when you ask a computer whether "Fred" and "FreD" are the same, it sees two different sets of numbers, and it says they aren't the same.

So why not just tell the computer that "d" and "D" are the same? Okay, done. Hopefully you don't mind if Microsoft Word now occasionally replaces all the d's in your term paper with D's. They're the same now, so what difference does it make?

Hopefully the problem is becoming clearer now. Sometimes we want our computers to see "d" and "D" as the same thing, and sometimes we don't. The difference is in the context.

Computers aren't fuzzy

The fundamentals of computing are deeply rooted in mathematics. The earliest computers were designed to calculate solutions to complex ballistics problems, and for the most part they remain glorified calculators. The only things they can really do are math and various operations on individual bits. In this sort of basic math, there's not a lot of room for context. The number four is always the same, so there's not much fuzziness to deal with.

As befits their mathematical underpinnings, most programming languages support operations like addition, subtraction, and the like. They also support comparisons, including tests for equality (many languages use "==" for this instead of "=", since the latter is often employed for another purpose). These operations make good sense for working with numbers, but it gets trickier when they get applied to other sorts of data.

For dealing with textual data, computers use something called a "string", which is a sequence of characters (single letters). "Fred" can be treated as a string, composed of the characters "F", "r", "e", and "d". Most languages allow the equality test (==) to be used on strings, and here's where things get tricky: by default this test looks for a very strict numeric equivalence, the kind that says "d" and "D" are not the same. The human programmer may not have intended that, though; the programmer is quite often aiming for some fuzzier form of equivalence.

To deal with this, computer languages often provide various specialized ways to compare strings, which can be used in different contexts. One way is the super-strict "no differences whatsoever", but you can also specify a comparison that ignores case (so that "d" and "D" become the same), or even a comparison that first applies all kinds of interesting linguistic normalizations to smooth out variations. The strict comparison can be used in strict contexts (e.g. verifying passwords), and the looser comparisons can be used for things like finding names in customer databases.

Identity is fuzzy too

So far, all the examples I've used to talk about equivalence have been simple, interchangeable things, like apples. Two totally identical red apples are more or less the same, and you'd probably be equally happy to have one vs. the other. There are lots of things like this in life, but not everything fits that description. If I were to replace your favorite old leather jacket, which smells like your dad and has years of old memories attached to it, with an old leather jacket I found at Goodwill, you likely wouldn't be happy at all. As another example, if you repainted your red Ford Mustang to be chartreuse, you'd still expect everyone to know it was your car, right?

What I'm getting at is the concept of identity. Just like equivalence, identity is something we understand naturally and deal with all the time. Everyone understands that the lime green car you're driving today is the very car you were driving yesterday: it's your car, the particular car that you own. Likewise, your old leather jacket has specific unique value to you; it has a particular identity which distinguishes it from other similar leather jackets. Identity is closely related to continuity over time; the significance of your jacket's identity has a lot to do with it being the very jacket that you had on all those previous occasions in you life.

The word "same" can refer to both equivalence and identity, even when the two concepts are in opposition (that pesky fuzziness again). For instance, if we're talking about identity, I might say that the green car I see today is the same car that you were driving yesterday (i.e. both cars were you particular Mustang). However, visually the cars are not equivalent, so I could just as correctly say that the car is not the same today as it was yesterday.

Computers and identity

Programmers often refer to the "identity" concept above as "reference equality" (as distinguished from "value equality", which is the equivalence concept). For reference equality we usually pick some stable identifier, such as a VIN or an email address, and use that for identity. Reference equality is often less fuzzy than value equality, but there's still room for error; for example, if you use an email address as the identifier, do "fred@domain.com" and "Fred@domain.com" identify the same account? Probably they should.

Sometimes computers and programmers don't pick the right type of equality to match our expectations, or they don't implement it the way you'd expect. A good example is that term paper you wrote last week on your computer: "The Strange World of Ocelots". You probably view that paper as having a particular identity, after slaving over it for hours. If I asked you where the paper is right now, you could presumably tell me what computer and folder it sits in. You might even have created a shortcut to it on your desktop.

So what happens when you rename the file to "Ocelots - Strange but Wonderful"? I'll tell you what happens: the shortcut on your desktop may not work anymore. That's because most computers consider the identity of a file to be solely a matter of the file's name (as well as the names of the folders it lives in), and you just changed the name. Of course, this behavior seems totally wrong to the average person, because in our minds, the paper on ocelots is still perfectly well identifiable as itself.

By the way, this example does actually work in newer versions if Windows, thanks to the Distributed Link Tracking service. However, the need for a specialized service just to make this work just emphasizes the fact that this is a tricky problem.

Where am I going with all this?

The point of all this is that equivalence, identity, and sameness are hard; hard to describe, and hard to correctly implement. I don't have any magic solutions to offer, but I believe that thinking more about this topic can help programmers write better software with less effort and pain.

Some specific ideas for programmers to keep in mind (including my future self):

  • When designing new systems, think about what types of equivalence/identity might be involved, and what behavior the user will expect.
  • Be careful with standard/easy ways of comparing things (e.g. operator== and Object.Equals). Does the easy way actually have the semantics you want?
  • Better yet, be explicit about how two things will be compared. For instance, use function overloads which explicitly specify string comparison modes.
  • Make sure you understand the language and use it as intended. For example, C# provides a very simple reference equality for reference types. It also uses value equality for built-in value types, which means you should usually do the same with your own value types (so you don't surprise people).
  • Find or build automated tools to help verify your code's correctness. For instance, you can use FxCop to verify that you're explicitly specifying string comparison modes whenever possible.

Labels:

Sunday, February 9, 2014

how do I write an Alt+Tab replacement program?

Over the years I've done several Alt+Tab replacement projects, and recently I started a new one. Unfortunately I found that the techniques which worked under Windows XP do not work under Windows 7 (and presumably not under Windows 8 either). I did eventually get it to work, and created this page to document what was required.

Here are the essential ingredients for an Alt+Tab replacement (a "switcher") under Windows 7:

#1: Capture Alt+Tab

Under Windows XP this was easy, you would just use RegisterHotKey and override the default handling of Alt+Tab. Unfortunately this does not work under Windows 7*. Instead, the best option I found was to set a Windows hook using SetWindowsHookEx, specifically a low-level keyboard hook (WH_KEYBOARD_LL). From here you can detect the Alt+Tab key combination and invoke whatever UI you want.

* Actually, it might work once you enable uiAccess (see below). I never tried it again after switching to Windows hooks.

#2: Enumerate windows

A switcher needs to know which applications it's switching between. There are a few ways to do this, and it's not particularly complicated. Two options are EnumWindows and the UI Accessibility framework (see System.Windows.Automation). The latter has more functionality but can be less performant if you're not careful.

As a side note, you can also use the UI Accessibility framework to determine the order of buttons in the Windows task bar, which might be useful depending on what behavior you want in your switcher. I did this by finding the Explorer process and searching its windows for one with a ClassNameProperty of "MSTaskListWClass". The child windows of this window seem to be the taskbar buttons. There might be cleaner ways to do this, though, and no doubt this is subject to breakage in future releases of Windows.

#3: Actually switch apps

Once the user picks an app to switch to, your switcher needs to actually perform the switch. This is the part that gives people the most trouble, and the one I fought with the longest. I tried SetForegroundWindow (unreliable), SwitchToThisWindow (also unreliable), AttachThreadInput (unreliable and probably a bad idea), and no doubt some other things I already forgot about. These do not work due to deliberate (and good) security limitations in Windows.

What does work is to set uiAccess to true in your application manifest (see this MSDN overview). You do not need to change requestedExecutionLevel (the app does not need to run with elevation), you just need uiAccess="true". In order for uiAccess to work, you will need to sign your executable (self-signing is a good option for initial development) and install it in Program Files. If you fail to do either of those things, your app will not be able to launch.

Once you enable uiAccess, your switcher will be ready to go. I ended up settling on SwitchToThisWindow for the switching, but I think SetForegroundWindow would probably work as well. For debugging, usually I just temporarily change uiAccess to false and live with the fact that some switches will fail due to security limitations.

Conclusion

That's it! Hopefully this will be useful to other developers; figuring this out (particularly item 3) was a long and frustrating process, and hopefully this can save people some pain.

Sunday, August 18, 2013

a note about the SDLC

I've been reading a lot of resumes recently, as we slowly grow the software group where I work, and I've noticed a lot of folks referencing the Software Development Life Cycle (SDLC). A large percentage of these resumes indicate that the applicant is well versed in the "entire SDLC", and they often go on to list the SDLC in detail as something like the following:
Requirements-gathering, Design, Development, Testing, Deployment
My concern here is that almost nobody includes "maintenance" or "evolution" in their list.

I'll say up front that I am not an adherent to any specific formal development process, be it Agile, Waterfall, or any of the other approaches out there. I certainly don't claim to be an expert on the SDLC. I can say this with complete confidence, though: no matter what process you follow, software always requires maintenance!

When I read these resumes I get the impression that the person thinks software development is like making a sculpture: you decide what it should look like, do the sculpting, make sure it looks like you intended it to, deliver it to the customer, and you're done! This is emphatically not how software development works.

A much better way to think about software is like a garden. Once you plant it, your job has only begun. You get to spend the next N years tending the garden: pulling weeds (fixing bugs), occasionally adding new plants (new features), and periodically moving things around (refactoring). Whether or not you do this work, someone has to do it, or the garden/software turns into a jungle and eventually dies.

I won't say that I immediately discard any resume that lists the SDLC and leaves out maintenance, and I realize some folks just haven't encountered this part of the process yet, but seeing this on a resume is a huge red flag for me.