Have you ever been asked to help with something, agree to do it, only to find out your job is to just stand there and hold a flashlight while someone else does all the work? Then, when they’re done, they thank you for the help? When you’re a kid and get relegated to flashlight holder, it’s the most depressing feeling in the world. You did literally nothing, and the other person had the gall to thank you. Then you get older, and have to do some job that requires a third (or even fourth) hand, and all of a sudden having someone there to just hold something in place for you actually is a really big help. I get the impression that the whole trend of AI development is a bit struggle to figure out who’s doing the work, and who’s doing the minor, but still very helpful, assisting.
(more…)Category: Programming
Used for posts that deal heavily with code, design, and programming specifics.
-
Why I’m shifting my programming vocabulary
Yes, I know I missed the peak on renaming software terms, like changing the default trunk branch name from “master” to “main,” or the trend of renaming “whitelist” and “blacklist” to “allowlist” and “blocklist,” but I’m also not trying to change how I talk because people are capable of stretching words until they get offended. That’s always going to be an issue, and I don’t have nearly enough patience to indulge it. What I am trying to do is avoid terms that have developed connotations that lead to bad programming habits, and replace them with ones that are clearer about what I’m trying to accomplish, and don’t invite people into fixating on the wrong pieces and losing sight of the point.
(more…) -
Product management really does matter
Not too long ago, Joel Spolsky’s blog post about architecture astronauts hit my various consumption feeds, and it serves as a good reminder that, as fun as it is to make fun of product managers (and it is a lot of fun), they’re also probably the most important people in software development. That may seem a bit over the top, seeing as how QA engineers are the ones who ensure that what’s shipped actually works, developers like me actually write the applications and services in the first place, and then there’s the operations teams that build and run the production infrastructure the code actually runs on. It sure sounds like there’s a lot of other people with a lot more direct connection to the actual engineering bits. The truth is, we’re all important, but without good product management, it’s entirely possible for everyone else to do a perfect job…and the release still fail.
(more…) -
If you’re going to just run the code, just run the code
I’m very pro “just running the code” when it comes to testing software. But while just spinning up containers does actually “work” – in the sense that the test runs and completes without error. But you very quickly realize that’s clearly not how these things are supposed to work. I’ve been using testcontainers to test the gift registry app I’ve been working on, and it’s been great. I’ve implemented a basic passwordless login setup, and I can test every part of this using live code with the sole exception of actually sending an email via a simple
(more…)make test. But this was very obviously not the best way to go about it, as you can see from the test output: -
System 1 programming
Early in my career, my team lead pulled me over to show me something in some code of mine I had written and put up for peer review. I don’t remember the exact context, just that there was a fairly simple operation that could have been done quite simply in 4-5 lines of code, that I had cleverly condensed down to 1. He had the code in question up on the screen and told me “I see what you’re doing, and this works. But it took my pea brain about a minute of really thinking about it to understand what you’re doing and confirm that it works. On the other hand, if you had just written this out in 4-5 lines of code, I’d have understood it instantly. So I’m going to need you to fix this.” It’s a vivid, specific example of something experienced developers try to impart on the newbies – don’t get clever, and don’t hesitate to write more lines in order to be more explicit about what you’re doing. I just finished reading Thinking, Fast and Slow by Daniel Kahneman, and this incident jumped back to my memory, because it was the perfect case study for writing code they way we naturally think.
(more…) -
Abstractions are hard to get right
Abstractions are 1 of those things that are fairly easy to understand the basics of, but hard to really do right. They’re a tool used to simplify code by using a simpler-to-understand proxy (like a database record or a class/interface), but that doesn’t really scratch the surface of how to use them well vs. just tossing in them into code because you’re supposed use them. Done well, abstractions let you move forward while keeping just the right level of detail in your head. The problem is that almost everything we do in programming is just layering abstractions over real-world processes and behaviors. That makes it deceptively easy to have software that feels like it’s in the way more than it is actually helping anything.
(more…) -
The AI pitfall
I really wanted to call this “The AI trap,” but I try not to ascribe to malice what I could explain with ignorance, apathy, and/or stupidity, and given that I generally don’t ascribe the level of foresight and deliberation needed to execute a “trap” to the types of people running large public companies, “trap” isn’t the right word. But even so, this push to start using AI to do as much as humanly possible has already generated content about the plight of junior devs. What I’m worried about is senior developers (yes, I am technically considered a “senior” dev, so there is some self-interest here) are about to walk themselves into a nasty setup they’re never going to recover from.
(more…) -
You can just run the code
So I haven’t made as much progress on the actual gift registry I wanted to write this year, although I do have a Go web application that connects to a Postgres database, with an endpoint that gets the database stats, collects telemetry data, pipes it all to an OpenTelemetry stack, and returns an HTML page with the health check results (server-side rendering is a much more pleasant experience than trying to wrangle Javascript frameworks). I also have tests that confirm this is working. That took a lot longer to set up than I anticipated, but I’m really happy with what I’ve been able to do.
(more…) -
Another “left-pad” incident is coming, and it’s going to be nasty.
Maybe it’s just me, but lately it seems like every problem that doesn’t come directly from customers is resolved by integrating with something that just does it for you, no need to worry. Some of this stuff is really useful because it solves a problem that’s tangential to yours but too much work to just do yourself (for example, a library that renders graphs on a web page based on JSON data, or a framework for setting up a REST API web server). But lately it seems like more and more stuff is coming out that’s handling stuff that really should be handled by the application itself (for example, building an OAuth sign-in widget, or implementing feature flags). I get not wanting to spend a lot of time on something that isn’t the key thing that your business does, but I think we’re wildly overestimating the value we’re bringing to our applications if we outsource everything but proprietary company data, and wildly underestimating our exposure if 1 of these dependencies breaks or has a security problem. Just because it’s not “core” to the main objectives of our software doesn’t mean it’s not important, or so complicated that we can’t do it ourselves.
(more…) -
Just write the setters (and the getters while you’re at it)
I’ve been against the idea of writing getters and setters off as boilerplate for a while, yet sadly that’s the prevailing idea in software development. A large part of that is probably fueled by the fact that we treat objects is nothing more than a local copy of database records. The result is that half the time we’re assuming the data is already valid and we don’t have to validate or default anything (when we’re reading it from the database), or that we just have to validate data when it first enters our system via endpoint (when creating or updating a database record). As a result, we don’t have to actually write proper getters and setters, and can lazily just use the templates our IDEs make for us, and outsource our validation to some simple annotations. It’s a tempting sales pitch, but it’s for a specific (limited) use case. Getter and setter methods, on the other hand, are universal.
(more…)