To C or not to C

Over the last few days, there has been this… debate over at Twitter sparked by a claim that you cannot be a good programmer without knowing C. You obviously can be one, but there is some nuance in what “knowing” C is truly about. Here is my take on the matter. Let me repeat this first: of course you can be a perfectly good programmer without knowing C. Knowing a language doesn’t make or break a programmer, and there are great programmers out there that don’t touch C.

February 21, 2024 · Tags: blogsystem5, opinion, programming, twitter-thread
Continue reading (about 4 minutes)

Code reviews: A success story

Code reviews have a bad rep: they are antagonistic in nature and, sometimes, pure red tape. Some argue that they are bad practice; others say that peer programming is better. And while these may be true, I want to tell you a story about a case where code reviews worked well! Meet X: a junior engineer in the Bazel team circa 2018, tasked to implement two features: A and B. As you may know, Google is big into code reviews—and their tooling for this is awesome; believe me—so this was the standard process for X to get his code checked in.

November 21, 2023 · Tags: programming, twitter-thread
Continue reading (about 4 minutes)

5 ways to instantiate Rust structs in tests

I’m a big fan of static typing and I’ve found that using narrow types for each entity in the object model of my programs reduces errors. Rust is particularly well-suited at this task: its lack of implicit type conversions eliminates surprises, and its ownership semantics allow type transformations with zero cost. Unfortunately, (ab)using narrow types in an app’s domain is really annoying when writing tests. While non-test code rarely instantiates new objects—in the case of a REST service, this would only happen at the service’s boundaries—tests instantiate objects infinitely more times than non-test code. Code patterns that may seem reasonable in non-test code can become unbearable in tests. In this post, I want to look into the various ways in which you can instantiate strongly-typed objects. For each, I show examples and describe their pros and cons. And yes, as a matter of fact, I have tried them all before… and I can’t yet make my mind as to which one is best.

October 6, 2023 · Tags: programming, readability, rust
Continue reading (about 10 minutes)

Good performance is not just big O

Having a fast and responsive app is orthogonal to “knowing your big Os”. Unfortunately, most tech companies over-emphasize algorithms in interviews and downplay systems knowledge, and I believe that’s one reason behind sluggish apps and bloated systems. I’ve seen this play out repeatedly. Interviewers ask a LeetCode-style coding question, which is then followed by the ritual of discussing time and memory complexity. Candidates ace the answers. But then… their “real” code suffers from subtle yet impactful performance problems. Focusing on big O complexity rarely matters in most apps. Sure, it’s important to think about your algorithmic choices, but there are so many more details to worry about that have a direct impact on app performance and responsiveness. Let’s look at a bunch of them!

September 8, 2023 · Tags: programming, sre, twitter-thread
Continue reading (about 6 minutes)

Costs exposed: Frameworks

“Fast machines, slow machines”… ah, the post that spawned these series. As I frantically typed that article while replying to angry tweets, the thought came to mind: software engineering as a whole is hyper-focused on lowering the costs to write new code, yet there is a disregard for the costs that these improvements bring to other disciplines in a company on even to end users. So, in this series finale, I want to compare how some choices that apparently lower development costs actually increase costs elsewhere. I also want to highlight how, if we made different decisions during development, we could possibly expose those extra costs early on. This is beneficial because exposing costs upfront allows us to make tough choices when there is still a chance of changing course. To make things specific, I will look at how the use of modern frameworks that facilitate development can end up hurting performance, reliability, and usability. So let’s start with a three-part rant first (sorry) and then let’s look at what we might do.

August 31, 2023 · Tags: opinion, programming, sre
Continue reading (about 7 minutes)

Costs exposed: On-call ticket handling

In the previous post, I proposed that certain engineering practices expose systemic costs and help with planning while other practices hide those same costs and disturb ongoing plans. The idea I’m trying to convey is hard to communicate in the abstract so, in that post, I used the differences between a monorepo and a multirepo setup as an example. Today, I’ll expore a different scenario to support the same idea. I’m going to talk about how certain ticket assignment practices during on-call operations can expose service support costs vs. how other practices hide them. Keep in mind that, just like in the previous post, I do not want to compare the general merits of one approach vs. the other. The only thing I want to compare is whether one approach centralizes toil and allows management to quantify its cost vs. how another approach hides toil by smearing it over the whole team in hard-to-quantify ways. Whether management actually does something to correct the situation once the costs are exposed is a different story.

August 26, 2023 · Tags: opinion, programming, sre
Continue reading (about 7 minutes)

Costs exposed: Monorepo vs. multirepo

In software engineering organizations, there are certain practices that keep costs under control even if those seem more expensive at first. Unfortunately, because such practices feel more expensive, teams choose to keep their status quo even when they know it is suboptimal. This choice ends up hurting productivity and morale because planned work is continuously interrupted, which in turn drags project completion. The reason I say seem and not are is because the alternatives to these cost-exposing practices also suffer from costs. The difference is that, while the former surface costs, leading to the need to allocate time and people to infrastructure work, the latter keeps the costs smeared over teams and individuals in ways that are difficult to account and plan for. To illustrate what I’m trying to say, I’ll present three different scenarios in which this opinion applies. All of these case studies come from past personal experiences while working in different teams and projects. The first one covered in this post is about the adoption of a monorepo vs. the use of multiple different repositories. The other two will come in follow-up articles.

August 23, 2023 · Tags: monorepo, opinion, programming
Continue reading (about 6 minutes)

A failed experiment with Rust static dispatch

Initial versions of the EndBASIC Service, and therefore initial versions of EndTRACKER, used dynamic dispatch to support abstract definitions of system services such as the database they talk to and the clock they use. This looked like a bunch of Arc objects passed around and was done to support extremely fast unit testing. When I generalized the core logic of these services into the III-IV framework, I decided to experiment with a switch to static dispatch. The rationale was that using static dispatch better aligns with the design of well-regarded crates in the Rust ecosystem, and also because I wanted to avoid unnecessary runtime costs in the foundational pieces of my web services. Let me tell you that this decision was a huge mistake and that the experiment has utterly failed. Using static dispatch has been a constant source of frustration due to the difficulty in passing types around and reasoning about trait bounds. The situation had gotten so bad that I dreaded adding new functionality to my services whenever a change to a statically-typed struct was needed, because that meant adding yet another type parameter and plumbing it through tens of source files. In lieu of the difficulties, which eventually turned into blockers to implementing new features, I made the choice of going back to dynamic dispatch. The goal was to gain ergonomics at the expense of a supposedly-negligible runtime cost. Let me tell you about the problems I faced, the refactoring journey, and some measurements I gathered after the rewrite.

August 6, 2023 · Tags: endtracker, iii-iv, programming, rust
Continue reading (about 13 minutes)

Unit-testing a web service in Rust

One of the things I'm most proud of the Rust web services I have written is how I can run their tests with zero setup and within milliseconds, all while making me confident that "main" can always be shipped to production. I've previously touched upon how this all works in other articles, but it's time for a deep dive. To make things specific, I'll be describing the testing infrastructure of EndTRACKER, the EndBASIC Service, and the sample key/value store app of III-IV. These services are all structured in three separate layers, and I'll be covering the testing strategy for each of them.

July 7, 2023 · Tags: endbasic, endtracker, iii-iv, programming, rust
Continue reading (about 19 minutes)

Useless use of GNU

The GNU project is the source of the Unix userland utilities used on most Linux distributions. Its compatibility with standards and other Unix systems, or lack thereof, directly impacts the overall portability of any piece of software developed from GNU/Linux installations. Unfortunately, the GNU userland does not closely adhere to standards, and its widespread usage causes little incompatibilities to creep into any software created on GNU/Linux systems. Read on for why this is a problem and the pitfalls you will encounter.

August 25, 2021 · Tags: opinion, programming, shell, unix
Continue reading (about 12 minutes)

Should the browser use all available memory?

We have all seen discussions go like this: someone first complains that an application like Google Chrome is wasteful because it uses multiple GBs of memory. Someone else comes along and says that memory is there to be used for speed and therefore this is the correct behavior: if the computer has multiple GBs of free memory, an application such as Chrome should make use of all the available memory in the form of a cache to be as responsive as possible. Makes sense, right? Yes, it does makes sense—as long as Chrome is the only application running. Let’s explore why this is not a great idea.

August 12, 2021 · Tags: opinion, programming
Continue reading (about 13 minutes)

EndBASIC 0.6 release announcement

After a very active month of development since the 0.5 announcement, it is time to welcome EndBASIC 0.6! This new 0.6 release is super-exciting for three reasons: preliminary GPIO support in the standard library specifically tailored to the Raspberry Pi; multidimensional array support in the language; and availability of binary releases for the most common platforms. You can dive right in by: visiting https://repl.endbasic.dev/ for an interactive session, reading more about the project at https://www.

February 19, 2021 · Tags: endbasic, programming, release, rust
Continue reading (about 8 minutes)

Embedding EndBASIC into a (Rust) program

One thing that bothers me quite a lot about various language implementations is that the core of their interpreter isn’t clearly separate from their standard library. This makes it hard to embed those interpreters into other programs because it’s not obvious how to limit their side-effects and because the interpreter dependency can be heavy. In this post, we will see how EndBASIC’s design tries hard to keep the core as small as possible, and we will see some examples on how to use EndBASIC from Rust and vice versa.

January 26, 2021 · Tags: endbasic, programming, rust
Continue reading (about 7 minutes)

EndBASIC 0.5 release announcement

A month has passed since the 0.4.0 announcement so it is about time to say hello to yet another EndBASIC release because 0.5.0 is here! So, what’s new? Not much… unless you look under the covers, in which case a ton has changed. About 30% of the codebase has been affected in one way or another to improve general quality, so read on to see how.

January 24, 2021 · Tags: endbasic, programming, release, rust
Continue reading (about 3 minutes)

EndBASIC 0.4 release announcement

About a month ago and after a long hiatus, I published EndBASIC 0.3 and the adrenaline rush that came with it got my wheels spinning again full-steam ahead. So here I am today, ready to announce the 0.4 release. But… “what could have possibly changed in just a month of someone’s free time”, you wonder? Enough, actually! EndBASIC 0.4 is the release that fulfills my original goal of being able to run a “guess the number” game.

December 25, 2020 · Tags: endbasic, programming, release, rust
Continue reading (about 13 minutes)

Unit-testing a console app (a text editor)

The most notable feature in EndBASIC 0.3 is its new full-screen console-based text editor. In this post, I describe why it is important and useful to unit-test a console app like this, and I will dive into how to implement unit tests that catch regressions and inefficiencies. Code samples are in Rust, but the concepts presented here are applicable to any language with minimal data abstraction facilities.

December 8, 2020 · Tags: endbasic, featured, programming, rust
Continue reading (about 16 minutes)

Using the builder pattern to define test scenarios

I’ve been playing with the builder patter to express test scenarios in a succinct and declarative manner. I’ve liked the outcome and feel that this design can yield to pretty good test code, so I’ll dig through this idea here. Note that, while this post and the associated code talk about Rust, the ideas presented here apply to any language. So don’t leave just because I said Rust!

December 4, 2020 · Tags: endbasic, programming, rust
Continue reading (about 6 minutes)

EndBASIC 0.3 is here

After a 6-month long hiatus caused by me hunting and changing jobs and cities, I am pleased to announce the release of EndBASIC 0.3! The Thanksgiving break has been as fruitful as I had hoped 😁 There are two major changes in this release. The first is the official debut of the web-based interface. I introduced this months ago and have had it running on a “push on green” model, which means that the web deployment of EndBASIC is always tracking Git HEAD.

November 29, 2020 · Tags: endbasic, programming, release, rust
Continue reading (about 2 minutes)

Bridging the web gap in EndBASIC

After a ton of work, a lot of which was unexpected, I am ecstatic to announce that EndBASIC is now a reality on the web! The whole language interpreter can now run as a fully client-side web app on a computer, on a tablet… and even on a phone. Yes: the whole thing, which is written in Rust (94%), works in a modern browser with just a tiny bit of JavaScript glue (1%).

May 30, 2020 · Tags: endbasic, programming, rust
Continue reading (about 7 minutes)

EndBASIC 0.2.0 is here

A couple of weeks ago, I announced EndBASIC: a simple BASIC language interpreter written in Rust with a goal to provide an environment for teaching my kids how to code. That first release provided what-I-think-is a robust interpreter, but that was about it: the language features were still minimal and the interactive features were non-existent. Well, EndBASIC 0.2.0 is here and things are changing! It’s still far from the vision I want to reach, but it’s slowly moving towards that direction.

May 7, 2020 · Tags: endbasic, programming, release, rust
Continue reading (about 6 minutes)

What is Rust's Into<T> for?

Rust provides a bunch of traits that you may use or implement in your code, but unless you have experienced them first-hand, it can be hard to imagine what their real utility is. For example, if you go read Into’s documentation, all you find is: Trait std::convert::Into A value-to-value conversion that consumes the input value. The opposite of From. […] Yay, very useful. This text tells me what this trait does, which is fine for a reference manual, but not when I could find it useful.

April 27, 2020 · Tags: programming, rust, sandboxfs
Continue reading (about 4 minutes)

Hello, EndBASIC!

Introducing EndBASIC, a new interpreter for a BASIC-like language that is inspired by Amstrad’s Locomotive BASIC 1.1 and Microsoft’s QuickBASIC 4.5. Like the former, EndBASIC intends to provide an interactive environment that seamlessly merges coding with immediate visual feedback. Like the latter, EndBASIC offers higher-level programming constructs and strong typing. The main idea behind EndBASIC is to provide a playground for learning the foundations of programming in a simplified environment.

April 22, 2020 · Tags: endbasic, featured, programming, release, rust
Continue reading (about 3 minutes)

The OSXFUSE, hard links, and dladdr puzzle

Hello everyone and welcome to this new decade! It’s already 2020 and I’m only 17 days late in writing a first post. I was planning to start with an opinion article, but as its draft is taking longer than I wanted… I’ll present you the story of a recent crazy bug that has kept me busy for the last couple of days. Java crashes with Bazel and sandboxfs On a machine running macOS Catalina, install sandboxfs and build Bazel with sandboxfs enabled, like this:

January 17, 2020 · Tags: bazel, fuse, internals, programming, sandboxfs
Continue reading (about 13 minutes)

Resurrected ONLamp.com articles

Quite some time ago, I wrote a handful of guest posts for O’Reilly’s ONLamp.com online publication. Unfortunately, that site seems now gone from the interwebs and I only noticed by chance upon realizing that some of my links to those articles were now broken. Fortunately, I was able to find copies of those articles via archive.org’s WayBack Machine. So I have now taken the chance to import those articles into this site.

October 11, 2019 · Tags: articles, programming
Continue reading (about 1 minute)

Sample REST interface in Rust and Go

Over the summer, I prototyped a bunch of web apps whose ideas had been floating in my mind for a long time. I spent some time reading through REST API documentation pages and, as part of these exercises, implemented sample RESTful web services in both Go and Rust. (Just for context, the last time I wrote a web app was in high school… and it involved PHP, MySQL, and I think IE6?

September 27, 2019 · Tags: featured, programming, rust, webapp
Continue reading (about 16 minutes)

Safely restoring the previous working directory

The current working directory, or CWD for short, is a process-wide property. It is good practice to treat the CWD as read-only because it is essentially global state: if you change the CWD of your process at any point, any relative paths you might have stored in memory1 will stop working. I learned this first many years ago when using the Boost.Filesystem library: I could not find a function to change the CWD and that was very much intentional for this reason.

September 21, 2019 · Tags: programming, unix
Continue reading (about 3 minutes)

The fallacy of forbidding assertions

There are two ways to handle abnormal conditions in a program: errors and assertions. Errors are a controlled mechanism by which the program propagates details about a faulty condition up the call chain—be it with explicit error return statements or with exceptions. Errors must be used to validate all conditions that might be possible but aren’t valid given the context. Examples include: sanitizing any kind of input (as provided by the user or incoming from the network), and handling error codes from system calls or libraries.

July 24, 2018 · Tags: programming, reliability, sre
Continue reading (about 5 minutes)

Rust vs. Go

There is no good answer to this question: people tend to put Go and Rust in the same bucket because they were released at around the same time, because Rust’s release felt like a response to Go’s, and because they are marketed to similar audiences. They are, however, vastly different. So let’s give in and compare them anyway.

July 13, 2018 · Tags: featured, go, programming, rust, sandboxfs
Continue reading (about 13 minutes)

Rust review: Closing thoughts

Thought that the Rust review was over? Think again; I was just on vacation! I’m back now to conclude the series with a bunch of random thoughts and a surprise follow-up post. The series is coming to an end. It’s time to summarize everything we have discussed so far and to cover a few more items that didn’t really deserve full posts of their own. Most of these miscellaneous items were thoughts that I jotted down while reading TRPL book.

July 10, 2018 · Tags: programming, rust
Continue reading (about 5 minutes)

Rust review: The ecosystem

In this part of the review, I would like to focus on Rust’s ecosystem: in other words, how Rust plays with other parts of a functioning system and how Rust’s standard library vs. external libraries interact with each other. There are a lot of pieces to cover in these areas and they have left me with mixed feelings. Let’s look at some. The standard library The std library feels generally well-thought out and full of features.

June 22, 2018 · Tags: programming, rust
Continue reading (about 4 minutes)

Rust review: The book

“The Rust Programming Language” is one of the free books that the community has put together to teach the language. The book does a good job in general, but there are some things that could be better. Let’s cover these, but first, some background. A couple of years ago, right after getting started with Rust, I tried to go through the book’s first few chapters. It all sounded cool… but the first edition of the book moved at a glacially slow pace because it covered things in excruciating detail.

June 19, 2018 · Tags: programming, rust
Continue reading (about 4 minutes)

Rust review: The match keyword

A commonly-acclaimed feature of Rust is its match keyword: a “conditional on steroids”. match lets you take the value of an expression and compare it against a bunch of values—or, more generally, patterns. As you write and read Rust, you will notice that this keyword is used everywhere because it’s the way to access certain types, like Option values or error codes. For example: match node.get_parent() { // node is an Option<Something>.

June 15, 2018 · Tags: programming, rust
Continue reading (about 3 minutes)

Rust review: Expressions, expressions, expressions

Rust resembles a functional language in many ways although it does not claim to be one. In fact, I have been thinking of Rust as a “pragmatic Haskell” or as a “well-balanced mixture between C++ and Haskell”. One of the ways the functional aspects show up is via expressions and how pretty much any construct in Rust can be treated as an expression. But before we begin, a little warning: the examples below are, by no means, idiomatic Rust—I just hope they are simple enough to illustrate what I want to show.

June 12, 2018 · Tags: programming, rust
Continue reading (about 4 minutes)

Rust review: Learning curve

Writing Rust code is not restricted to programming gurus—but there is no denying that the learning curve is steeper than that of other languages. Or is it? In this post, I’ll try to convince you that the curve does feel steep, but it isn’t when taken into perspective. Let’s first start by stating that learning a language is not the same as learning its syntax. Learning a language involves learning the syntax, of course, but it also involves familiarizing oneself with its common idioms and grabbing a good sense of what the standard libraries provide.

June 8, 2018 · Tags: programming, rust
Continue reading (about 4 minutes)

Rust review: Protect the data

The one thing that blew my mind about Rust is its approach to data sharing in concurrent situations. I had always thought of mutexes as something that is easy to get wrong and was convinced that the use of a RAII pattern to prevent lock leaks never happen (like with Abseil’s MutexLock) was the panacea. (I’m a fan of RAII in C++ by the way, in case you haven’t noticed.)

June 5, 2018 · Tags: programming, rust, sandboxfs
Continue reading (about 5 minutes)

Rust review: The borrow checker

Aaaah, the borrow checker: the dreaded enemy lurking within the Rust compiler, ready to make its move to bring pain to your life by preventing your code from compiling. Or that’s what everyone seems to say, which is one of the reasons I put off learning Rust for so long. In reality… the borrow checker is a blessing, but it is true that getting past its gates is difficult at first.

June 1, 2018 · Tags: programming, rust, sandboxfs
Continue reading (about 3 minutes)

Rust review: Immutable by default

Let’s start the deep dive by looking into a powerful feature of Rust: all variables and references are immutable by default unless qualified with mut. To understand why this is important, let’s cover some context first. One of my pet peeves when reviewing C++ code is to ask authors to sprinkle the const qualifier everywhere: if something ain’t mutated, say so explicitly. This includes marking local variables, function arguments, function return values, class attributes, etc.

May 29, 2018 · Tags: programming, rust
Continue reading (about 3 minutes)

Rust review: Introduction

I had been meaning to learn Rust since I first toyed with Go a couple of years ago. During this period, I’ve written a non-trivial amount of Go code both inside and outside Google, but never found the chance to sit back and learn Rust. This changed a month ago during my yearly family trip to Korea. This time around, I decided upfront that I would not work on any personal or work projects for the 2-week long vacation.

May 25, 2018 · Tags: programming, rust, sandboxfs
Continue reading (about 3 minutes)

#! /usr/bin/env considered harmful

Many programming guides recommend to begin scripts with the #! /usr/bin/env shebang in order to to automatically locate the necessary interpreter. For example, for a Python script you would use #! /usr/bin/env python, and then the saying goes, the script would “just work” on any machine with Python installed. The reason for this recommendation is that /usr/bin/env python will search the PATH for a program called python and execute the first one found… and that usually works fine on one’s own machine.

September 14, 2016 · Tags: featured, portability, programming, scripts, unix
Continue reading (about 5 minutes)

Making NetBSD Multiboot-Compatible

This article first appeared on this date in O’Reilly’s ONLamp.com online publication. The content was deleted sometime in 2019 but I was lucky enough to find a copy in the WayBack Machine. I reformatted the text to fit the style of this site and fixed broken links, but otherwise the content is a verbatim reproduction of what was originally published. The i386 architecture is full of cruft required to maintain compatibility with old machines that go back as far as the 8086 series.

March 1, 2007 · Tags: featured, netbsd, onlamp, os, programming
Continue reading (about 13 minutes)

Smart Pointers in C++

This article first appeared on this date in O’Reilly’s ONLamp.com online publication. The content was deleted sometime in 2019 but I was lucky enough to find a copy in the WayBack Machine. I reformatted the text to fit the style of this site and fixed broken links, but otherwise the content is a verbatim reproduction of what was originally published. C++, with its complex and complete syntax, is a very versatile language.

May 4, 2006 · Tags: cxx, featured, onlamp, programming
Continue reading (about 17 minutes)

Making Packager-Friendly Software (part 2)

This article first appeared on this date in O’Reilly’s ONLamp.com online publication. The content was deleted sometime in 2019 but I was lucky enough to find a copy in the WayBack Machine. I reformatted the text to fit the style of this site and fixed broken links, but otherwise the content is a verbatim reproduction of what was originally published. My previous article, Making Packager-Friendly Software (part 1), explains why software packaging is sometimes problematic due to real problems in the mainstream sources.

April 28, 2005 · Tags: featured, netbsd, onlamp, programming, unix
Continue reading (about 15 minutes)

Making Packager-Friendly Software (part 1)

This article first appeared on this date in O’Reilly’s ONLamp.com online publication. The content was deleted sometime in 2019 but I was lucky enough to find a copy in the WayBack Machine. I reformatted the text to fit the style of this site and fixed broken links, but otherwise the content is a verbatim reproduction of what was originally published. A package maintainer, or packager, is a person who creates packages for software projects.

March 31, 2005 · Tags: featured, netbsd, onlamp, programming, unix
Continue reading (about 20 minutes)