Core Python

When I describe my programming background these days, I say that I code “primarily in Python, JavaScript, Clojure, C… and Zig!” I put Python first in that list for good reason.

This is a post about the core Python language, but also the ways in which Python is evolving its single-core and multi-core CPU performance.

Python has been my go-to programming tool for a long time. When I started to build out my last startup and shipped the production core of its product, Python 2.7 had just stabilized, creating an excellent “core language.” This is a language that I truly respected, as evidenced by my style guide. And, as I discussed in my Python technical book review round-up, this core language was best described by David Beazley in the first half of his Python Essential Reference book, which was also turned into an excellent standalone volume (which includes Python 3.x coverage), Python Distilled.

Many, many useful open source projects, companies, and projects were built atop that Python 2.7 core foundation of a language. Its community truly flourished.

Continue reading Core Python

Putting Your Media on a Diet

When you type an address into your web browser and are brought to a web server, a lot of decentralized magic happens within the span of a few seconds. Through the web, we have an infinite media available to us.

It as though you have a beautifully-maintained bookshelf and run your finger along the spines of the books, and then pluck out the one you want. But the sci-fi part, which is more science than fiction today, is that the bookshelf has millions of virtual entries and the information you want is delivered to you instantaneously. Once this virtual book is delivered (once a website is loaded), it can be frequently refreshed with real-time updates, and it exists in a form that can be navigated, searched, read, spoken, heard, shared, saved-for-later, or even automatically analyzed and summarized.

This is a lot of power for each individual to wield.

That is a lot of text to choose from, with which you can train your brain.

And that is even if you put aside the world of paid digital books via Amazon’s empire of Kindle. By the way, this Amazon empire need not cost money to you in the US, as you can often gain (adequate) free access to it via your local library on the Libby app.

So, one thing is for sure: there are a lot of words to choose from when deciding what to read. But this also means that an individual faces a paradox of choice when they click into that blank address bar in their browser.

Will they, like so many others, ignore the address bar and the browser altogether? That is, despite having the “infinite bookshelf” at their fingertips, will they, instead, hit an app shortcut to one of the major passive content delivery platforms, like Facebook, YouTube, Instagram, or TikTok?

Recent research from Pew suggests that major passive-consumption mobile apps are used by a majority of Americans, and, what’s more, that usage of the most video-forward of these (YouTube, Instagram, and TikTok) is nearly universal among people 18-29 years old. As for teens, 9 out of 10 of them are online (presumably via smartphones) every single day, and nearly 5 out of 10 are online “almost constantly.” This comes from a 2023 report.

If you read between the lines of these two reports, what comes into a focus is a culture of individuals addicted to video streaming devices in their pocket, filling inevitable moments of boredom with hastily- and cheaply-produced sights and sounds, rather than retreating to the world of written words. And, unsurprisingly, people are reading less.

Continue reading Putting Your Media on a Diet

The Blog Chill

The film The Big Chill came out a bit before I was born, over 40 years ago, in 1983. The plot focuses on a group of middle-aged friends, perhaps in their late 30s and early 40s, who had attended the University of Michigan – Ann Arbor together. They reunite after 15 years, brought together by the tragedy and the funeral of their friend, Alex, who, we learn in the film’s opening, died by suicide.

The “big chill” of the title can be interpreted a few different ways. The numbing loss of the innocence of youth. The cold realization of the quotidian nature of adulthood. Or, the wintry blast of mortality, which comes as a shock to this group of old college friends, who had become used to a sort of humdrum comfortable existence, pursuing families and careers, and then being suddenly shaken out of it by the sad news of their old friend Alex’s passing.

There is a historical and generational aspect to the film, too. The college years, for this group, were the 1960s. A time of great idealism in the US. The counter-culture was the culture. They weren’t supposed to end up like their parents. But then they found themselves in the 1980s, yuppies of exactly the sort they feared they’d become.

One of the interesting aspects of watching this film today is that, being set in the 1980s, it lacks altogether the technopoly we see in our current lives in the 2020s. There are no smartphones nor social media, to be sure, but, what’s more, there is no computing or internet either.

Continue reading The Blog Chill

Dependency rejection

Sam Altman once said: “Minimize your own cognitive load from distracting things that don’t really matter. It’s hard to overstate how important this is, and how bad most are at it. Get rid of distractions in your life. Develop very strong ways to avoid letting crap pile up.”

In programming, there is a technique called “dependency injection.” It’s a way of worrying, up front, about how to split the modules in your program from other code. You aim to give yourself the future benefit of being able to swap out a module dependency later.

In some communities, this little technique led to a temporary fad of constructing programs within a baroque superstructure via “dependency injection frameworks,” sometimes called “inversion of control frameworks.” With these, programmers fretted about a future that usually never arrived, and their worries expressed themselves as defensive code, all in the name of future-proofing. This meant in addition to spending time adopting a dependency, they also had a meta-distraction: working that dependency into their “management framework,” alongside the others. This sort of thing took some programmers very far away from the core “essential complexity” at the heart of their code.1

Dependencies seem to be all around us, both in the real world, and in programming. And they are perniciously distracting in just this way. Have you ever noticed how rare it is for you to just do something?

If so, you might have been worrying, up front, about dependencies.2

In the back of your mind, you wonder: has this been solved? The world is full of solutions in search of problems, and the internet is always nearby. You convince yourself to research if some of these happen to apply to your problem.

Even if you don’t find something off-the-shelf, you still might think to yourself: I could just do this, but is this a good use of my time? Lacking a ready-made solution, you then turn to delegation: whom shall I ask to solve this? After all, the market usually obliges with eager participants willing to sell their labor for a price.

But whether your proposed solution is an object or a person (and whether it is free or paid), there’s one thing it always is: a dependency.

Continue reading Dependency rejection

Over-Organization (1958)

This section of Brave New World Revisited, a long essay by Aldous Huxley reflecting on his own novel many years after its publication, can be found on Project Gutenberg Canada; if you enjoy it, I recommend you purchase Brave New World & Brave New World Revisited, which includes the original novel (1932) and Huxley’s essay (1958), along with a wonderful foreword by Christopher Hitchens (2003), published by Harper Collins here.

As a computer programmer and software entrepreneur, I like to make order from chaos. But, as Huxley argues quite well in this section entitled “Over-Organization” in his essay, a little too much order may be at odds with a very human freedom.

Though written over sixty years ago, and though reflecting on a future technocratic world state originally envisaged in the author’s mind nearly a century ago, this excerpt feels unbelievably modern when read from a 2020s vantage point. And yet, Huxley was writing during the heyday of mid-20th-century industrialization, but right before the beginning of the information age and the rise of pervasive computing. As a result, he couldn’t foresee the new forms of “over-organization” we’d face after the digitization of everything.

In Huxley’s fiction, he predicted that the systematization of daily life would eventually arise from a combination of state power and genetic technology. But in his non-fiction analysis of modern times, he recognized that it would most rapidly arise from corporate power and a general advancement of industrial technology. This we have witnessed in the decades since his passing.

We who work in software and who see a certain beauty in large systems and the organizational models they enable should, perhaps, take a moment to reflect on humanity’s deepest fact: that each human being is unique, and we are only truly happy when there is individual freedom of thought and action.

The rest of this post is Huxley in his own words. Please enjoy Huxley’s thoughts on “over-organization” below.

Continue reading Over-Organization (1958)

How Python programmers can uncontroversially approach build, dependency, and packaging tooling (+ a note on Zig)

A few years back, I published The Elements of Python Style, a popular Python code style guide. Since publishing it, friends of mine in the Python community have wondered if I might consider adding a section about package installation, dependency management, and other similar “standard tooling” recommendations.

This is a reasonable request, since Python lacks much in the way of standard tooling. I took a stab at this in a pull request here, but then abandoned my attempt. The length of this “section” started to approach the length of the overall style guide itself! So, I gave up on that. I decided to turn the section into this blog post here, instead. Then, I’ll share one thought about how emerging programming language communities, such as Zig’s, could learn from the Python experience.

On “Standard” Tools

There’s a zoo of tooling options out there, and no “standard” Python tooling beyond the python executable, and, perhaps, pip (for installing packages, which was semi-formalized in Python 3.x with PEP 453 and PEP 508). Here, we’ll discuss an opinionated (yet uncontroversial) approach to “standard” tooling with Python.

Continue reading How Python programmers can uncontroversially approach build, dependency, and packaging tooling (+ a note on Zig)

Turning n/2 + 1

When I turned 27, I wrote the following in my birthday post:

I don’t need stuff. I just need time. Of course, that’s the bittersweet part of one’s birthday. That even as you come to realize the importance of time, the day acts as a reminder of how our time on this earth is limited. 1 day passes, and only n-1 left to make a difference.

The average life expectancy for a US male born in 1984 is 75. I just turned 38 today. Therefore, it’s fair to say, I just turned n/2 + 1.

That is perhaps a bit too fatalistic and reductive. The number n is not guaranteed to be 75. “Don’t be so morbid!” someone might exclaim to me. “After all, many people live to 80, 90, even 100. And medicine improves all the time.”

Well, yes, this is true. But, it’s also likely — and increasingly so — that I might die any minute. Freak accidents, a late-discovered birth defect. Or, just losing the medical lottery in middle age. So, I return to the wisdom of my youth: “I don’t need stuff. I just need time.”

But, toward what end? That has been the interesting riddle of approaching n/2 with the following undeniable privileges:

  • good health
  • professional satisfaction
  • financial security
  • confidence in my irreversible life choices

Many approach this same milestone with none of the above, and many would love for any one of them to be squared away.

The honest truth is, I find myself heavy with the weight of these privileges. History is, as Harold Bloom once put it when describing literature, “a conflict between past genius and present aspiration, in which the prize is […] survival.” Here, he was referring to well-crafted stories. “Survival” meant their perpetuation through the ages via timeless literary relevance, something he referred to as “canonical inclusion”.

But what of my field, software?

Continue reading Turning n/2 + 1

Parse.ly, Automattic: the long view

In 2009, I quit my first programming job after college to work on a startup. That startup eventually became Parse.ly. I’ve written about Parse.ly’s startup beginnings and evolution elsewhere on this blog, including:

It is 2021 now, more than 12 years since the company’s original founding. And much has changed.

Parse.ly “the startup” was a rollercoaster, like all startups are, but it was, ultimately, a success. In 2009, we were a tiny 3-person team hacking away on prototypes at a startup accelarator in Philadelphia. In 2012, Parse.ly had its first handful of customers for the content analytics system that became our core product, and shifted into enterprise SaaS as a business model. In 2013, we raised “Series A” style financing to pursue the ambition of defining and leading the content analytics category.

By 2017, it was clear that Parse.ly had done just that: we had built a valuable product in the market and a beautiful SaaS business model, where our R&D efforts were aligned with our customer needs. There was only a question of total market size. As a result, in 2018 we shifted our efforts to expanding Parse.ly’s market — acting as a content measurement layer not just for major media and entertainment companies, but for all content management systems and all content-rich websites.

By the end of 2019 and heading into early 2020, it was clear that Parse.ly was succeeding in this new vision, and was going to be a SaaS company “in it for the long-term”, serving our customers for years to come.

Continue reading Parse.ly, Automattic: the long view

Managing software teams: the definitive reading list

Frederick Brooks once wrote:

The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds castles in the air, from air, creating by exertion of the imagination.

In his classic essay, “No Silver Bullet”, he also wrote about software’s “essential” complexity:

The complexity of software is an essential property […] Hence, descriptions of a software entity that abstract away its complexity often abstract away its essence. For three centuries, mathematics and the physical sciences made great strides by constructing simplified models of complex phenomena, deriving properties from the models, and verifying those properties by experiment. This paradigm worked because the complexities ignored in the models were not the essential properties of the phenomena. It does not work when the complexities are the essence.

It’s therefore no surprise that once a team develops expertise in a technical domain and starts to evolve a product from that foundation, there is still a huge heap of complexity left over.

This is made worse on bigger problems where more people are involved, thanks to Brooks’s Law. In addition to the software’s essential complexity, you also need to navigate the built-in complexity of human communication, and the associated combinatorial explosion of information pathways on growing teams.

Modern software management practices have thus evolved two distinct skillsets for navigating the problems of team coordination around complex software delivery. These two areas are product management and software engineering management.

Product management centers around areas like market positioning, product strategy, and customer-focused iterative development. The product manager, working closely with the engineers, determines the “what”, aligns the team around the “why”, and acts as a liaison to users and the wider market.

Software engineering management focuses on the practice of coordinating teams of programmers in the delivery of high-quality shipped software, often leveraging programming languages, tools, frameworks, cloud services, and lots of open source technology. Pithily, this is “the how”, as well as the art of making informed engineering tradeoffs, e.g. as relates to time-to-market, performance, quality, and cost.

This post will cover some of my favorite reading materials spanning product management and software engineering management, as disciplines. A preview of some of the titles is here:

I have curated these resources carefully, and I have recommended them at various times to my own product managers and my own software engineering managers over the years. I hope you find this a useful starting point for your own study.

Continue reading Managing software teams: the definitive reading list

Learning about babashka (bb), a minimalist Clojure for building CLI tools

A few years back, I wrote Clojonic: Pythonic Clojure, which compares Clojure to Python, and concluded:

My exploration of Clojure so far has made me realize that the languages share surprisingly more in common than I originally thought as an outside observer. Indeed, I think Clojure may be the most “Pythonic” language running on the JVM today (short of Jython, of course).

That said, as that article discussed, Clojure is a very different language than Python. As Rich Hickey, the creator of Clojure, put it in his “A History of Clojure”:

Most developers come to Clojure from Java, JavaScript, Python, Ruby and other OO languages. [… T]he most significant […] problem  [in adopting Clojure] is learning functional programming. Clojure is not multiparadigm, it is FP or nothing. None of the imperative techniques they are used to are available. That said, the language is small and the data structure set evident. Clojure has a reputation for being opinionated, opinionated languages being those that somewhat force a particular development style or strategy, which I will graciously accept as meaning the idioms are clear, and somewhat inescapable.

There is one area in which Clojure and Python seem to have a gulf between them, for a seemingly minor (but, in practice, major) technical reason. Clojure, being a JVM language, inherits the JVM’s slow start-up time, especially for short-lived scripts, as is common for UNIX CLI tools and scripts.

As a result, though Clojure is a relatively popular general purpose programming language — and, indeed, one of the most popular dynamic functional programming languages in existence — it is still notably unpopular for writing quick scripts and commonly-used CLI tools. But, in theory, this needn’t be the case!

Continue reading Learning about babashka (bb), a minimalist Clojure for building CLI tools