Good terminal font: MesloLGS NF

The other day, I learned about the “MesloLGS NF” font. It’s a highly legible font for terminals and for looking at code. I’ve been using it for a few days, and I like it better than IntelOneMono (which is also a great font) and probably as much as Hack 10.

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…

  1. 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.
  2. allowable ranges for temperature, signal strength, etc.
  3. preferred unit representations. E.g. dBm instead of a percentage.
  4. maximum length of strings, arrays, and maps.
  5. positive naming logic preferred over negative, where applicable. e.g. “online” instead of “offline”.
  6. 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.

How to rate people and teams

Notes from June,  2022 about about how to rate people and teams as I read Nine Lies About Work. The notes are my own (although the quotes are not), and I may have misrepresented some of what the book was saying; some of the examples are ones I made up.

Lie: People can reliably rate other people (on an abstract attribute such as performance or strategic thinking)

Summary: Although we can’t reliably rate other people, we can reliably ask about our own experience and our own intentions “right now” in regard to those people. (Sidenote: we aren’t reliable at rating our own personality or performance.)

Why:

  1. The Idiosyncratic Rater Effect — accounts for 54% of how people rate others (or so says the book)
  2. Data insufficiency: we don’t “see” people enough to be able to rate them accurately
  3. There’s no single definition of “performance” between people, let alone teams.

“Lucy’s pattern of rating does not change when she rates two different people. Instead her ratings stay just about the same – her ratings pattern travels with her, regardless of who she’s rating, so her ratings reveal more about her than they do about her team members. We think that rating tools are windows that allow us to see out to other people, but they’re really just mirrors.”


  • Crowds are not smarter than a few people. Truth: well-informed crowds are wise. Ill-informed crowds are not.
  • Noise plus noise never equals signal.
  • Bad data contaminates all the good data.
  • Adding bad data to good, or the other way around, doesn’t improve the quality of the data or make up for its inherent shortcomings.

Good data has three distinct characteristics:

  • it is reliable
  • it is variable
  • it is valid

Reliable:

  • stable and predictable measurements
  • something that can be counted
  • doesn’t mean accurate… it means the data doesn’t fluctuate randomly
  • Your height is reliable data. I.e. we can trust the data-gathering tool

Variable:

  • The range of data reflects the natural world.
  • E.g. when a car salesman is rated 5/5 by all customers, there’s no variation, and therefore the measure doesn’t mean anything in the real world.
  • E.g. when a thermometer bottoms out or maxes out on measuring real world temperatures, it’s not variable enough.
  • When it comes to rating our own human experience, “to produce a range in our rating tools, we have to create questions that contain extreme wording.”

Valid: a.k.a. criterion-related validity

  • Once piece of reliable data predicts another piece of reliable data
  • Does a high score on the measurement tool predict a high score on something else in the real world?
  • When a scatter plot of the data shows that it clusters to one end of the scale, it’s probably not good data.

A more reliable way to capture data about people. “People can reliably rate their own experience” and intentions “right now”.

We can ask a manager/peer questions like this (and do it in a timely fashion, not asking them to reflect 4 months later):

  • Do you always go to this team member when you need extraordinary results?
  • Do you choose to work with this team member as much as you possibly can?
  • Would you promote this person today if you could?
  • Do you think this person has a performance problem that you need to address immediately?

Thought: Regardless of human limitations in accurately rating others, we do it anyway. Recognizing that our ratings of others are biased and inaccurate is hopefully a step toward humility, and thus to more fully loving others, and trying to avoid incorrect ratings 


Here’s the author’s website with three pages, all brief. The first explains the problem, the second explains a solution approach, and the third gives a concrete example of questions that he asserts “predict high-performing teams” in four areas: Purpose, Excellence, Support, and Future.

https://www.marcusbuckingham.com/good-data-bad-data-idiosyncratic-rater-effect

https://www.marcusbuckingham.com/data-fluency-series-current-tools-good-data

https://www.marcusbuckingham.com/data-fluency-series-case-study

I’m still here; rich tapestry among employees

Yes, I’m still here. My rate of writing blog posts has slowed over the last few years.

About a year and a half ago, I become a software engineering manager. It’s been an interesting journey to hire and work with employees. Each one brings a unique set of talents, enthusiasm and skills to the table. Thank goodness none of them are the same! I appreciate a rich tapestry of perspectives and motivations.

I still dabble in code, and contribute at a lesser level. Is this good? Is it bad? It’s neither — it’s a different focus, a new experience. It’s rewarding to see excitement in others, and to see the payoff when hard work comes to culmination and is delivered. I like seeing others succeed.

MacOS and the command line

I’ve spent decades using the Linux command line on a daily basis. Six months ago, I switched to a MacBook Pro as my day-to-day machine, and I’m still learning to acclimatize. Happily, many of the tools I’ve grown to love still work on MacOS, either because they’re shipped with it (ssh, git, python3, bzgrep, zip, less, curl), or because I’ve installed them with “brew install …”

  • vim
  • ripgrep ‘rg’
  • tree
  • xz
  • socat
  • shellcheck
  • tcptraceroute
  • screen
  • jq
  • jhead
  • htop
  • coreutils

Things that are subtly different, and still annoy me:

  • find lacks a -mindepth option, so install “coreutils” and use “gfind”
  • bash 3 is ancient and doesn’t work like modern bash 5, so use zsh instead
  • grep lacks -P. Happily, -E gets me most of what I want, and when it doesn’t, I use “ggrep” (brew install ggrep) or “pcre2grep” (brew install pcre2) instead.
  • cat doesn’t respond to CTRL-D, so use CTRL-C instead, or use “gcat” from “coreutils”
  • ps is very different, and lacks a –forest option, so install and use “pstree”
  • zcat doesn’t use gzip. It handles compress Z files. So use “bzcat” , or “gzcat” from “coreutils”.
  • no sha256sum, md5sum, etc., so run “brew install coreutils” to get them.

There’s far more, under-the-hood, that is different, but I haven’t run into those things as much, yet. I’m still more comfortable with Linux, but I’m glad that “brew install” gives me so much. Thank you to the people who maintain ‘brew’ and the packages.