Author: Jud

Technologist interested in building both systems and organizations that are secure, scaleable, cost-effective, and most of all, good for humanity.
The Herpes Of Version Control

The Herpes Of Version Control

I love git. Truly. Once I got over the fear of learning something new and dove in, everything else paled in comparison. Maybe it’s just because I was a math major and directed acyclic graphs are cool. Maybe it’s because it everything about it makes sense (kinda like Python in that respect). Maybe because it’s the foundation behind open source software development sites like Github.

But this post is not about how much I love git, or why you should use it over the alternatives. It’s about one particular feature that drives me crazy at times, and that’s tags. Yes those littles things you use to mark important places along the development tree. They’re quick and easy to make (especially by CI tools that vomit them out daily), and really useful to have around. But the darn things are nearly impossible to get rid of.

It’s not that the implementation is confusing or doesn’t have logical justification (it does). But the distributed nature of git means they spread like wildfire, and are incredibly difficult to delete across all cloned repositories. You think you’ve gotten old ones deleted, and then some poor developer who hasn’t cleaned up his repo (or even worse, the local copy of a repo on your CI server) pushes and they all come back. Argh.

For a guy who is as anal-retentive as they come about keeping his repos tidy, tags are just the worst.

Be A Polyglot!

Be A Polyglot!

A couple of days ago a colleague of mine was reading out loud some code he was debugging, and I could have sworn he was direct quoting from Execution In The Kingdom Of Nouns.

That story is one of my favorite warnings against the notion that software development is a “one size fits all” proposition. There’s great value in being fluent in a number of tools and approaches, and using the right tool for the job. Can this be taken to an unhealthy extreme? Of course, but in general the benefits outweigh the drawbacks.

Lions And Tigers And Permutations, Oh My!

Lions And Tigers And Permutations, Oh My!

This blog is turning into a bit of a “debugging adventure of the day”, which wasn’t the original intent, but whatever. I’ll get around to meatier posts someday.

This morning’s adventure was debugging a pretty serious issue with a web application where selections would not save. Initially it only manifest itself on Windows machines, so we thought Microsoft was to blame. Oddly, though, Chrome failed to work but Edge was fine. Weird.

Wanting to check a few other variables, we grabbed another co-worker’s Windows laptop, and it worked fine in Chrome. WTF!?! Nearly identical hardware, same OS, same browser, and same browser version, but one machine worked, and the other didn’t. Cleared caches, rebooted, etc. Same results.

But did you catch the word “nearly” there? Turns out there was a difference between the two laptops. One had a touchscreen, and the other didn’t. Fast-forward through an hour of slogging through a bunch of hacked together JavaScript code to support drag-and-drop on a variety of devices, and sure enough, the “non-mobile yet touchscreen enabled” case had its own special snowflake handler that wasn’t working correctly in Chrome.

Why you ask? Well, in some browsers, touch events are delayed by 300ms (this is so things like double-tap and dragging can be detected properly). This causes the mouse click event to go first, and when clicking on a button that submits the form, the form gets processed before the touch event can fire that needs to run and configure the inputs to the form submission. If you touch the button instead of clicking with the trackpad (a condition that only makes sense on a touch-enabled laptop vs a tablet), it works okay.

That means this situation only manifest itself on a touchscreen-enabled non-mobile device, in Chrome, when the user clicks the submit button with the trackpad vs touching the button. Can’t hardly blame QA for not finding that one.

Dirty Work

Dirty Work

Developers like to write code, that’s what they do. But being a software professional means working on a number of other tasks, some of which are decidedly un-fun. The wise developer recognizes the importance of these tasks and approaches them with no less effort than their more enjoyable work. Grooming a task list. Writing documentation. Cleaning up repositories. Slogging through a naming refactor to improve consistency. She knows that these will all pay off in the long run.

Yesterday I spent nearly 10 hours working in JIRA, getting my head around nearly 150 tasks that need to get done in the next 3 weeks. Circumstances had forced me to be pretty heads-down in dev-world the past couple months, and my planning responsibilities had fallen by the wayside. I owe the team more than haphazard and vague requirements, and this is the first step to doing better. Here’s to a full July!

Tyranny Of The Urgent

Tyranny Of The Urgent

A wide variety of tasks face the developer each day. Some can be accomplished quickly, like responding to emails, and some need much time, such as implementing a new product feature. Some require little thought, like cranking out a refactoring across several components, and some take a lot of mental energy. Some have immediate near-term deadlines, and others are not due for some time.

It’s particularly easy to focus only on the tasks that must be done soon (so-called “urgent” work) but the responsible developer must fight this tendency. Urgent and important are not synonyms.

Ain’t No User Here

Ain’t No User Here

Here’s a new one. I was debugging a problem with a web server that hadn’t been used in a while that was allowing users to log in, but failing to perform a number of other functions (gotta love an API that happily returns a 200 OK even though it’s clearly not working because there’s no data in the response). No one could think of anything that had changed, but clearly something had.

After some spelunking through logs, I found some DB permissions errors. Obviously some DB calls were working, so that was odd, as I knew credentials were only specified in one place.

Another hour of research later, I discovered that MySQL views run as the user who created them, not the user who queries them. This actually makes sense for use cases where you want to give controlled read access to parts of the DB to a less-privileged user. Logically then, if that user is deleted, the view fails to run. And in this situation that’s exactly what happened.

There’s a number of lessons to be learned from this situation:

  1. A user probably should fail to delete if it owns other objects in the database. Otherwise unexpected side-effects occur.
  2. Accurate error messaging is essential to debugging. When trying to run the view, I got a simple “user does not have permission” error, which told me nothing about the underlying problem, which meant another hour or two of research. This goes for APIs especially. Please know when to use a 4XX vs. 5XX error especially, and even better learn the subtle differences between 502, 503, and 504, and when each should be used.
  3. Don’t try to diagnose problems on Friday afternoons before holiday weekends. You’re asking for trouble.
Do The Right Thing

Do The Right Thing

I love it when a programming language behaves in an unsurprising and helpful way. This is Python in a nutshell.

Consider the following situation I came across yesterday. I needed to pair off two lists. Naturally, Python has a built-in function for this:

x = [1, 2, 3]
y = ['a', 'b', 'c']
zip(x, y)
# [(1, 'a'), (2, 'b'), (3, 'c')]

But what happens if the lists are different lengths (as they were in my case)? Python does the logical thing, and stops with the shorter list:

x = [1, 2, 3]
y = ['a', 'b', 'c', 'd', 'e', 'f']
zip(x, y)
# [(1, 'a'), (2, 'b'), (3, 'c')]

This is exactly the behavior I needed, no special case handling required. Woot!

It’s All Geek To Me

It’s All Geek To Me

One of the hallmark characteristics of a nerd is the ability to enjoy a wide variety of things without worrying about how popular they might be. On that note, I listed to this song yesterday and unashamedly enjoyed every minute of it. Wish I’d been there.

Gimme That Foot Gun

Gimme That Foot Gun

The past couple of days I wrote about the dangers of providing too much functionality. In a fit of cognitive dissonance I now want to contradict myself and demand dangerous power when it suits my needs.

I’ve been working the past week to get a particularly gnarly application running in a set of docker containers. There are over a dozen services, plus a Rabbit queue and a database. Many of the services do not handle database connection failures in a robust way. During my testing I wanted a simple way to ensure they waited a bit before trying to connect, as the database container needs a minute or so to seed itself and get ready for connections.

Unfortunately,docker-compose does not have any form of manual startup delay feature. This is by design, as the Docker team (rightly) argues that having services intolerant to connection failure is a bad thing. However, it’s frustrating to not have the power to do the wrong thing in the short term.

Then again, it turns out it wasn’t too tough to augment my compose file with a depends_on clause that includes a health check, which is a more reliable solution anyways.