Latest Posts (20 found)

jj sales pitch

A new jj tutorial, summarizing a many of the reasons jj is so useful, and powerful, in just a few paragraphs. jj improves upon Git by achieving two opposing goals at the same time: it has a simpler mental model and command set, but simultaneously provides more powerful functionality. jj simplifies Git not by hiding complexity, but by using a better conceptual model. – Evan’s Jujutsu Tutorial

0 views
Unsung Today

Flickr’s optimistic committing

Somewhere next to optimistic loading and optimistic saving exists another technique to make apps feel faster: optimistic committing. Flickr is a great example. After navigating to photo upload, you enter a sort of a foyer where you can drag in the photos, reorder them, name and tag them, and otherwise prepare them before pressing the big Upload button. But Flickr also optimistically assumes you will press that button, and slowly starts uploading the heavy photos in the background the moment you drag them in. Like all optimistic schemes, being friendlier toward the user complicates things for Flickr’s designers and engineers. After all, there is still a regular upload modal after you do commit to the upload… = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/flickrs-optimistic-committing/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/flickrs-optimistic-committing/2.1600w.avif" type="image/avif"> …so the two states – quiet staging area upload, and the official visible upload – have to be reconciled and kept in sync. Also, optimistic but eventually cancelled uploads have to be cleaned up from the servers. Lastly, there’s signposting. Contrary to lighter optimistic loading schemes, which typically simplify reality by pretending no data transfer is actually happening, the optimistic committing here is actually visible through small indicators: I think this transparency is welcome. In the past, Meta (who else!) got into hot water for abusing optimistic committing : Did you ever record a video on Facebook to post directly to your friend’s wall, only to discard the take and film a new version? You may have thought those embarrassing draft versions were deleted, but Facebook kept a copy. The company is blaming it on a “bug” and swears that it’s going to delete those discarded videos now. They pinkie promise this time. In this context, it’s good that Flickr conveys data is being sent to the servers; I believe this helps with building trust. On top of transparency, I think it’s also good that this process shows the progress of uploading with a lot of precision – not just between files, but also within each file. Internet connection speeds vary so much, not just geographically, but also even situationally, that this is really helpful in practice. There are many moments where auto saving to the cloud needn’t bother the user unless the connection goes offline for a longer while, but this feels like a situation where clarity is better than magic. #details #loading states

0 views

Choosing Movies

Almost surely, if you totaled up the number of hours of movie watching I’ve done and the hours of TV show watching I’ve done, TV dwarves movies. It’s not a conscious choice; just how it shook out for me. Via the internet , I “know” a couple of people who are consciously movie-only. Khoi Vinh does all these movie reviews and has more or less said he’s only got time for movies. Sean Fennessey, host of The Big Picture has said he only watches movies as well. Paraphrasing from what I remember, it’s that TV’s incentives are to make the most of it , not to make the best art possible, which is more aligned with movies. I’d think the budget and talent also favor movies. So why the imbalance in the other direction for me, and maybe a lot of you? Is it the shorter format? Is it designed to hook you in with more digestible structures and cliffhangers to keep us coming back? Is TV traditionally less expensive to have access to? My defense of TV is that there is just more to sink your teeth into. I can feel more for a character I’ve seen for 20 hours than for one I’ve seen for two. Not that I want to defend it. I kinda wish I were more of a movie guy, hours-wise. I love art, and movies are closer to a form of art. I’m going to at least try to be more conscious of my choices. Two nights ago, I watched  Tell No One , a French murder mystery thriller that turned out to be a real banger, and I was quite happy with my choice. Last night I watched The Outrun , with Saoirse Ronan as a recovering alcoholic on some Scottish isle. Very beautiful. The art was oozing out of it. But truth be told, I was so tired, I could tell my dumb brain wasn’t appreciating it fully. I probably should have just watched some shitty episode of Dutton Ranch and gone to bed.

0 views

Apple Sues OpenAI, Apple’s Real Problem

Apple is suing AI for stealing trade secrets; there is one guilty employee, but this mostly feels like lashing out.

0 views

📝 2026-07-13 08:12: Haven't worn this watch for months, but it's such a fun one to wear in...

Haven't worn this watch for months, but it's such a fun one to wear in summer. Beautiful dial and a Seiko movement that will probably outlive me. Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views
Unsung Today

My one (1) Medium secret

When I was at Medium, over a decade ago, I really enjoyed going deep on typography. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/1.1600w.avif" type="image/avif"> People seemed to generally enjoy what we did. Writers really loved automatic em dashes and range dashes, discovered the beauty of hanging punctuation, and as funny as it might sound today, the smart quotes were a huge hit, too. I was proud of the tight drop caps, the underlines brought me some notoriety, and we even supported ligatures at a time when not only this wasn’t the default, but it also had some mildly scary performance consequences. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/4.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/4.1600w.avif" type="image/avif"> But for every two things that worked well, there was also something that in retrospect proved to be me trying too hard, and had to be quickly undone. I was really excited about resurrecting pilcrows , but many users saw them as rendering or escaping errors. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/6.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/6.1600w.avif" type="image/avif"> I briefly added vulgar fractions to all the places where Medium rounded numbers, but that made those numbers confusing and weird in practice. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/7.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/7.1600w.avif" type="image/avif"> (And I already mentioned the strange, rare bug with system fonts , although I suppose there are always bugs.) = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/8.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/8.1600w.avif" type="image/avif"> It was an interesting calibration process. And somewhere in between successes and failures was one thing that I have never mentioned before, and one nobody ever brought up. I recently shared the story of 2015’s typographical redesign of Medium. As we were exploring the candidate typefaces, we fell in love with one in particular: Charter , a font designed by the industry legend Matthew Carter – and no, this is not a bug, Google Search switches to using Carter’s own Verdana to honor him. Charter had this perfect balance of “casual” and “refined” we wanted for Medium at the time. Unsurprisingly, it also came with a bunch of typographical niceties – among them lowercase (old-style) digits, which I really wanted: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/9.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/9.1600w.avif" type="image/avif"> But there was a problem. Those lowercase numerals came with a “medieval 1,” a particular style of a lowercase digit 1 that resembled an uppercase I. People hated it and were confused by it, thinking indeed that a bug caused a letter I to make its way to the numbers. No amount of pleading would get us to push that digit through. The backup plan was going with uppercase numerals, but I hated the idea; those digits felt so ugly and pedestrian to me – they were not just uppercase, but also monospace! It was a frustrating situation, being so close and yet separated from a warm Charter embrace by one glyph that it didn’t happen to have. And so… I drew one. = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/10.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/10.1600w.avif" type="image/avif"> I, someone who has never ever designed a typeface, decided to vandalize Matthew “ The Most Widely Read Man In The World ” Carter’s typeface and plop in a new digit 1 of my own creation. = 3x)" srcset="https://unsung.aresluna.org/_media/my-one-1-medium-secret/11-framed.1600w.avif" type="image/avif"> The internal complaints stopped. Weeks later, we launched the new fonts, Charter front and center, my fresh non-medieval 1 attached. I don’t remember the exact details, but we found a way to do this that was compatible with the font’s licensing – and yet I never talked about it because… well, I think you can understand why. I believe my rogue 1 lasted until a subsequent redesign in 2022, long after I left the company. A decade in, I still don’t know how to feel about it. Did I save Charter as a candidate for Medium by mutilating it a bit, am I writing this post just to launder my own ego, or is this the equivalent of a perp coming back to the scene of the crime? Was I ambitious (laudatory) or ambitious (derogatory)? Maybe you can tell me. But I hope either way it makes for a fun story. #above and beyond #craft #hacks #marcin wichary #typography

0 views
Unsung Today

“Animating something and animating something well are two very different things.”

From Jakub Krehel, a new blog post about self constraint in the era when AI makes it easy to ignore constraints altogether. My caveat is that the post doesn’t fully come together for me – jumping from AI to animations and then back to AI the way the author did does not feel cohesive. At the same time, in the middle of the post, there are some nice examples of animating juxtaposed with overanimating that caught my attention. We talked about sugar and juice before, and this adds to that conversation. Here’s one example: Not all animations need to be wholly meaningful and functional – just like not all graphic design, iconography, and typography have to be – but part of growth as a designer is knowing how to limit your budget of “superfluous” stuff even if no one else tells you to, and then in spending that budget really, really well. #ai #craft #motion design

0 views
DHH Yesterday

The will to power will return

In the 1980s, France started 43 nuclear reactors across 14 sites. On average, each reactor took just seven years to build. Forty years later, all but one of these reactors are still running, and they continue to produce nearly half of France's electricity. Can you imagine France doing something like this today? Or any other country in the West for that matter? The past is a foreign country. But why is this? Why did the West lose the will to power? A popular meme would explain it as the inescapable good-times-hard-times circle: Hard times (WWII) create good men, good men create good times (Les Trente Glorieuses), good times create weak men (The End of History), weak men create hard times (now). The Fourth Turning by Strauss and Howe offers a theory for this wheel of time by tracing the last five centuries to the same four recurring phases: High, Awakening, Unraveling, Crisis. It was the good men of France's hard times who planned the country's incredible nuclear build out. This hero generation, as Strauss and Howe calls them, planted the trees of power that would provide shade for several generations to come. It seems inconceivable to expect similar bold plans and action from the current cohort of the European political establishment. But The Fourth Turning argues this was ever thus. The decline that always sets in once we enter the unraveling phase of the century (or saeculum, as the book calls it) inevitably leads to a crisis. We're on the cusp/in one of those right now. So pessism is perhaps a rational response. And yet, the night is darkest before the dawn, and the current Crisis is likely to lead to another High, if the past five centuries and Strauss and Howe's theory are any guide. If so, we should expect the next hero generation to reject this managed decline of our present turning, and once again taking up the mantle of ambition. The circle of the saeculum is both a prophecy and a roadmap. We're not supposed to live like this forever: weak, ineffectual. This too shall pass. And when it does, once the Crisis becomes another High, we'll marvel at the time wasted, but with the pity due a pathetic period of the past, not from within an eternal prison of decline. We just have to make it out of the current Crisis alive. The last one brought us a total war. Would be nice if we could get back to the High without something quite as devastating, but don't bet on it.

0 views
Kev Quirk Yesterday

📝 2026-07-12 10:08: It's a beautiful morning here in North Wales. My wife has taken our youngest to...

It's a beautiful morning here in North Wales. My wife has taken our youngest to his cricket match, and our oldest is upstairs playing with his Lego out of the heat. Me? I'm sitting in the sunroom, listening to the goats and chickens, with a coffee and book. Perfect Sunday morning. Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views
Playtank Yesterday

Game Design Stages Part 1: Ideation

Part 1 of 6 on the six stages of game design . Back in 2021, I tried to formulate the six stages of game design as I’d observed them. Aspirational more than definitive: I was hoping to solve observable problems through structure. The stages are: The crucial bit of added texture is linearity : once you pass Commitment, you can’t go back to ideation or exploration until your next project. The reason is that I’ve seen so many projects get delayed, made complicated, or even cancelled because designers would simply never stop ideating. Even with a fraction of the schedule remaining, a new idea or a new “what if?” could flop onto the schedule like a severed limb, bleeding on everything from art production to menu flow. This makes it necessary to be specific about what you want from each stage. This six-post series starts with some tools for how to make your ideation productive. You can find more of these tools in my book (linked on the About page), and I’ve kept the overlap between book and post to a minimum. Let’s have ideas! “Ideation: the activity of forming ideas in the mind.” Cambridge Dictionary Few things say game designer quite like having ideas. Even within the profession, we run into the occasional “ideas guy” (it’s usually a guy). But having ideas is the easy part — telling the rest of your team how to execute on them is the hard part. Good ideas are informed, concrete, and practical to communicate. The first and possibly most important element of good ideation is positive communication. Not saying no — never shooting things down. Instead, borrow a page from improvisational theater: the trusted “yes, and …” When someone has an idea, you start by accepting it, and then you build more on top. “What about space ships?” Says the first designer. “Yes! Space ships, and they have like 1,000 people onboard.” This process is not there to give you a finished design, but to let you ideate without anyone feeling shot down or left out. It’s also a good way to train your collaborative communication. It’s not uncommon that your spontaneous “no” comes more easily than your spontaneous “yes,” so exercising your “yes, and …” does real collaborative work with limited effort. The greatest achievement of positive reinforcement like this is that you avoid pushing people into the defensive mindset that often takes over when you say “no” or insist on your own ideas. Gains of “yes, and …”: Indie developer Tomas Sala mentioned this, and I think it’s some of the best advice there is when it comes to ideation: “Lots of young developers want to make what they love. They want to make what they play”, he said. “My first step is get rid of that, because you’re replicating what you are, you’re not being an authentic creator that is adding to the field. That is not interesting to a publisher or an audience.” More cynically, if you plagiarise your fandom, you’ll risk making a worse version of something better. No matter how much I personally love Thief: The Dark Project , I’m probably not the person to make a first-person thief game. By all means, be inspired, but find ways to channel your inspiration into something that is yours. This is harder to do, and it will take longer than copying something else, but the more you do it the better. Gains of getting out of your fandom: In journalism, there’s an idea that you should actively work to keep yourself out of your reporting. You may be political, progressive, conservative, or have something specific you want to say; but you shouldn’t rub the reader’s nose in it. You should actively strive to keep yourself out . You do this by providing three or more sources whose combined image of a story allows the reader to draw their own conclusions. The sources should be one for, one against, and one that’s observational or represents an expert opinion or a neutral but related party. In cases where someone has done something bad, you let them speak their mind as a contrast against the words of the victim; then you get a lawyer or expert to chime in with a third angle. You can also bring in friends, relatives, coworkers, and so on, to flesh out the story even more. Like journalists, game designers should allow players to make up their own minds too. Since a game can become anything and be played by anyone, it’s impossible for you as the game designer to decide how a player will feel as they play your game. The thing you intended to be a feelgood reveal may carry emotional baggage for a certain demographic, but the imagery may cause disconnect for someone else. This doesn’t mean that everything needs to get equal terms, however. But you leave the conclusions for the players to make. An anti-example of this is the mushroom man in FarCry 3 . First time you meet him, you learn he locked one of your friends in his attic. As he unlocks the door, and reveals she’s drugged out of her senses, he seemed a total creep to me. Then the character I was playing proceeded to thank him for this treatment — I wanted to shoot him. That is the kind of disconnect that happens when the player isn’t able to “own” the experience. Gains of keeping yourself out: Theory crafting and intellectual discussions on emotions, design principles, and much more is a huge and important part of ideation. But it can’t be the only part. To “think with a controller,” you pull one out and you imagine yourself playing the game you intend to make. Which buttons you press, how frequently, and when. If there’s some interface needed to tell the player how a certain thing works. This is of course a metaphor, since it can be physical components of some other kind than a controller, but the simple act of physically interacting with your game even at this extremely early stage will help you flesh out your ideas. Gains of thinking with a controller: If you want to make games, you can’t wait to find your muses. You must be able to do the work. In ideation, the tendency is to never stop ideating, making you stay in conversation mode for longer than you should. Getting things on a page pushes you towards both the literal page, writing things down, and towards the exploration stage, where you will be challenging everything you just came up with. The effect the blank page will have on the typical writer sets in for game designers too. The dreaded block! To get out of this blank page effect and avoid getting stuck on details that are not actually important yet, you can try to just get something on the page. Gains of getting things on a page: Brainstorming and spitballing is great, but complete freeform ideation is very much a hit/miss process and often leans too much on seniority or other soft credentials. Enter intrinsic ideation! The term comes from a NoClip documentary on the making of Horizon: Zero Dawn , and the way they phrase its use is that “everything has to come from something you already established as true.” In other words, you take the facts defined for your game, and you only bring the new thing being discussed into your game if it can be motivated using those facts. It’s a handy way to sanitise your ideas and see that they fit with the game as a whole, and also to remove ideas that may be cool on their own but don’t fit into the whole. This tool is only useful if you’ve already been through a few rounds of exploration and are returning for more ideation, but the main advice I’d give you is to be ruthless . If things don’t check out against your pillars, facts, or other documented processes, you should cut it out and move on. Ideation is the only time where cutting things out is cheap . Gains of intrinsic ideation: We sometimes forget that gaming is a form of make believe. Pretending to jump really high, or spending millions of virtual dollars, or killing half the population of Evil Land. Our species has been engrossed by make believe for as long as we’ve been about, and it can therefore be particularly useful to seek out some of that as inspiration. Make believe isn’t freeform conjuring of the fantastical, it’s imagining that you are doing something . Driving the expensive car, performing the athletic feat, climbing the highest mountain, defending your village from an attack, exploring the deepest woods, keeping your head down in the mud and trenches of World War I. It’s easy to forget that there’s a whole world out there that has nothing to do with dice or controllers. Reading, watching, and doing , is about immersing yourself in the real world, embracing that reality surpasses fiction. Perhaps you shouldn’t watch the Game of Thrones series from HBO a third time, but instead watch a documentary or read some books on the Wars of the Roses. Perhaps a book on medieval longsword fencing is not the way, when you can visit your nearest Association for Renaissance Martial Arts (ARMA) group and swing a longsword yourself. First step for this to work is to get out there and expose yourself to new things. To translate this inspiration into game ideas, there are two things you can look out for: verbs and adjectives . What is being done, and how it’s described by the people doing it. Some things are of course harder or more dangerous to try than others. You can’t try the trench life of a British soldier in 1916, but perhaps you can go to a rifle range, and you can load up your backpack and march for a couple of hours in the rain. Gains of reading, watching, and doing: Most of us have very concrete ideas of what a certain genre or type of game should be. An interesting way to start ideation can therefore be to write all these things down and actively turn some of them upside down. Conventions will usually belong in a broad category. When someone says they’re designing a worker placement game, for example, this will come with a list of conventions. Each player has their own workers, a common board with a set number of slots for workers, a placed worker will block other worker placements in the same slot. Etc. If you write each of these down, you can usually see the inverse of each of them. Each player has their own workers — what about a common pool of workers? A common board with slots — what about player-owned boards holding those slots? This exercise can go as deep as you want, and can also aid you in figuring out the shape of your inspirations. But you have to be fairly specific about what a convention is. Gains of challenging conventions: If you already have a long list of features you want to explore, you can select just a handful and focus only on those. If not, you can take a broad theme and make it a hard constraint. The reason you use constraints is that they can directly inform your ideation. Many times, ideation that is too vague will result in derivative designs. If you say that you can only use the analogue sticks and triggers on a gamepad, for example, you can push every other button out of your mind and just think about what you should do with those specific inputs. It doesn’t mean you won’t use the other buttons down the line, just that you should keep them out of your mind for now . Gains of using constraints: Ideation : coming up with ideas and vetting them. Exploration : trying things out as cheaply as possible. Commitment : deciding what to commit to. Problem solving : solving problems in the real game. Balancing : broad strokes for the core audience. Tuning : fine-tuning the marketed product. More positive communication. More diverse ideas. More constructive conversations. Forces you to find your own identity. Makes it easier to separate work from inspiration. Lets you focus on the experience of play. Let players decide the meaning of things in your game. Enhances the sense, for players, that the game is “theirs.” Respects the death of the author . Makes your design tangible, in a simple way. Gets you thinking about the practical side of things. A player story . Just a paragraph or two that describes the player going through a segment of the game as you imagine it. Bullet point lists . List verbs, cool abilities, interesting characters, key features; anything that can be readily listed and that you want your game to have. Documentation headlines . Get just the headlines of a bigger outline or document in place. “Gameplay,” “Art Direction,” “Level Design;” whatever feels important to you. Write just a sentence under each to summarise your thoughts. Goals and anti-goals . Things you want to achieve with the game, and things you don’t want at all. Moves your ideas from the purely intellectual space to the practical. Forces you to sort through the ideas you have. Things to dig deeper into as well as things to reject outright. Reinforcement of established principles and design facts. A neutral process for vetting ideas that doesn’t lean back on soft credentials. Pivots when it’s still cheap to pivot. Gets you away from the computer. Concretises your inspirations into their different details. Lets you discover new inspirations. Expands your ideation vocabulary. Activities . Killing goblins and taking their stuff. Moving puzzle pieces. Drawing cards. What if you change or invert an activity? Maybe give goblins stuff, remove puzzle pieces, and start with all cards on hand. Components . What if you change the rules around a common component? Instead of rolling a die, you pick a number and you hide it under your hand. Restrictions . You can only play one card per turn and weapons can run out of ammo. What if you remove a standardised restriction? Play as many cards as you like, and have infinite ammunition. Controls . The gamepad left trigger is for aiming, and you must press Jump when you reach an obstacle. What if you switch or remove controls? You track opponents by holding the left trigger, and you jump automatically when you reach an obstacle — you just have to look in the right direction. Helps you figure out your own convention biases. Fertile ground for coming up with new ideas that are twists on existing ideas. Makes it easier to communicate — many conventions will be assumed during ideation. Restrict theme . It must be about monster hunting in the 1800s. Restrict player avatar . The player is a bus driver. Restrict activities . Players can’t have more than two choices to make at any given time. Restrict controls . You can only use two fingers on one hand, with a touch screen. Restrict player count . Playable by exactly three players. Restrict components . The game should only use 20 cards. Restrict play time . A session cannot take more than 5 minutes to complete. Restrict narrative . Just one location, three characters, and two specific events. Restrict inspirational sources . Watch only this documentary; read only that book; play these two games. Restrict preferences . Build a game from a feature or theme you don’t like. Pushes you towards results. Allows you to ignore potential distractions. Helps you evaluate the specific thing you decided to zoom in on.

0 views
DHH Yesterday

But Y

It's no mystery to me why the Tesla Model Y is the world's best-selling car. As a total package, I could make a fair argument  that it's simply because it is the world's best car.  I'm no stranger to Teslas at this point. We've owned a Model S Plaid, the Model X we traded in on the Y, and we still have the Cyberbeast too. But as impressive as all those cars are, the Y towers above them in several key respects, but first and foremost, value. The premium all-wheel-drive white-on-white seven-seater we just got was right around $55,000. That's not exactly cheap, but it's less than half of what we spent on any of the other Teslas. It's a quarter of what we spent on the Porsche Taycan Turbo S. It's a sixth of what a new Aston Martin DBX would set you back. And, if I could just have one car, I'd pick the Y over all of them. The first thing you notice coming from earlier Tesla models is just how well-built the new Model Y is. The gigapress process that produces these new cars results in a package that feels reassuringly solid: no squeaks, no rattles, no flex. This couldn't be said about any of the earlier S and X models we had. But compared to other makes, it's not exactly revolutionary that a brand-new car feels well put together. Many other makes have managed to perfect that process over the decades. Tesla has now merely leapfrogged itself to the front of the class. But what very much is revolutionary is just how effortless owning the Y feels. It starts with entry and exit. Once you've paired your phone, you never think about keys or starting or stopping the car again. It just happens. There's no on/off button, no starter, no unlock. Again, other makes have made attempts at this, but none that I've tried is even close to the effortlessness that Tesla's superior software stack is able to deliver. Speaking of software: It just works. Every time. Going anywhere. You don't miss Apple CarPlay or Android Auto for a second. The navigation, the Spotify integration, the setup. Everything feels like it was written by a leading American software company. Not subcontractors out of India or firmware developers forced to deal with user interfaces. But where everything comes together is FSD. The self-driving technology that Tesla pushed against all odds for over a decade is finally here in an utterly magical incarnation. The car not just drives itself anywhere, it drives better than almost any human I've ever been driven by has been able to do. Its ability to anticipate traffic patterns, hit the perfect deceleration curve towards a light, slow down for even minor speed bumps, and gracefully curve around pedestrians or cyclists is nearly unbelievable.  As in, you'd be forgiven the suspicion that there must be a human driver hidden somewhere controlling the car over the internet. But it's just AI, and it's gotten fiendishly better over just the past year or so. All in service of that effortless experience. In fact, I'd go so far as to call it a luxurious experience. Like you're being escorted by the Queen's own driver to your desired destination. The Queen wouldn't bother with keys or rattles or driving. She'd just get in, be driven, and arrive fresh for a waive. This is the best approximation you can buy for mortal money today. But then, unlike the old X, it's actually also surprisingly delightful to grab the wheel yourself, hustle it down a hill, lean it into some fun corners, and surge out on that wave of endless torque that electric motors always deliver so well.  No, it's not a Porsche 911, but I'd say it's 90% as fun as a Taycan, at a fraction of the price, in a package that's endlessly more practical, and — did I mention this already? — can drive itself once you're done with the spirited part of the journey. The Tesla Model Y is a triumph of capitalism. Making the best self-driving technology available to the masses at a price that's accessible to the middle class in a car that even billionaires would appreciate.  Andy Warhol captured this egalitarian celebration well with this sentiment: “A Coke is a Coke and no amount of money can get you a better Coke than the one the bum on the corner is drinking. All the Cokes are the same and all the Cokes are good.” The Tesla Model Y is an incredible car for nearly everyone.

0 views
Unsung 2 days ago

“Not being good at something doesn’t mean you can’t love it.”

Perhaps ironically given the subject matter, I found this 34-minute video by Razbuten a bit intense, but I would still recommend it to people who work on onboarding, settings, etc.: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/not-being-good-at-something-doesnt-mean-you-cant-love-it/yt1-play.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/not-being-good-at-something-doesnt-mean-you-cant-love-it/yt1-play.1600w.avif" type="image/avif"> In the video, the author tries to answer the question: how to make any given game a challenge, given there is no universal standard of difficulty and every player arrives at a game not just with different skillset, but also likely different goals. There are many techniques a game can use to adapt to the player – a simple upfront difficulty selector, complex difficulty settings, a training level, adaptive difficulty, accessibility/​assist modes – but there are no easy answers. Each method comes with pros and cons, and perhaps the very notion that a game should adapt to the user is flawed; some players might find it more rewarding to have to step up to the game instead. In the video, Razbuten covers a lot of examples really well. I’m not going to say any of this maps 1:1 to productivity software as goals of games are very different than goals of apps… but even though I have never played any of the games mentioned, the examples made me think. After all, some of the psychology of mastery will be the same between these two realms. (I bet there were at least some of you who saw the previous post about LaTeX and thought “this looks hard and fascinating – I’m going in,” and others took a note to never approach it.) #flow #games #onboarding #settings #youtube

1 views

Request for Proposals for Non-profit Grants

For the last five years our family has been giving grants to a handful of U.S. non-profits using the following criteria. We are planning to slowly expand this effort and I’m putting this post out there in hope that more orgs, especially newish ones, find us over time. $25-200K annual grants U.S. non-profit within a target area (see below) Ideally founded in last 5 years with <$1M budget, which is in service of trying to increase the probability our limited grant budget is impactful Can use grant(s) to level up impact, for example hire a new team member, start/expand a project, or unlock new funding sources Science Acceleration Example grant: PubPeer RFP: Raise the U.S. science budget Example grant: Rank The Vote RFP: Citizen-led amendment path RFP: Enlarge the House of Representatives RFP: Multi-member, proportional House districts Example grants: Free Law Project , Fix The Court RFP: FOIA for the Judicial branch Example grant: Public Accountability RFP: Similar appellate impact litigation Example grants: GiveWell Top Charities Fund , DonorsChoose RFP: Coordination for starting more bail funds Mainstreaming Critical Thinking Example grant: School of Thought RFP: Help people reason about complex topics If you’re wondering where is privacy as a target area, it is covered by the independent DuckDuckGo donations , which you can learn about more in this Duck Tales episode . Thanks for reading! Subscribe for free to receive new posts or get the audio version . $25-200K annual grants U.S. non-profit within a target area (see below) Ideally founded in last 5 years with <$1M budget, which is in service of trying to increase the probability our limited grant budget is impactful Can use grant(s) to level up impact, for example hire a new team member, start/expand a project, or unlock new funding sources Science Acceleration Example grant: PubPeer RFP: Raise the U.S. science budget Example grant: Rank The Vote RFP: Citizen-led amendment path RFP: Enlarge the House of Representatives RFP: Multi-member, proportional House districts Example grants: Free Law Project , Fix The Court RFP: FOIA for the Judicial branch Example grant: Public Accountability RFP: Similar appellate impact litigation Example grants: GiveWell Top Charities Fund , DonorsChoose RFP: Coordination for starting more bail funds Example grant: School of Thought RFP: Help people reason about complex topics

0 views
Anton Zhiyanov 2 days ago

On interactive Go tours

Over the past two years, I've published interactive tours for five Go releases, from 1.22 to 1.26. I know some of you have read them, and I've received a lot of kind words from you (even some core Go team members reached out) — thank you so much for that! Tour history: Go 1.22 • 1.23 • 1.24 • 1.25 • 1.26 + Go features by version Unfortunately, at some point, writing these tours stopped being fun and started to feel like a part-time job. I'm not really excited about that, so I've decided to stop. I still like Go (well, most of it). I read a lot of Go code, I write some Go code, and I write Solod code, which is also Go 🙂 (Solod is a systems language with Go syntax and a Go-like stdlib). I'm still pretty close to the language and will probably continue to write about it. But the interactive tours story is over.

0 views

Neo beginnings

I did it. I finally bought a new Mac. I managed to snatch a MacBook Neo on Amazon a few minutes after Apple announced the price increase across their line-up. It all happened very quickly, but I think it’s worth taking the time to explain my messy, complex, overcomplicated train of thought. If you’re a regular reader of this blog, you know that I complained (or bragged) a lot about the fact that I still used an early 2020 MacBook Air as recently as two weeks ago, and that its battery was getting a bit old, and it was maybe a little bit slow at times. I explained in a post that I felt confident in being able to keep using it for one more year, as its limitations felt more like a way to focus and maintain a well-controlled set-up rather than constraints. I was ready to wait for something like the M6 generation of the MacBook Air (so I could continue my story with that family of laptops, which started with the early-2015 11-inch model). But this post was written in January, before Apple unveiled the new M5 MacBook Air, and, as a little surprise, the MacBook Neo. I first considered the Neo, because its clear limitations were not a deal-breaker for me; on the contrary, they were a great follow-up to my then-current set-up, which was very much not demanding by design. In fact, the Neo looked pretty much, feature by feature, like the laptop of my dreams: simple, focused, reliable, cheap, well-built, straight to the point. With the classic Apple pricing ladder, of course the MacBook Air looked very tempting, offering so much more for just a little extra: better speakers, better trackpad, a backlit keyboard, double the memory, a better screen, a better audio jack, better connectors, a better battery, a far better chip, a better webcam, Touch ID, etc. Therefore, for 400 euros more, it looked like a better deal, and better value than the Neo. I could even use that extra bit of power to finally edit photos on my laptop instead of on my phone, where the screen and performance have long been better suited than those of my old Mac for running apps like RAW Power. This is where it got a bit complicated in my head and froze all my purchase intentions. Value-wise, the MacBook Air M5 was, like I said, a much, much better choice than the Neo: for 50% more money, you get more than double the computer basically. Money-wise, if the Neo is indeed sold at a great price, it’s not as good a deal as the MacBook Air, not as good value. But if I were to stick to value and price, well, keeping my old MacBook Air Core i5, costing me zero, would always be a better deal. For a while, whenever I thought of “what I already have” (the old MacBook Air) versus “what I really want” (the new MacBook Air), I had always chosen the easiest and cheapest option of the two. What I should have done instead was focus on the fundamentals: what I actually needed (the MacBook Neo). What I need is a laptop I can count on, but not only performance-wise, where my old Air was surprisingly resilient. The battery life, enabling the laptop lifestyle, is essential. Spending time on my computer is my hobby, my pleasure at the end of the day. On the days I had forgotten to plug the computer in, when I wanted to check something sitting on the couch or on my balcony, far from the reach of the charging cable, well, I could not: the little bugger had no juice left, my end-of-the-day moment was ruined, and this situation was overall a pain. So when I first learned that Apple planned to raise prices , I reconsidered once again the timeframe in which I had to change my Mac. Waiting another year and spending 20% more for the same-ish computer as the one I could buy today didn’t look like a good idea. So when I saw that Amazon had a special deal on the MacBook Air, priced at 1080 instead of 1200 euros, I was ready to buy one. A few days later, while I still hadn’t made the jump on the purchase, I saw the headlines pop up that the Air was getting 200 euros more expensive on the Apple store. From that moment, I knew I had to act fast, before Amazon raised the price too. This is when I saw that the Neo was sold at 630 euros instead of 700, and this is when a little light bulb appeared above my head. This Mac was the one I needed. In fact, as I needed to buy the laptop right away, before the price change, I was keen on saving 450 euros, especially a few days before my salary arrived. The 630 euro price tag was more affordable than 1080 and more compatible with an impulse buy. So I ordered the cheapest Neo model, without Touch ID, and ended up saving 170 euros on the Neo. That’s more than a 20% discount if applied to the current price on the Apple website. Needless to say, I’m very pleased with this deal: now if I were to sell my computer I could possibly still get more money than I paid for it, in case I end up unsatisfied with it, which is not the case so far. After two weeks of regular use, I have no complaints really. Thank you Apple for raising prices and forcing me to buy the computer I actually needed, I guess? Performance is fine, even great when compared to my old Mac. I want to say it’s more or less as snappy as the M1 MacBook Air I use for work. Clearly, this is no match for the M5 chip, and 8GB of memory may feel a bit limiting, but I don’t need that much memory to run BBEdit, NetNewsWire, GoodLinks, and Safari anyway. I actually like that this limitation is forcing me to keep my feet on the ground when it comes to trying out new apps and revisiting my current set up . We’ll see how it goes in the coming months and years. I don’t think I’ll be able to push this device as hard as I pushed my old Air, but hey, it’s almost half the price. The keyboard is more or less the same, if a bit firmer, probably due to the fact that it’s a new computer and I come from a six-year-old, worn-out keyboard. Most of the computer feels identical to the Air, if ever-so-slightly worse, like the speakers or the screen. As I don’t plan to edit photos on this machine, really, there is only one part where I really “suffer” from a downgrade compared to the Air: the trackpad. The Air’s trackpad has been so good for so long that we tend to forget about it: the haptic feedback makes it very satisfying and informative to click. On the Neo, pressing on the trackpad is nowhere near as satisfying. The travel distance of the trackpad is, I want to say, 60 to 70% longer than it feels like on the haptic trackpad, and this is 60 to 70% too long, too deep, too loud. So far, this is the only part that feels really worse in terms of my daily experience. In the end, this is what the Neo really is: a familiar 630-euro laptop — a 630-euro new Mac — perfect for my activities of web browsing, video streaming, writing, and geeking around with apps. Dare I say that the Neo, as a single-purpose device, is a perfect blogging machine?

0 views

Short Reflection on being Offline for 24 hours

There are, I think two reactions to the title of this post. One is to scoff at how short a time 24 hours really is; something barely worth mentioning. But another, perhaps less voiced reaction is to think "wow, I can't remember when I last did that..." When I last did this it was involuntary - I was living in a shack in the mountains and a sheep had chewed through the cable connecting me to the satellite dish, which was in turn connecting me to the web. And so I spent a couple of weekends net-less (with weekdays at a co-working space so I could keep in contact with my client). But I can remember kind of enjoying it, reading things I claimed I would get round to reading but never did, and thinking more deeply. "Maybe I should make it a regular thing" I thought, "just to reset things and get a new perspective...". That was some six years ago, and the most I'd managed since then is maybe an hour of self-imposed internet exile. But things have been building recently. Having a three your old who - while she does enjoy a cheeky music video or three - is nevertheless content to do things like read, draw, and play with blocks through her day made me reflect. How much was she seeing her father doom scrolling with the excuse of "I just need a break"? Why couldn't I be more like her, and how long until she was more like me? I took note of the contemporary moral panic around kids and smart phones, and I deemed it pointless if society at large was addicted; the generation who had chided us millenials for "always TXTing" on our monochrome nokias were now grey, wisened, and often more addicted to contemporary devices than we ever were. But unlike the generations before or after, I at least had partial immunity from remembering old youtube with it's amateur video content and primitive skinner box mechanisms; of having some natural resistance to the more modern and extreme developments of shorts and AI thumbnails. What hope does a child have of resisting contemporary, weapons-grade slop addiction? And so I've spent the last 24 hours cut off from the internet as an experiment. Completely self imposed - just disconnected my devices and set an alarm. Once again I read more, once again I thought more deeply, and once again I liked it. My alarm will be ringing soon and I will be lying if I said I wasn't excited to re-connect. And nor am I trying to say that the internet itself as some wholly negative thing - after all, that's where the things I read come from; the best written material the world has to offer, saved to my machine. And yet despite the incredible upside of the internet, I can't help wonder if my continued resistance against its dark side might require more drastic action. I'd already quit facebook, reddit, lobsters, HN (ok...provisionally) bluesky, several discords, and most recently I'd been off youtube entirely for days. But there's always a hook back in. "I can't quit X" I tell myself, "I've met so many great people... oh what's that, tech drama? Well they surely need to hear my opinion..." My time online draws near. The ever-full needle of stranger's opinions hovers tantalisingly over my swabbed, tensed arm. Still, I like to think I've taken the first step.

0 views

Establishing an Identity

If you’ve followed me on RSS for any amount of time, first off, thank you so much! Second, you may not have noticed how often this site changes. RSS protects you from the near-monthly changes that my mad scientist side makes to this site. This year alone, ThatAlexGuy.dev has been powered by 11ty, Hugo, plain HTML, Bear, Micro.blog , and Pure Blog. My files have sat on OpenBSD Amsterdam, DigitalOcean, and a Laravel Forge VPS. I’ve written new articles and lost old articles in migrations. My site has switched appearance more frequently than a Bian Lian (变脸) performer! I’ve come to realize I’ve been seeking both an identity and a voice. I want an outlet that reflects my interests, my background, and my day-to-day, but that’s more than what I could accomplish on something like Mastodon. All that brings us here, iteration 4 (or 8, or 15, or 16, I can’t remember). There are a few key differences and intentional choices that reflect where I want ThatAlexGuy to go. Building a new experience that will stick and satisfy the goals in my head won’t be easy, but here are the guiding pillars that are to shape what’s coming next. I have a desire to create in-depth, well-researched, and potentially interactive content. Many of my current posts come with a “1-minute read” tag. I want to change that. I’ll be digging into topics with greater detail, cross-referencing multiple sources, and (hopefully) interviewing others. As a result, I’ll be posting less frequently, but my new goal is quality over quantity. Regulars on my site will be aware of my “Photo Journal” series in which I posted a set of photos around a theme (macro, nature, Gameboy Camera ). I want to continue building my photography skills through the incorporation of high-quality photos in my articles. While text sets the tone, visuals set the atmosphere in an article. Here’s the big tomato, as they say (nobody says that): defining what this site represents. That means setting the tone and defining how topics string together to form a consistent narrative. I’ll be figuring this out for a while, but I want to leverage my interests such as indie technology, vintage computing, time away from the screen, photography, and Chinese culture. So what’s changed so far? Quite a bit! First, ThatAlexGuy.dev is now run by Ghost.org . For myself, this means less time in the technical weeds and more focus on writing. For readers, it opens the doors to a wider audience. Email newsletters are a more accessible way to stay up-to-date on new articles. Don’t worry though, RSS isn’t going anywhere! In fact, I managed to fix the broken RSS feed URLs from previous migrations (hopefully)! I’ve started to define the personality of the new site. I pulled background and accent colors from one of my favorite atmospheres in a game (Sprout Tower in Pokémon Gold). Using my iPad, I’ll be creating article images that give a calligraphy + hand-painted vibe. I’ve also brought in my Chinese name for the logo(小艾 - Little Alex). I’m working on my first longer-form article. It probably won’t be great, but first attempts never are. From there, I hope to refine my writing, researching, and supporting photography.

0 views

Dot product: Component vs. Geometric definition

The goal of this post is to answer a simple question: why are the following two definitions of the vector dot product in Euclidean space [1] equivalent for vectors \vec{a} and \vec{b} : Here’s a graphical depiction of our vectors (focusing on for clarity, though this applies to any-dimensional vectors). It shows both the components of the vectors and the angle between them. The length of the arrow for \vec{a} is |\vec{a}| . We’ll show two proofs of the equivalence here, the geometric proof and the projection proof . The Appendix describes some properties of dot products that facilitate these proofs. We’ll be using this diagram of our vectors \vec{a} and \vec{b} , as well as the vector \vec{c}=\vec{a}-\vec{b} : Using the law of cosines [2] on the triangle formed by the three vectors: Since for any vector \vec{a} , we have \vec{a}\cdot\vec{a}=|\vec{a}|^2 (see Appendix), let’s rewrite this equation as: But \vec{c}=\vec{a}-\vec{b} and the dot product obeys the distributive property (see Appendix). Therefore: For this proof, we’ll assume the geometric definition is correct and will see how it leads to the component definition. We’ll begin by denoting vectors \vec{e}_1,\vec{e}_2\dots\vec{e}_n as the standard orthonormal basis for . For example, in 2D space, these basis vectors are \vec{e}_1=[1\ 0] and \vec{e}_2=[0\ 1] , shown in this diagram: If we take an arbitrary \vec{a}\in\mathbb{R}^n and calculate its dot product with a basis vector, we can use the geometric definition: where a_i is the component of \vec{a} in the direction of \vec{e}_i . The diagram makes it easy to see why this is true from basic trigonometry, but in the more general case this is just a vector projection . Now let’s represent vectors \vec{a} and \vec{b} as linear combinations of the basis vectors: And calculate the dot product \vec{a}\cdot\vec{b} , beginning by rewriting \vec{b} with its linear combination of basis vectors representation: Using the fact that the dot product distributes over linear combinations: But earlier we’ve shown that \vec{a}\cdot\vec{e}_i=a_i . Therefore: Which is the component definition \blacksquare . A generalization of dot products in is the inner product , which is an operation meeting some specific requirements, defined on a vector space. The inner product is denoted as \langle x,y\rangle:\mathbb{R}^n\times\mathbb{R}^n\to\mathbb{R} , and must satisfy the following requirements for all vectors x,y,z\in\mathbb{R}^n and scalars a,b\in\mathbb{R} : For , we define the inner product operation in its component formulation as: Let’s prove the requirements listed above for this operation; this is fairly straightforward, given the well-known properties of scalar multiplication and addition on : Linearity in the first argument: Positive-definiteness: Consider the components of vector x . Clearly, \forall i\quad x_i\cdot x_i=x_i^2\ge 0 . Since the vector x is not the zero vector, at least one of its components is nonzero, and for that component x_i\cdot x_i>0 . Therefore: Now that we’ve proved all the inner product requirements on our operation \langle x,y\rangle , we can say that is an inner product space with this operation. By meeting these requirements, it can be readily shown that our inner product operation has additional useful properties: The third property is particularly helpful, because it means the inner product is bilinear , and thus is distributive over addition. Note that these are shown for the component definition of dot product. It’s not too hard to prove distributivity for the geometric definition using the notion of projections and how they add up. The norm of a vector x in an inner product space is defined as |x|=\sqrt{\langle x,x\rangle} . Therefore, the square of the norm is |x|^2=\langle x,x\rangle . The norm is used to express the notion of magnitude , or length of a vector. If you think of a vector x\in\mathbb{R}^n in Cartesian coordinates, the definition of the norm is a generalization of the Pythagorean theorem. Component definition: \vec{a}\cdot\vec{b}=\sum_{i=1}^{n}a_i b_i Geometric definition: \vec{a}\cdot\vec{b}=|\vec{a}||\vec{b}|cos(\theta) , where |\vec{a}| is the magnitude of \vec{a} and is the angle between the vectors’ directions Symmetry: \langle x,y\rangle=\langle y,x\rangle Linearity in the first argument: \langle ax+by,z\rangle=a\langle x,z\rangle+b\langle y,z\rangle Positive-definiteness: if x\ne 0 then \langle x,x\rangle>0 \langle x,0\rangle=\langle 0,x\rangle=0 \langle x,x\rangle=0 if and only if x=0 \langle x,ay+bz\rangle=a\langle x,y\rangle+b\langle x,z\rangle \langle x+y,x+y\rangle=\langle x,x\rangle+2\langle x,y\rangle+\langle y,y\rangle

0 views
Evan Hahn 2 days ago

Prefer STRICT tables in SQLite

In short: I prefer strict tables in SQLite because they avoid some datatype problems, such as putting text in number columns. SQLite has a feature that I think is underrated: strict tables . Strict tables help enforce rigid typing, preventing mistakes like putting text into integer columns. I like them, and wrote this post to promote their use! To make a strict table, add to the end of its definition. Like this: That’s it! But what does it do? Broadly, strict tables help enforce rigid types, like other SQL engines do. Most significantly, strict tables keep you from inserting the wrong type into a column. For example, SQLite normally lets you put text into an column, but not with strict tables. Personally, I think it’s a mistake to try to put text in an integer column, or vice-versa. I don’t want SQLite to let me make this error! The same validation happens for s, too. Notably, if a value can be losslessly converted, it will still be accepted. For example, the string can be perfectly converted to an integer, so it’s allowed. These two lines are equivalent, even for a strict table: By default, you can create columns with bogus types. For example, all of these work even though they aren’t valid SQLite datatypes: I think these aren’t what the developer intended. Some of these are typos, some of them are misunderstandings of which datatypes SQLite supports , and some are egregious mistakes. Appending to any of these statements makes them error. In my opinion, that’s the correct behavior! Only , , , , , and are allowed. Strict tables also require a column type, so you can’t do . If you still need a column to be flexible, you can use the datatype. As the name suggests, it allows anything—even in a strict table. I haven’t found a use for this, but maybe you will! I prefer strict tables but I must share a few cons. Not everything is better! I think it’s best to use strictness from the start, but that’s not always possible. Unfortunately, I don’t think there’s a way to a table to make it strict. I think you have to copy the data out of the non-strict table into the strict one. Something like this: Note that this could be tricky if the non-strict table has invalid data! For example, if the old data accidentally contains text in an integer column, you’ll get errors when doing the migration. You’ll probably need to clean the data or cast it . You could make a rule for your codebase that all new tables are strict. That might be useful—at least some of your tables are valid! But it might also mean you have inconsistent validation across your tables, which might be more surprising than having weak validation on all tables. It’s up to you to decide whether this is a good fit for you. SQLite has a whole page called “The Advantages Of Flexible Typing” , where they argue that SQLite’s flexible behavior is good, actually. I hesitate to wade into the controversy of static-versus-dynamic, but I disagree in most cases. I’ve personally encountered many bugs where an unexpected data type caused subtle headaches. I’d much rather these mistakes explode loudly. But it’s worth noting that SQLite’s developers seem not to share my preference for strict tables! They point out a few good uses for flexible tables, such as “a pure key-value store” or “a place to store miscellaneous attributes” of different types. They also mention that you might want to keep the invalid data in some cases, like if you’re directly importing a messy CSV and don’t want to lose any data. I still prefer strict tables, but acknowledge there are some reasonable cases for non-strict ones. (There’s also at least one comment in the SQLite source that calls non-strict tables “legacy” , but I trust that less than the official documentation.) SQLite introduced strict tables in version 3.37.0 , released November 2021. If you’re on an older version of SQLite, you can’t use strict tables. It’s worth noting that old versions of SQLite can’t read databases with strict tables. For example, if you create a strict table in the newest version of SQLite and then try to read that database in SQLite 3.36.0 (before strict tables were added), you’ll get an error—even if the strict table is already in the database. Strict tables are theoretically slower because they have to do a little extra work. For example, they check datatypes when doing an insert or update . But in practice, I don’t think this is an issue. I wrote a hacky script that inserted millions of rows into a table with 100 columns, and there was no obvious difference on multiple machines I tried. The file size on disk was also the same. I didn’t test this thoroughly, so maybe there’s something I missed, but I don’t think strict tables present a performance problem. In fact, one might expect better performance because you won’t be accidentally mismatching SQLite’s column affinities. But again, I haven’t tested this. Personally, I think the pros of strict tables outweigh the cons. I generally prefer when types are rigidly enforced. It squashes a class of mistakes, and help enforce good data integrity. They’re not a panacea, but they’re usually easy to add and go a long way. If there’s a SQLite feature you think is underrated, please tell me .

0 views
Sean Goedecke 2 days ago

In defense of not understanding your codebase

As a software engineer, how well do you have to understand your own codebase? My guess is that people who work on small codebases with low-turnover teams (say, Redis or games like The Witness ) would say “obviously you have to understand it completely, otherwise you can’t do good work”. I’d also guess that people who work on large codebases with high-turnover teams (say, the Google web search backend or GitHub) would say “obviously you can’t understand it completely, you just have to do the best you can in your local area”. These are two largely different ways of programming with different methods, practices and cultures 1 . However, the first group is over-represented in online discussion about software engineering 2 . I want to defend the second group against the first. In many software engineering environments, there’s nothing wrong with being in a state of partial understanding. In fact, in large systems a partial understanding is the best you can do. The best articulation of the “you have to understand your codebase” side is Peter Naur’s famous paper Programming as Theory Building . I like this paper, but I think it goes too far in that direction. Naur’s core point is that when programmers work on a program, the code is really just a by-product, and the main product they’re working on is their “theory of the program”. That’s made up of their intuitive sense of what’s happening and why, which can only be partially captured by code or documentation. If they lost the code, they could rewrite the program easily. If they lost their understanding (say, if the team experienced 100% turnover), they would struggle to make sense of the code. So far, so good, but Naur goes further than this. He says that the theory should not be reconstructed from the code. According to Naur, you’re better off scrapping the program entirely and having a new team rebuild it from scratch , building up a new theory in the process 3 : reestablishing the theory of a program merely from the documentation, is strictly impossible … [therefore] the existing program text should be discarded and the new-formed programmer team should be given the opportunity to solve the given problem afresh Anyone who’s been an effective software engineer at a large company knows that Naur is dead wrong about this. There are at least two reasons. First, you simply can’t rebuild large software systems from scratch . Sufficiently large systems (if they have users) contain thousands of weird cases and quirks that cannot be reimplemented. Even a team that’s intimately familiar with the system couldn’t do it: there’s just too much stuff to juggle. Successful rewrites always start by carving out the existing codebase into small isolated chunks, then rewriting one chunk at a time. In other words, rewriting a software system involves making a bunch of changes to the old system. If you can’t change the old system, you certainly can’t replace it with a new one. Second, abandoned systems are revived all the time . In a tech company with hundreds of millions of lines of code and thousands of engineers, it’s not uncommon for a codebase to have nobody left who’s familiar with it 4 . All it takes is a few people to quit at the wrong time, or for a codebase to be unmaintained for a year. Not only have I seen other teams do this, I have personally taken ownership of abandoned codebases, figured them out, and gotten to a point where I could effectively work with them. It takes time, but building a new theory of the codebase is possible. You start by understanding one flow end-to-end, then slowly branch out from there, making careful changes as you go. In sufficiently large codebases, everyone operates with an incorrect theory of the program . The defining feature of modern software systems is that they’re just way too big for anyone (or even a whole team) to keep in their head: nobody understands it all . To be effective, you have to figure out a way to work with a merely partially-correct theory. This is why I keep going on about taking a position and confidence . If you’re not sure about something, you can’t just sit back and wait for someone with a perfect understanding to come and give you the answer. If you’re a competent engineer, that person is you . You have to grit your teeth, make your most educated guess, and then deal with the consequences. To be generous to Naur, it’s possible that in 1985 the average size of a program was several orders of magnitude smaller than today, and that when Naur writes about “large programs” he’s not talking about tens of millions of lines of code. Naur’s first example of a large program is a 200,000 line industrial monitoring program, and his second example is a compiler. In 1987, the first version of the compiler GCC was about a hundred thousand lines of code; in 2015 GCC was over fourteen million lines. I can believe that rewriting one or two hundred thousand lines of code is relatively straightforward, particularly if you get to reuse existing tests. Not so for one or two million. LLMs are often cited as a tool that’s bad because it impedes the ordinary process of theory-building. I think this is overly simplistic. Like many software tools, LLMs are a double-edged sword: they make it harder to construct a detailed mental theory of the software, but they allow you to build a partial theory quickly and they can help you leverage that partial theory more effectively. This is a complex tradeoff that I’m still thinking about. Setting LLMs aside, I’m confident that it’s silly to say that anything that interferes with your theory of the software must be bad. Here is a partial list of other things that make it harder to maintain a theory: Like most things in software, “maintaining a theory of the codebase” is one value among many. Sometimes it’s the most important value and you sacrifice other values for it; other times you trade it off for speed, or legal compliance, or for political reasons 5 . Almost all engineers — particularly “pure” engineers — prefer to maintain an accurate mental model of their software. It’s more fun, less stressful, and feels more like “real engineering”. That’s why many engineers take up open-source projects in their spare time in order to work on small codebases by themselves: in order to do engineering work where they can maintain an accurate Naur theory of the codebase. I don’t think there’s anything wrong with that. However, at work you are paid to do a job . In other words, they pay you money to adopt their set of engineering values. It’s hopefully well-understood that however much you might personally care about performance, sometimes you have to write slow code at your job (for instance, to get a project done on time, or to accommodate some awkward requirement). Maintaining a theory of the codebase is the same kind of thing. I wrote about this at length in Pure and impure software engineering . I think many of the repeated arguments we have in the software industry are caused by the pure total-understanding culture coming up against the impure partial-understanding culture. Open-source engineers are more excited to blog about their work, the raw engineering content is typically more impressive (because coordination problems dominate big proprietary systems), open-source projects can be legally written about while proprietary systems can’t, and even if you could do it legally, writing about large codebases is impossible because it requires too much specific context . I re-read the relevant chapters of Ryle’s The Concept of Mind (which Naur cites throughout) and I think Ryle is more generous about theory-building. For Ryle, theory-building or know-how automatically happens as you do things. It’s fully consistent with Ryle to think you can pick up an existing codebase just from the code, purely by puzzling it out. Naur says: “Lest this consequence may seem unreasonable, it may be noted that the need for revival of an entirely dead program probably will rarely arise, since it is hardly conceivable that the revival would be assigned to new programmers without at least some knowledge of the theory had by the original team.”. If only! Some engineers might say that maintaining a theory is the core value, because without it you can’t fulfill any of the others. I disagree. You could say the same thing about readability, or maintainability, or correctness, or a bunch of other engineering values. We trade off “core” values like this all the time. Other people being allowed to write code in your codebase Having to implement legally-required features like accessibility and data protection Allowing your colleagues to quit their jobs or move between teams Having to upgrade software versions for security patches Bringing in libraries or other dependencies I wrote about this at length in Pure and impure software engineering . I think many of the repeated arguments we have in the software industry are caused by the pure total-understanding culture coming up against the impure partial-understanding culture. ↩ Open-source engineers are more excited to blog about their work, the raw engineering content is typically more impressive (because coordination problems dominate big proprietary systems), open-source projects can be legally written about while proprietary systems can’t, and even if you could do it legally, writing about large codebases is impossible because it requires too much specific context . ↩ I re-read the relevant chapters of Ryle’s The Concept of Mind (which Naur cites throughout) and I think Ryle is more generous about theory-building. For Ryle, theory-building or know-how automatically happens as you do things. It’s fully consistent with Ryle to think you can pick up an existing codebase just from the code, purely by puzzling it out. ↩ Naur says: “Lest this consequence may seem unreasonable, it may be noted that the need for revival of an entirely dead program probably will rarely arise, since it is hardly conceivable that the revival would be assigned to new programmers without at least some knowledge of the theory had by the original team.”. If only! ↩ Some engineers might say that maintaining a theory is the core value, because without it you can’t fulfill any of the others. I disagree. You could say the same thing about readability, or maintainability, or correctness, or a bunch of other engineering values. We trade off “core” values like this all the time. ↩

0 views