Author: Jud

Technologist interested in building both systems and organizations that are secure, scaleable, cost-effective, and most of all, good for humanity.
A Helpful Transmogrifier

A Helpful Transmogrifier

Have a large CSV file and want a quick way to query it? Consider transforming it into a SQLite database. It’s easy! One command will do it:

$ sqlite3 "$sqlite_filename" ".import $csv_filename $table_name --csv"

Here’s a concrete example using airtravel.csv:

$ sqlite3 air.db ".import airtravel.csv air --csv"
$ sqlite3 air.db "SELECT * FROM air WHERE air.Month = 'JAN'"
JAN|  340|  360|  417

Neato! Admittedly the handling of headers and column names isn’t great, but that can be solved with a bit more script-fu (which I’ll leave as an exercise for the reader).

Sean Maguire Was Right

Sean Maguire Was Right

Don Norman came to mind today, a not uncommon occurrance. I’ve mentioned him before, but not loudly enough. If you care at all about building great solutions, technical or otherwise, reading The Design of Everyday Things is a must. Here’s my favorite passage:

The idea that a person is at fault when something goes wrong is deeply entrenched in society. That’s why we blame others and even ourselves. Unfortunately, the idea that a person is at fault is imbedded in the legal system. When major accidents occur, official courts of inquiry are set up to assess the blame. More and more often the blame is attributed to “human error.” The person involved can be fined, punished, or fired. Maybe training procedures are revised. The law rests comfortably. But in my experience, human error usually is a result of poor design: it should be called system error. Humans err continually; it is an intrinsic part of our nature. System design should take this into account. Pinning the blame on the person may be a comfortable way to proceed, but why was the system ever designed so that a single act by a single person could cause calamity? Worse, blaming the person without fixing the root, underlying cause does not fix the problem: the same error is likely to be repeated by someone else.

The notion of system error is quite profound, applicable to technology, organizations, governments, even entire civilizations. Leaders of all stripes do well to consider its explanatory power.

Just discovered that Don has a new book coming next month: Design For a Better World. Pre-ordered!

The Tie That Binds

The Tie That Binds

Read these two articles yesterday. On the surface they’re about different topics, but there’s a common thread: both call out an aspect of technical work that is often ignored, especially by the less-experienced.

The first tale, Our Company Fired the Best Developer and Project Manager, reminds us that “Getting your tasks done is half of the job. The other half is how you do it.” I’d go even further and say getting your tasks done is only a quarter of your job. The rest is how you do them, when you do them by, and most importantly, ensuring you understand why those are your tasks in the first place, and if perhaps you should be doing other tasks instead. Don’t climb the ladder only to find you leaned it against the wrong wall.

Coding Won’t Exist In 5 Years is yet another ChatGPT article, whose crux is the following: “Programming is the process of solving problems using a computer. Writing code is just one aspect of this process. It’s a necessary part, but it’s not the whole picture.” Yes, learn to write code well, but be aware you’re more valuable as an editor than as a drafter, and that’s only going to get more true as AI gets better.

That Last 20%

That Last 20%

I got an email this morning from a reader who asked if I had an email subscription feature on this blog. I didn’t then, but now I do! Want my writing to hit your inbox the moment I publish? Just add your email address into the widget at the top of the sidebar and hit subscribe. Easy!

You know what wasn’t easy? Trying to get that widget to match the rest of the site. At first it looked like this:

Gross. Luckily WordPress supports adding custom CSS. Unluckily, that means I had to fiddle with CSS, which is a special form of hell. I couldn’t get it perfect on all browsers, but it’s not bad now:

While I was at it, I made a few other visual tweaks to the site, primarily shrinking the masthead height, which has always bugged me. Here’s the final code snippet. Not the prettiest, especially with all those !important keywords (generally they’re a smell that your CSS is too complex), but it gets the job done.

.navbar {
    display: none;
}

.site-header {
    height: 300px;
    min-height: 300px;
}

.site-title::after {
    margin-top: 0.5em !important;
    margin: auto;
}

button.wp-block-button__link {
    height: 34px !important;
    margin-left: 0px !important;
    padding: 0px 5px !important;
    background: #fab526;
    font-weight: bold;
}

input#subscribe-field-1 {
    padding: 5px !important;
    border-bottom: 2px solid #ddd !important;
}

.search-field::placeholder {
    color: #B9B9B9;
}

If you happen to notice any weirdness on your device/browser of choice, do let me know, eh?

No Easy Answers

No Easy Answers

I’ve been managing technical people for a while now, but when it comes to asking good questions and listening well, I’m always learning. One thing I’ve discovered is that questions needn’t be complex to be effective. Here’s three I use regularly:

How do you feel about that?

Giving someone space to express their emotions is usually a good place to start when beginning a conversation. This is doubly true in the workplace, where there’s a misperception that feelings have no place. But we’re all human, and our effectiveness is predicated on aligning our emotions to the task at hand.

What could you do about that?

Once a person feels safe describing how they feel about a situation, it’s time to explore options for how to move forward. The word could here is critical, it’s a word about possibilities. Usually with just a little nudge, people will be able to come up with a variety of potential solutions on their own.

What do you want to do about that?

Too often people are asked to consider all sorts of factors when weighing options, but never their own desires. And especially not just surface desires, but what they truly want based on their own complex (and often competing and contradictory) web of values. It’s a powerful question; simple to ask, but hard to answer truthfully. Though once it is, I’ve found one often has all the data at hand to make a high quality decision.

Irreduceable Complexity

Irreduceable Complexity

“Make everything as simple as possible, but not simpler.” – Albert Einstein

In any technical discussion, beware when someone says something is simple. Things are rarely as simple as their marketing materials claim, and there is a vast gulf between a quickly-constructed proof of concept and a production-ready solution.

Even concepts that might seem straightforward at first glance have considerable potential for edge cases and other gotchas. Consider the following as canonical examples:

A corollary to the above: there is no such thing as a “5 minute task” in technology. When you hear such a claim, mentally multiply by 10.

Jud Flow

Jud Flow

Keeping a nice and tidy code repository makes me happy. Here’s the typical process I use to avoid messes:

  1. Create my-sweet-new-feature branch from main
  2. Make some awesome code edits, then commit them
  3. Make some slightly less awesome edits, commit them also
  4. Run some tests, nothing works; debug and commit the fix
  5. Decide my originally awesome code isn’t so awesome; rewrite the whole feature and commit
  6. Tests pass locally, yay! Push my-sweet-new-feature to Github and create a pull request
  7. Hrm, tests fail in pipeline; whoops, forgot a file; commit and repush
  8. Okay, tests pass now, so message team for review
  9. That’s a reasonable request, change made and committed
  10. Fine, we’ll use your naming convention; change made and committed
  11. Ugh, made a spelling error; committed
  12. Fixed moar typos
  13. Uggggggh, one last commit to fix spacing; pushed to Github
  14. Wha? Tests failing? :facepalm: forgot a file again
  15. Commit that file and push one last time for realz
  16. Tests pass, team reviews and approves, we’re good to go
  17. Pull an update of the main branch
  18. Come back to my-sweet-new-feature and rewrite all the commits on top of updated main; group edits into a clean subset of logical changes, one per commit, that makes it look like I wrote the code perfectly the first time, with nicely crafted commit messages that will mean something to some poor future developer that has to maintain my code ten years from now
  19. Run tests to ensure everything still passes; it does
  20. Force push to the pull request, obliterating all those ugly prior commits with these nice clean ones
  21. Try to merge the branch to main with fast-forward only option, forget that Github doesn’t support it (curse you Github! even flipping CodeCommit supports fast-forward only merging)
  22. Fast-forward merge my-sweet-new-feature to main locally so my final commit signatures are preserved
  23. Try to push main to Github, but it fails because the branch is protected
  24. Unprotect main temporarily, repush
  25. Dang it, someone merged new changes since step 17; repull main and rebase my branch
  26. Re-push my final changes and re-protect main

See how easy that is? No excuses moving forward, my friends!

All The Things

All The Things

I agree with this article that there’s a special joy that comes from building something to suit your own needs. But that doesn’t mean you shouldn’t share the results. You’ve got to store your artifacts somewhere, so might as well stick them in a public spot like Github. Perhaps someone else will find your work interesting and useful, not the least of whom might be an interviewer who needs examples of your code to do a proper evaluation.

Here’s a rundown of projects for which I am either the primary author or significant contributor, grouped roughly by subject matter. I capture them here for the value of having such an index, but also because some of it I believe has value. If any of you find such value, would you let me know?

Lambda Functions & Tools

Buy Me A Coffee Webhook – I wrote about this project two weeks ago, it’s a CDK-deployed Lambda function with an HTTPS endpoint that can receive webhook notifications from Buy Me A Coffee.

Temperature Collector – Another Lambda function, but this one deployed using terraform. It gathers temperature data from heterogeneous sources and publishes it to CloudWatch. I’ve also written about this one before; if nothing else it’s a reference example for how to use terraform modules.

Selenium Lambda Layer – It’s tricky to get all the right bits in place to get a headless browser working with Selenium in Lambda. Given how browser tech evolves, I doubt this still works, and if I have to do it again, my first choice would be CloudWatch Synthetics Canaries instead.

Lambda Layer Builder – When packaging dependencies, I prefer keeping them in a layer vs including them in the Lambda deployment package itself. It keeps the deployable package small, and ensures I can edit code directly in the console when I need quick turnaround. This script makes it a one-liner to construct and upload a layer that contains a set of either Python or Node.js dependencies.

Blockchain Constructs

Managed Blockchain Document Ledger – As part of a customer workshop I built this fully-functional example of using Amazon Managed Blockchain to write and read documents to Hyperledger Fabric. It illustrates how to create the network, set up users, load chaincode, front with an API Gateway and Lambda function, and deploy Hyperledger Explorer for visualizing the contents of the blockchain. It’s all automated using CDK and bash scripts.

Hyperledger Fabric CDK Construct – As I was developing the above, I realized there could be value in porting the capabilities provided by the bash scripts into custom resources, and packaging it all up into an easily installable CDK construct. This was my first foray into publishing a construct, and I learned a ton about it, in particular how to use projen to deploy a full CI/CD pipeline and get support across all CDK-supported languages.

Ethereum CDK Construct – Essentially the same as the above, but for Ethereum-based blockchain networks. I can only take minor credit for this one; while I gave them the idea, most of the implementation was done by an early career cohort as a capstone project.

Math, Music, and A/V Tools

Lilypond Music Files – Analogous to LaTeX for academic whitepapers, Lilypond is a text-based markup language for engraving (i.e. typesetting) sheet music. I created this repository as a place to collect my own by-ear transcriptions of bass guitar lines. There’s not much in there; consider it an aspirational life goal to add more (what would be extra rad is if this could be automated via AI/ML, with a tool like melody.ml).

Mix Maestro – I’ve been mixing live audio for nearly 20 years, on both analog and digital consoles. Back in 2013 I was doing so on a Roland mixer that had an RS-232 interface for remote control, and I wanted a way for musicians to adjust their own levels without buying an entire Aviom setup. So I grabbed a Raspberry Pi and wrote an HTTP server that abstracted the details. This repository contains the server code; I also wrote a companion Android app.

Light Maestro – Similar to Mix Maestro, I needed a way to control stage lighting, but without any budget to buy a console that had an app. Not only was I able to get a DMX interface built on top of another Raspberry Pi, but I was able to synchronize scenes to ProPresenter via its ability to trigger audio file playback, which I detected using Linux atime changes. Kinda hacky, but it worked more reliably than the bargain basement light board and the inexperienced volunteers that ran it.

Project Euler Solutions – If you want a fun and nerdy way to practice coding, Project Euler is a great resource (and more fun than Leetcode in this mathematician’s opinion). This repository contains my solutions to all the problems I’ve solved to date.

Docker Images

Buildozer – I love Python a lot, and sometimes that means I want to use it for projects where it isn’t typically considered, such as cross-platform GUI app development. With Kivy, it turns out to be quite possible. Buildozer is a framework for building Kivy apps for Android and iOS. Getting its dependencies right is a pain, especially on MacOS, but Docker to the rescue!

LaTeX – Back in graduate school I earned money by typesetting academic papers for mathematicians (such as the esteemed George Andrews) using LaTeX, a typesetting system built by none other than Donald Knuth, one of the giants of computer science (if you haven’t read The Art of Computer Programming, you really should; those folks were geniuses in ways modern developers rarely appreciate). Anyhow, LaTeX is also one of those tools that’s tricky to get set up, so it’s a perfect fit for running in Docker.

Development Utilities

AWS CLI Profile Credential Helpers – Early in my tenure with AWS, I was working with several customers simultaneously, each of which had its own single-sign on solution for their accounts (e.g. Azure SSO, Okta, Shibboleth). In order to abstract away the details of each provider’s mechanism for getting temporary credentials, I built this wrapper, along with a handful of other useful utilities. I’ve used them daily ever since.

Amazon CloudWatch Publisher – Another tool that came directly out of customer work, I needed a way to publish basic CloudWatch metrics (like CPU usage, disk space, network traffic) from Apple hardware, which would not (at the time) run the CloudWatch agent. I decided to build it in Python (natch), which has the added benefit of allowing it to run on other platforms such as the Raspberry Pi.

Kubernetes Tools – It took me a couple months of regular usage to get comfortable with kubectl. Once I could rattle off most commands from memory, I found myself doing similar things over and over. Hence these wrappers. I stuck them on Github for posterity, and am glad I did.

MacOS Dotfiles – Since I made the switch to MacOS (and its Linux-like terminal) in early 2014, I’ve had 4 employer owned and 2 personally owned Apple computing devices. Not changing that any time soon, and looking forward to a rumored 15″ Macbook Air, which I’ll probably buy for its portability (don’t really need the raw power of the Pro when I’ve got the cloud). When I do, I’ll use this set of scripts to automate its setup just how I like it.

Résumé Builder – An example of using LaTeX and my associated Docker image to build a PDF résumé via a continuous deployment pipeline implemented on Github and Travis CI. The résumé is the résumé, if you follow me?

Software Packages

Chrome Local Storage – Yet another project I’ve blogged about, this is a Python package for importing and exporting local storage from a Chrome browser. I built it to move Wordle stats from my laptop to my phone.

Output Scrubber – Writing sensitive information to application logs is generally a bad idea, but it’s easy to do so inadvertently. Include this package in your Node.js application, and it will insert itself into stdout and stderr and remove any pre-configured patterns it finds, such as social security numbers and email addresses. Of course if you’re logging in AWS, there’s some additional tools at your disposal.

Requestium – I’m not the original author of this package, but found its “best of both worlds” tremendously helpful when building some automation around an internal website, because it let me get logged in via Selenium and then switch over to the requests module to interact with APIs. When I needed a few new features, I offered to write the PRs, and discovered the creator was looking for a new owner for the project, and I decided to say yes, at least on a best effort basis. So far it hasn’t required more than a few hours a month at most.

Other Applications

Garage Envoy – This is another “build an HTTP API on top of a thing” project. I took a Raspberry Pi, added a relay that I wired into the opener, and some proximity sensors for detecting the position of the door, and voilà, I had an Internet controllable garage door. The most useful thing here was learning how to control the RPIO pins on the Pi to open/close switches and read sensor values.

Pinochle Scoresheet – In 2013 I went back to school to get a web development certificate from San Diego State. Part of that program was a class on Android app development, and this code was my capstone project. Pinochle is a card game that I’ve been playing since I was a kid, so it was fun to create an app I’d actually use. In retrospect, though, a native app is overkill and a simple mobile-friendly web app would be fine. Also, this app was Pinochle-specific, but I play quite a variety of games regularly, so a general-purpose tool would be nice to have…

Online Scoresheet (coming soon) – … thus this idea was born. Besides being an app I would use myself, I want to use this development to learn a few new things. First, I want to build it within a cloud-based integrated environment like Github Codespaces or Amazon CodeCatalyst. Second, I want to (finally) learn React.js beyond a hello world app. My domain name is bought (onlinescoresheet.net plus a few synonyms) and a sample app is spinning, all I need to do now is build it out.

Garbage In, Garbage Out

Garbage In, Garbage Out

I try to put as much code as I can on Github, as an exercise in learning in public. Over the holiday I published something new: a Lambda function deployed with CDK that is called when events fire from Buy Me A Coffee. It’s notable for a couple reasons:

  • First, if you haven’t noticed, there’s now a little orange icon down in the lower right of this blog. If you’ve benefited from my writings here, and are feeling generous, you can buy me a coffee using that icon. No pressure, though!
  • Second, I wanted a permanent reference repo for doing a basic Lambda deployment with CDK, and now I have one.
  • Finally, and most interestingly, my first draft of this code (both the CDK and the function itself) was written by ChatGPT.

As I’ve been reflecting on what artificial intelligence means for the future software engineering, I doubt it’s going to obviate the need for understanding code. What I do think it will be able to do is produce workable drafts, getting maybe half-way to a workable solution, with developers making revisions to get it across the finish line.

If I’m right about that, software professionals are going to need to tweak their skill sets to be less like writers and more like editors. Few developers I know are particularly adept at reading code, though it’s a shortcut for leveling up coding skill. Software is an oddball in that respect: in most other creative domains, one must study the work of the geniuses who came before, but we don’t typically train coders that way. Now it might not even matter, because the machines can do the studying for us.

What will be important, then? Formulating problems, and then tweaking resultant autogenerated code. So code fluency will still be needed. Just not for the boilerplate; for that, we’ll have tools like ChatGPT and AlphaCode.

Living On A Jet Plane

Living On A Jet Plane

Between a job requires a considerable amount of travel, and a whirlwind European vacation this summer, I’ve been to quite a few places this past year:

I’m thankful for the experiences I’ve had to date. Few things are more humbling than realizing that you are just one individual in a large world; I feel that way from my travels, and I’m far from having seen even a decent fraction of the cultures that fill the earth.

Want to be a better developer, manager, relative, friend, or person in general? Consider travel if you can.