week 49, 2021

Should You Use Upper Bound Version Constraints?

Bound version constraints (upper caps) are starting to show up in the Python ecosystem. This is causing real world problems with libraries following this recommendation, and is likely to continue to get worse; this practice does not scale to large numbers of libraries or large numbers of users. In this discussion I would like to explain why always providing an upper limit causes far more harm than good even for true SemVer libraries, why libraries that pin upper limits require more frequent updates rather than less, and why it is not scalable. After reading this, hopefully you will always consider every cap you add, you will know the (few) places where pinning an upper limit is reasonable, and will possibly even avoid using libraries that pin upper limits needlessly until the author updates them to remove these pins.

Source: Should You Use Upper Bound Version Constraints?, an article by Henry Schreiner.

Minimalist Guide to Lossless Compression

Lossless compression is the act of making a dataset smaller than its original form while still being able to transform the compressed version back into the original source material. This contrasts lossy compression which produces a derivative dataset that, while being something humans can appreciate, cannot recreate the original source material.

Source: Minimalist Guide to Lossless Compression, an article by Mark Litwintschik.

Defensive CSS

Defensive CSS is a collection of snippets that can help you in writing CSS that is protected. In other words, you will have fewer issues in the future.

Source: Defensive CSS, an article by Ahmad Shadeed.

Using Haskell as my shell

In the process of switching my shell to Haskell, I also got a lot faster at writing Haskell. Haskell is now the primary interface through which I use my computers, and it has been very pleasant. I no longer have to deal with regexes, since I can whip out a full parser combinator library any time.

Source: Using Haskell as my shell, an article by Las Safin.

Lightweight dependency injection and unit testing

Very often, making code easy to unit test tends to go hand-in-hand with improving that code’s separation of concerns, its state management, and its overall architecture. In general, the more well-abstracted and organized our code is, the easier it tends to be to test it in an automated fashion.

However, in an effort to make code more testable, we can very often find ourselves introducing a ton of new protocols and other kinds of abstractions, and end up making our code significantly more complicated in the process — especially when testing asynchronous code that relies on some form of networking.

But does it really have to be that way? What if we could actually make our code fully testable in a way that doesn’t require us to introduce any new protocols, mocking types, or complicated abstractions? Let’s explore how we could make use of Swift’s new async/await capabilities to make that happen.

Source: Lightweight dependency injection and unit testing using async functions, an article by John Sundell.

Quaternions: Part 1

A common problem in computer animations is rotating an object in fully 3D space. Think objects, spaceships and heroes tumbling and turning in complex sequences. This is usually accomplished with an arcane mathematical object called a quaternion.

Source: Quaternions: Part 1, an article by Lior Sinai.

How to write idempotent Bash scripts

It happens a lot, you write a bash script and half way it exits due an error. You fix the error in your system and run the script again. But half of the steps in your scripts fail immediately because they were already applied to your system. To build resilient systems you need to write software that is idempotent.

Source: How to write idempotent Bash scripts, an article by Fatih Arslan.

How to implement asynchronous requests in your Python code

Traditionally, Python has been a blocking language when it comes to I/O and networking, meaning lines of code are executed one at a time. With network requests, we have to wait for the response before we can make another request. Meanwhile, our computers sit idling. Luckily, there are ways to address this, the most exciting of which is leveraging asynchronous requests with the aiohttp package. This article explains how asynchronicity can help solve these issues – and how you can put it into place within your own code!

Source: Tech spotlight: How to implement asynchronous requests in your Python code, an article by Joseph Perry.

Why your multiprocessing Pool is stuck

You’re using multiprocessing to run some code across multiple processes, and it just—sits there. It’s stuck.

You check CPU usage—nothing happening, it’s not doing any work.

What’s going on?

In many cases you can fix this with a single line of code—skip to the end to try it out—but first, it’s time for a deep-dive into Python brokenness and the pain that is POSIX system programming, using exciting and not very convincing shark-themed metaphors!

Source: Why your multiprocessing Pool is stuck (it’s full of sharks!), an article by Itamar Turner-Trauring.

Branchless Git

One Git usage pattern that I think is underused is the “branchless” workflow. The idea here is pretty intuitive if you’ve used trunk-based development: there’s just one “main” branch that everything gets merged into. No feature branches, no release branches, no hotfix branches.

The “branchless” workflow is, in a nutshell: You work in a stack of atomic commits which are all eventually intended to be merged into a single trunk branch. Each commit can become a pull request, and each pull request consists of a single commit.

Source: Branchless Git, an article by Ben Congdon.

Some indexing best practices

We all know that indexing is important, but it can be difficult to know where to start. In this post, my aim is to collate some of the best advice I’ve seen for indexing Postgres, and simplify it for folks just getting started.

Source: Some indexing best practices, an article by Michael Christofides.

What role do Tasks play within Swift’s concurrency system?

When writing asynchronous code using Swift’s new built-in concurrency system, creating a Task gives us access to a new asynchronous context, in which we’re free to call async-marked APIs, and to perform work in the background.

But besides enabling us to encapsulate a piece of asynchronous code, the Task type also lets us control the way that such code is run, managed, and potentially cancelled.

Source: What role do Tasks play within Swift’s concurrency system?, an article by John Sundell.

The Memory Image Pattern

The Memory Image Pattern (MIP) is a novel approach to application development. It rejects the idea of storing state in a database and gains both developer productivity and run-time performance. If you can fit your application data in memory, MIP might be for you.

Source: The Memory Image Pattern, an article by Axel Svensson.

Tips on Adding JSON Output to Your CLI App

A couple of years ago I wrote a somewhat controversial article on the topic of Bringing the Unix Philosophy to the 21st Century by adding a JSON output option to CLI tools. This allows easier parsing in scripts by using JSON parsing tools like jq, jello, jp, etc. without arcane awk, sed, cut, tr, reverse, etc. incantations.

It was controversial because there seem to be a lot of folks who don’t think writing bespoke parsers for each task is a big deal. Others think JSON is evil. There are strong feelings as can be seen in response to the article in the comments and also on Hacker News and Reddit.

Source: Tips on Adding JSON Output to Your CLI App, an article by Kelly Brazil.