Bleeding

February 19th, 2025

For many centuries, bleeding patients was a standard treatment for many diseases. Cancer? Bleed the patient. Headache? Bleed the patient. Fever? Bleed the patient. Pneumonia? Bleed the patient. Bleeding was accepted medical wisdom.

Perhaps surprisingly to modern patients, bleeding worked, at least some of the time. The patient would get better. Of course, a lot of the time if the doctor did nothing, the patient still got better. No one bothered to ask whether it was the bleeding that caused the patient to get better or not. Few people even knew how to phrase the question.
Read the rest of this entry »

Stack Traces Considered Harmful

February 13th, 2025

I’m trying to build an open source project in a language I’m unfamiliar with and hit this problem:

(base) $ ruby bin/setup
== Installing dependencies ==

A new release of RubyGems is available: 3.6.2 ? 3.6.3!
Run `gem update --system 3.6.3` to update your installation.

Bundler 2.6.2 is running, but your lockfile was generated with 2.3.9. Installing Bundler 2.3.9 and restarting using that version.
Fetching gem metadata from https://rubygems.org/.
Fetching bundler 2.3.9
Installing bundler 2.3.9
Your Ruby version is 3.4.1, but your Gemfile specified ~> 3.0.4
bin/setup:16:in 'Kernel#system': Command failed with exit 18: bundle (RuntimeError)
	from bin/setup:16:in 'block in 
' from /opt/homebrew/Cellar/ruby/3.4.1/lib/ruby/3.4.0/fileutils.rb:241:in 'Dir.chdir' from /opt/homebrew/Cellar/ruby/3.4.1/lib/ruby/3.4.0/fileutils.rb:241:in 'FileUtils#cd' from bin/setup:10:in '<main>'

This illustrates a common antipattern in error handling. This is a Ruby program, but I’ve encountered it often in Python programs too, including the Google Cloud SDK. It also happens in Java, though less frequently. The most common place it appears in Java is when JUnit tests fail. Do you see it?
Read the rest of this entry »

Different Styles of Dependency Management

February 8th, 2025

Recently I was hacking out a quick Python script. Everything was fine until I needed to import one common third party library and then Boom! I was dropped head first into the messy chain of Python dependencies, weak typing, virtual environments, and conflicts. I couldn’t even install the necessary library with pip. I’d just get an unintelligible hash of error messages and stack traces.

So off to DuckDuckGo I went to remind myself how one actually builds and packages real world Python programs that do more than print Hello World! It wasn’t pretty, and it took me quite a while to understand it. This was actually harder for me than it might have been for a newbie because I was so invested in the way Java manages dependencies. I’ve spent years working with dependency management in Java at a depth most developers never sink to. I’m an Apache Maven committer. I’ve rewritten most of their documentation about dependencies. I’ve written tools to analyze Java jars, dependency trees, and classpaths. I wrote or edited most of Google’s Java Library Best Practices. I’ve debugged many problems caused by Java class loaders. So I’ve got a pretty good understanding of how Java dynamically links third party dependencies.

But Python? Python doesn’t work like that. And neither does everything else.
Read the rest of this entry »

Assume vs. Assert

February 1st, 2025

Assumptions are an underused feature of modern testing frameworks that should be more widely known. Briefly, an assumption verifies that conditions are right to execute the test. An assertion verifies that the test passes. If an assertion fails, the test failed, and we know the code is broken. If an assumption fails, the test was not run and the code may or may not be broken.

Read the rest of this entry »

“Is A” vs. “Represents A”

January 24th, 2025

We’ve all had the distinction between “Is A” and “Has A” in object oriented programming drilled into us. “Is A” relationships call for inheritance. “Has A” relationships call for delegation. Some theorists will even bother to distinguish between “Is A” and “Is a Role Played By“. However, recently I’ve been wondering about the distinction between real “Is A” and “Represents A” relationships, and I wonder if it may help explain some otherwise confusing points.
Read the rest of this entry »