I find that my colleagues are relying on AI to automate some of their bookkeeping tasks, and while it’s not wrong, it’s causing more work. Here’s a response I sent.
Hi Colleague, I see that your AI is prompting me on a weekly basis for progress on several initiatives (on a larger project) — the prompting is mostly slop, with a little bit of signal among the noise. Please reach out to me as a live human with specific questions, and do it (less frequently) every 2-3 weeks. Thank you.
The Natural World
I spend a great deal of time in front of a computer screen, inside — insulated from the natural world. Being insulated from the weather has advantages and disadvantages. I also appreciate being outside in nature among verdant trees and fresh flowing air. It gives me perspective, peace and a lower stress level.
About a decade ago, thanks to my son, I learned to ski, and it’s been an activity I look forward to each winter. Being in the mountains, above the inversion, with family and friends, is therapeutic.
In the last five years, I’ve come to enjoy jogging short distances — something I can do with my wife.
More recently, I mountain bike with my son’s team, and it’s fun to be with energetic youth and see their endurance and ability increase as the season progresses.
Solved: Slow Laptop WiFi with WPA3
In 2023, we bought three of our children ThinkPad E14 Gen 4 AMD laptops. Later that year when they were away at college, we upgraded our home router to a TP-Link AX3000 WiFi 6 router. Recently my daughters, who are visiting for the summer, started complaining about their unreliable and slow internet connections. The laptops contain a Realtek WiFi card, and the wisdom of the internet determined that it doesn’t do well with WPA3.
Possible solutions included 1. configuring the router to do WPA2 only, or 2. upgrade the the WiFi to a Intel AX210. My daughters chose the latter, and I helped them swap out the WiFi cards — it was fun, and it might’ve been their first time opening up a computer. The Intel WiFi chips allow their laptops to connect to the internet quite well. I’m glad there was a happy ending.
Good terminal font: MesloLGS NF
Standardized naming & data typing for integrated & loosely coupled systems
When working on a project with dozens of engineers (some of whom come and go) over the span of a decade, it becomes apparent that not everyone thinks the same, names variables the same that cross system boundaries, or uses data types consistently.
Yet converging on a standard is important so that “downstream” consumers of the data can interpret the data consistently, accurately, without as much special case code.
That may sound abstract, so I will give some context and concrete examples. The system may look something like the following, at a high level:
- Hubs, Cameras & IoT sensors in millions of homes or businesses, reporting in to a centralized set of servers. The devices have software written in Python, C, C++, Rust and bash.
- Servers that store the data & provide APIs for Smarphone apps & other business stakeholders — service tools, inventory control, account management, etc. The database could be a document store without a formal schema or common data types.
- The server farm consists of dozens or even hundreds of microservices,, many of which need to understand the data.
- A data lake that replicates the data and allows data analysts to do their thing
Let’s say that we want to report device status — which could include whether the device is online or offline. What do we name it? Is it a boolean or a multi-state with states of Unknown, Initializing, Offline and Online? Do we allow booleans to be represented as integers? With a variety of different engineers, we could end up all over the place with naming and types — each device could be arrive with a different set of choices.
If all of the code is “owned” by one organization, it is helpful if there’s consistency — it helps with understanding, consistent interpretation of the data, maintenance, and less necessity for special casing.
Imagine if an Android app needs to present a list view of the online status of all devices, and it has to cycle through logic to handle different names for each device type?
Loop over a list of all devices...
If device is camera_type_1, retrieve the "online" property as a boolean
else if the device is camera_device_2, retrieve the "offline" tri-state integer
else if the device is a thermostat, retrieve the "node_online" property as an integer that is essentially a boolean
And multiply that by many times, across iOS, web apps, many micro service and data analysts.
I hope that it’s clear that engineering standards can ease the cost for downstream consumers of the data.
But what if we have engineering standards, and no one reads them? There’s already enough other mandates, requirements and complexity for new-hires and even seasoned software developers.
That’s where tools can help. Like running linters or build servers that do checking, we can implement our own tools that do the checking for us, so that we don’t have to know or remember every standard.
What if not all of the code is “owned” by one organization, and devices must be integrated that use different standards? It can be more of a challenge.
It may be possible for the ingress/egress interaction points on the servers to translate to and from consistent naming standards and data representations. It can still be difficult when the data types and representations vary wildly. Sometimes, the desire to standardize results in data loss.
Consider what happens when the servers expect temperature to be represented as Celsius as a integer and a device supports temperature as Fahrenheit as an integer: There’s going to be rounding errors going back and forth between the two. Other choices could include the server representing temperature as centi-Celsius, milli-Celsius integer, or as a float.
What if the server stores temperature for different devices in Celsius, Centi-Celsius, Fahrenheit and Kelvin? We don’t want people incorrectly interpreting the data. It’s helpful to have a standard so that people know the units involved. Choices could include a suffix indicator, or an additional data point that tells the units.
Working with 64 bit integers can be a challenge for web front-ends. The device, the server and the database may all handle them adeptly, but what happens when we send one to a JavaScript front-end? It will break on large integer values — because JavaScript is limited to supporting integers of up to 53 bits, minus one (i.e. 2 ** 53 -1). It may be that losing precision is acceptable in some cases, and not in others, or that we want people to store them as a string. An engineering standard can help address this kind of challenge.
What about MAC addresses? Could it be helpful for a standard to specify upper or lower case, and whether to use separators? It makes the job of downstream consumers easier.
What about normalizing data and losing information? If data loss is a problem, could the server store the data in “raw” form, as sent by the device, and also support a normalized/translated version? When translation fails, what value does the normalized/translated data contain? E.g. a device sends an Ethernet MAC address of “uninitialized” or “driver error”, what do we do?
Engineering standards can also define…
- default values. E.g. an uninitialized dBm signal strength… should it be 0 or negative 100 or negative 128? Many languages initialize variables to 0. A dBm of 0 is an impossibly powerful signal strength for in-home radios like WiFi devices.
- allowable ranges for temperature, signal strength, etc.
- preferred unit representations. E.g. dBm instead of a percentage.
- maximum length of strings, arrays, and maps.
- positive naming logic preferred over negative, where applicable. e.g. “online” instead of “offline”.
- and so much more.
Thank you for reading. May your code wrangling and engineering standards go well.
Enum values: Integer or string?
I’ve been writing software for a few decades and historical momentum has been to define enum values as integers, probably because earlier languages supported integers, not strings.
class Color(Enum): UNINITIALIZED: 0 RED: 1 GREEN: 2 BLUE: 3
So it was a surprise when a discussion among engineers went the other direction — encouraging strings as enum values — for newly introduced enums. It seems that industry momentum may have shifted this direction. Here’s a contrived example that I do not recommend:
class Color(Enum):
UNKNOWN: ""
RED: "rood" # Note: Dutch
GREEN: "verde" # Note: Spanish
BLUE: "bleu" # Note: French
LAVINDRE: "lavndir" # Note: Purposefully misspelled
Benefits of using string enum values include:
- Clarity when viewing logs. However, it is possible to log integer enum values as strings.
- Clarity when debugging. However, some debuggers may already add clarity for integer-based enums.
- Disparate teams across the organization can more readily understand the data without having to refer to documentation.
- API interoperability and clarity.
- Ease of adding new items in the middle of the enum, whereas with a sequential integer approach, it is not possible.
- Default value as empty string. It has always been a pain when an engineer decided to use 0 to indicate anything other than “default”, “uninitialized” or “unknown”, because 0 is often the default value for uninitialized variables and properties. With strings, an empty string is ideal.
- It’s still possible to represent string-value enums as integers when persisting to a database or interoperating with other systems — although it may require additional work.
Caveats and counter indications:
- Legacy. Keep what works and don’t break things, especially when disparate systems depend on existing enumerated integers. Translation layers can be a solution.
- Lack of programming language support, although there are often alternatives including use of constants.
- When the enum string values are misnamed or poorly named, it can cause confusion and bugs due to misunderstandings.
- Who gets do decide which human language we use for the string values? Who will be consuming the values? Do they understand the language? I gave my example above with three different language values to emphasize that it’s best to stick with a single language.
- Misspelled values may need to remain misspelled forever to prevent breaking disparate consumers. Software engineers are human, and they make mistakes. We don’t usually misspell integer values, and when do, the software either won’t compile or won’t run. Translation layers can be a solution.
- Upper or lower case? Camel case or snake case? Decide on a standard.
- Performance critical systems and RAM/storage constrained systems may do better with integer values.
- Some databases support enums — the underlying data is an integer, and the database represents it as a string, including in queries and exports — so it could be possible to get the best of both worlds — performance and clarity for humans.
- Isolate the churn of a ever-changing names. The integers can stay the same and the enum keys can change to reflect current needs. E.g. marketing names tend to change.
Smart light switch lifetime: Resetting my expectations
I tend to think that an in-wall light switch should last twenty to thirty years. However, I’ve had to reset my expectations with smart switches.
I’ve had a several decora GE Jasco Z-Wave switches in my home for the past 10 years. Four of them lasted seven years before the electronics completely failed. I replaced three of them with new Jasco switches, and one of them with a dumb switch. When another switch stopped reliably responding to button presses after nine years, I replaced it with a traditional “dumb” switch. Another two Z-Wave switches are still going. Of the two, one is used multiple times per day, and the other one is used a few times per week.
Compared to dumb switches, smart switches contain additional complicated electronics — integrated circuits, capacitors, resistors and diodes. They’re more subject to age, “dirty power” and other environmental factors. High quality components can extend the expected lifespan.
There have been a few times when the switches stopped responding, and I’ve had to reset them. They have a small tab to pull, and then push back in. It’s like resetting a GFCI, only more difficult.
Z-Wave has had staying power, and Z-Wave devices communicate locally, so are not subject to the whims of a cloud provider who might decide to end support, or to economic forces that might shutter a business, leaving devices without cloud support. Still, the staying power of the cloud provider, or of a technology, also has an impact on the liftetime of a smart switch.
I expect smart switches to last 7-12 years, and to be less reliable than traditional switches. Is the convenience and automation worth it? Sometimes, yes. Other times, no.
CertSage ACME client and shared hosting
I host my website on asmallorange.com and recently, I noticed that Brave and Chrome would no longer load the website without TLS.. I looked in the cPanel, and the hosting provider wanted too much money to give it a TLS certificate. A web search turned up “CertSage ACME client”, and within 10 minutes, I had it set up and now my site has a proper TLS certificate from Let’s Encrypt. Thank you to everyone who made this possible, and I especially appreciate the vision of Let’s Encrypt.
Engineering mileu and customer experience
We have lived in our house for 17 years, and have replaced three dishwashers — a disappointment because in my mind, even a cheap dishwasher should last 20 years. The first was quite old, inexpensive, and still functional, but was loud and cleaned adequately only when we pre-rinsed all food bits. After two years, we replaced it with a different brand, a higher-end model with a steel tub — a KitchenAid. It cleaned dishes better — until it didn’t. The plastic roller axles on the lower tray broke, and I replaced them with steel bolts and nuts. The impeller drive motor broke, and I replaced it. The upper tray had plastic that broke, and I repaired and replaced it over four years. My young children sometimes got the twist ties from bread bags in the dishwasher, and I’d eventually find them in the disposal of the dishwasher, and would pull them out, along with gunk.
At some point, the control board fried, I contacted KitchenAid, and they said they’d sell me a new high-end model at a discount price. So I went with that. It wasn’t as much of a discount as I had hoped, and initially, it worked well.
However, over time, it had somewhat similar issues to the previous dishwasher — nylon parts were engineered cheaply, or engineered to fail over time. I replaced things as they broke, and when its ability to clean went downhill, I decided I’d had enough — I would “fire” the previous team of engineers and “fire” the entire process and culture that created the less-than-stellar machine, and “hire” a new team of engineers, with a different process — so we bought a Bosch.
The Bosch is different. No disposal. No heating element. No cheap plastic rollers. It has cleaned well, and has been a joy to use for over two years. It continues to clean well.
I don’t think the engineers from the previous company were inept. They had a different environment and a different set of constraints to work under — an environment that did not serve me, the customer, well. So I found one that had a mileu, culture, insights, and vision that have served our family better.
Printmaster 18.1 on Windows 11
My wife has been using Printmaster for over 25 years, and for the past several years, she’s been using version 18.1. When it stopped working recently, she enlisted my help. It turns out the desktop shortcut not longer functioned — it gave an odd install error. When I created a link to the executable, and pinned that to her toolbar, it worked — it functions again.