Simply Jonathan

Note Archive

CTO

On 1 November I got a new job. Again.

I’m back at GreenMobility, this time as CTO.

This obviously marks a big shift for me. It was only in August, joining GAN Integrity, that I transitioned out of being an individual contributor to being a manager, and now I’m also an executive.

This means I’m now working at a higher strategic level than before, something I relish. The first few months have been eventful. We’ve seen our biggest competitor announced their plan to leave our main market and announced our own decision to focus even more on that same market, while keeping pace on releasing new features.

It’s new and it’s different and it’s exciting. I believe as much in the vision as I ever have, and look forward to once again playing a part in improving the prospect for more people foregoing private car ownership and using a more communal alternative.

Joining GAN Integrity

On Monday, 1 August 2023, I joined GAN Integrity as a tech lead.

GAN Integrity are certainly not a household name, but are a leading global provider of compliance software to large enterprises.

For me this also marks a change, not just in employer but also in job description: This will be my first entry into management. This is something I’ve been looking actively for for quite a while, and I’m really happy to be taking that on at GAN.

Chelsea’s squad woes

After the defeat against Arsenal yesterday, a lot of people have been quick to point out the passiveness of the squad. I stumbled upon Jonathan Wilson’s post-match write-up in the Guardian.

Wilson makes a fine point about the mismatch of the squad of players and the manager. Some of it is a little lazy I think – declaring that David Luiz and Azpilicueta are emphatically 3-at-the-back players is a bit of an easy point to make in hindsight, when only one manager has ever played either of them in such a system – but a lot of Chelsea’s players do seem better suited to a 3-4-3, and it is certainly the case that Chelsea have been performing poorly for far too long now.

Sarri-ball is thrilling to watch when well-implemented, but the constant changes in managers – and, more importantly, mangers’ playing style – at Chelsea make it difficult to assemble a squad that can carry a playing style out. As Wilson says, ‘Chelsea’s squad has actually over the years proved remarkably accommodating to change, at times seems almost to have thrived on chaos’, but it seems it may have finally started to buckle.

I like Sarri’s style, and I hope he can get Chelsea playing that way. But if he’s having a hard time motivating this group of players, maybe he should have a look at his available alternatives.

Checking for missing migrations in Django

Back in the day, Django didn’t have a built-in way to change model schemas. You either had to figure out and apply the changes yourself or use a third party tool like South.

After a successful Kickstarter campaign, Andrew Godwin, Django core member and the author of South, added a native migration tool to Django. It solved problems such as conflicting merge names and the ability to squash migrations once there are too many of them in an app.

One thing it also changed is introduce what I have dubbed ‘cosmetic migrations’: these are migrations that make no changes to the database schema, but only add internal Django changes, such as changing a field’s choices or the ordering of a model. I’m sure the change is for good reason, but it annoys me to no end, because the lack of schema impact means I’m unlikely to notice that I haven’t made them until at some point I do make a schema-altering change, and that migration is then flooded with an untold number of cosmetic changes. This is a problem because commits should be atomic.

Django will occasionally notify you that ‘[y]our models have changes that are not yet reflected in a migration’, but I found that I would only see those when it was too late.

The solution

Thankfully, it is possible to make these checks yourself, although I have never seen it advertised anywhere. Executing this command will give your what you need:

$ python manage.py makemigrations --check

This command seems wholly counter-intuitive to me, but it does what I want: Exit with a code 1 if there are unreflected changes.

You can plug the above in to your Continuous Integration system or possibly a pre-commit hook. If you do so, I recommend that you also make it --dry-run, like so:

$ python manage.py makemigrations --check --dry-run

This will ensure that no migrations are actually created, which just seems the saner option if you want to check.

What’s the Cheapest Empty Iterable in Python?

From the department of ‘optimisations that are so premature that if you ever find yourself actually caring about it, you need to find better problems to solve’, I recently had this thought: What’s the cheapest/fastest iterable in Python?

Reminder: iterable and iterator are not the same thing.

The need for an empty iterable occasionally comes up, like when you need to provide a default value to a missing key in a dictionary, and you need it to be something you can iterate over without running the risk of a TypeError. The beautiful thing, of course, is that you can iterate over an empty iterable and just have nothing happen, so the actual type or contents don’t matter.

So I set out to test it. Again: you should never need to actually care about this. If you can live with the actual overhead of iterating over something, you can live with the overhead if that something is empty, no matter the actual type of iterable.

I evaluated strings, lists, tuples, dictionaries and sets. My hypothesis was that the fastest would be a string or maybe a tuple.

The test was performed on a late-2016 13″ MacBook Pro with a 3.3 GHz Intel Core i7 and I timed it using the timeit module.

First I tested out simply declaring the different types of iterables:

kweli:~ j$ python -m timeit -c '""'
100000000 loops, best of 3: 0.00672 usec per loop
kweli:~ j$ python -m timeit -c '[]'
100000000 loops, best of 3: 0.0187 usec per loop
kweli:~ j$ python -m timeit -c '()'
100000000 loops, best of 3: 0.0119 usec per loop
kweli:~ j$ python -m timeit -c '{}'
10000000 loops, best of 3: 0.0305 usec per loop
kweli:~ j$ python -m timeit -c 'set()'
10000000 loops, best of 3: 0.0924 usec per loop

So far so good: strings are the fastest, followed by tuples and dicts, with sets trailing far behind.

Then to actually iterating over them:

kweli:~ j$ python -m timeit -c 'for i in "": pass'
10000000 loops, best of 3: 0.0433 usec per loop
kweli:~ j$ python -m timeit -c 'for i in []: pass'
10000000 loops, best of 3: 0.0514 usec per loop
kweli:~ j$ python -m timeit -c 'for i in (): pass'
10000000 loops, best of 3: 0.0438 usec per loop
kweli:~ j$ python -m timeit -c 'for i in {}: pass'
10000000 loops, best of 3: 0.0707 usec per loop
kweli:~ j$ python -m timeit -c 'for i in set(): pass'
10000000 loops, best of 3: 0.136 usec per loop

And again, the hypothesis is confirmed, but interestingly the difference between lists and strings/tuples is much smaller when iterating compared to just declaring.

So in conclusion, use a string as an empty iterable, unless you have any reason at all not to. The difference is infinitesimal.

Two cultures

I was in New York in February, where it was unseasonably warm. So warm that you could see stuff like this in Prospect Park:

A sign that reads 'Danger: Thin Ice' in front of a completely non-frozen lake

Thin ice indeed

Yesterday I was out walking around the lake Damhussøen in my native Copenhagen. Here it is unseasonably cold for March (although not in the what-the-fuck-it’s-68°f-in-New-York-in-February category), and the lake is completely frozen:

A completely frozen lake, complete with a tree branch comfortably nestled on it; no signposts

But in Denmark, you’re on your own. To be fair, based on tracks we saw, it seems that people could actually walk on Damhussøen, though I doubt it’s something anyone would recommend.

International media are obsessed with FC Midtjylland

I am dumbfounded of the international media’s obsession with Danish football club FC Midtjylland. The latest is a story in The Set Pieces about defensive midfielder Tim Sparv, but previously The Guardian, De Correspondent and Outside of the Boot have also covered them.

I mean, sure, Midtjylland have an owner – Matthew Benham – whose Smartodds system is apparently a revolutionary way to assess football players. But Benham is English and owns Championship club Brentford too; surely they would make more sense to write about, and easier to get to too, at least for the English media?

And it’s not as though Midtjylland’s approach has been an out-and-out success. Aside from the aforementioned Sparv and a few others, their signings have been unimpressive since Benham’s takeover, and an amusingly large portion of them have grown up in the peninsula of Jutland, where Midtjylland are based. They signed a clearly over-the-hill Rafael van der Vaart, who has been ineffective in the few games he’s been picked this season. They did win the championship – the first in their history – in Benham’s first season (2014/15), but the season before that they finished second (and were top for a long time) and in the seasons since they haven’t really been in contention, finishing 3rd and 4th, 12 and a whopping 30 points after champions FC Copenhagen respectively.

None of this is too damning; Copenhagen have been magnificent, especially in this season, and they have a far larger budget than the rest of the league, so finishing behind them is to be expected.

As far as signing local players goes, it is certainly admirable, and every club in the world signs players who don’t work out. It is also a common tendency for sports directors in clubs in smaller footballing nations to sign players who on paper are impressive signings (like van der Vaart), but who are only available because they’re very much past their best.

But the promise of Midtjylland’s system is they would be insulated from such shortcomings, finding players who actually perform, from all over Europe, not just well-performing players from smaller clubs in nearby leagues or fringe players from bigger clubs.

And in light of all of this, I continue to be amazed at why media outside Denmark care. Midtjylland talk a big talk, but they’re a football club with the same problems as any other club in their position, and they certainly haven’t found the holy grail with their analytical approach.

Ras Kass & RZA – The end

My metaphors are meta-fives.

Change

Change, shit
I guess change is good for any of us

– Tupac Shakur

Yesterday, I returned from NIPS 2016. It’s the world’s preeminent machine learning conference.

What was I doing there? To be fair, it was probably not the conference I would have picked, but it was a very interesting conference to attend (the first of its kind I’ve ever been to, to boot). The reason I was there was because on 1 November I started a new job, working for Danish startup Sportcaster. This also means that after almost four years, I have left PDC, where I started working when Ovivo was acquired. (I realise I’ve been horrible at updating the blog with this information, but better late than never, I suppose.)

Working for PDC has been a great experience. I’ve felt welcome in all my years there, even though I got into the company by untraditional means, and even though – as I have joked many times over the years – I would never have been able to land a job there by sending a regular application. (The company values educational credentials very highly, so my B.A. in English and Communication & Rhetoric is basically useless as an engineer.) I would encourage anyone wanting to work with Microsoft technologies or, especially, Prolog in Copenhagen to take a look PDC’s way, it’s a great place to work.

For me, however, Sportcaster presented the complete package: The company’s goal is making a product aimed at filming grassroots association football, and I will be doing their web platform. This allows me to combine my interest (OK, let’s just call it ‘obsession’) with football as well as doing web development in Python. If someone had asked me what I wanted to do that would basically have been it.

My first month there has been excellent, and I look forward to spending a long time there, and I’ll try to make an effort updating this space with news of development.

Mediany

Tonight I’ve published Mediany, a small JavaScript library I’ve been working on. It’s released under the MIT License.

Mediany allows you to declare behaviour at different media query breakpoints. This allows you to e.g. have one thing happen when a button is clicked at one screen size, and something else (or something additional) happen when it is clicked at another screen size.

I built this to scratch my own itch. With responsive web design, it has become customary to transform the design based on the screen size of the user’s viewport – rearrange elements into columns, show things that were previously hidden, etc. (Media queries have a great many additional things to check for, but checking screen size – and width in particular – is the most common use case.)

As one transforms the design to fit larger sizes, I found that I also need to modify the behaviour. Clicking a button might require some set of changes at a small size, and something else entirely at a larger screen size. Mediany helps this process by declaring behaviour at specific media queries.

What’s in a name

I initially wanted to name the library responsive.js, because my research back then had indicated that was an unused name. As it turns out, it isn’t.

I still think responsive.js would be a great name for it. It is, in my estimation, the JavaScript library I’ve seen that comes closest to the principles of Responsive Web Design. There are a lot of libraries that will allow a mix of dynamic rendering (see aforementioned responsive.js project) and more complex break point handling. What I wanted was very simple: When a media query is true, perform this behaviour. I don’t want to handle the transition between two queries, and indeed I point people towards BreakJS for that functionality, I just want simple, declarative behaviour.

Developing a library

This is the first JavaScript library I’ve ever published. A lot of best practices were new to me (and I might indeed have missed many). I settled for a very conservative behaviour: there is no ES6-style encapsulation, only a simple bootstrapping function and one intended-for-public-consumption function: mediany.

It was also the development of Mediany that had my thinking so much about mustard. In the end, after a back and forth with Jeremy Keith, I settled for checking for features I reasonably expect aren’t present, but not all (Object.prototype.hasOwnProperty and Array.prototype.push not being feature-checked, although I technically could do it).

Mediany is available on npm, and I welcome any feedback.

This is Simply Jonathan, a blog written by Jonathan Holst. It's mostly about technical topics (and mainly the Web at that), but an occasional post on clothing, sports, and general personal life topics can be found.

Jonathan Holst is a programmer, language enthusiast, sports fan, and appreciator of good design, living in Copenhagen, Denmark, Europe. He is also someone pretentious enough to call himself the 'author' of a blog. And talk about himself in the third person.