Monday, April 29, 2024

don't be afraid to duplicate

 "I generally follow the rule. Duplicate code until you have at least three examples. Then you can generalise.

So many times if you dedupe code which appears in two places that at first looks like the same code you later realise it is different behaviour and make the "general" function much more complex."

--Clair Blackshaw

Interesting to pair that with my general sense of the kneejerk tendency of some folk to look for a library rather than write a little bespoke code. A good library solves MANY scenarios at once, but since the whole point is kind of NOT understanding the solution as deeply (or taking a lot of time to learn new language of configuration) if it does go wrong you're likely to have less clear sight into how to dig yourself out...

Monday, April 22, 2024

the chicken and the pig

Once upon a time I had official scrum master training with Ken Schwaber.

Besides the general scrum knowledge I acquired some details have stuck with me, like the bill-shaped duck call he would use to get peoples' attention. (He said people were less likely to steal it.)

Also this introductory line which seems oddly belligerent, but reflects the Scrum folks' faith that they had the better idea (and indeed they did make the new standard, even if few places practice the pure version) is this:

You suck... and that makes me sad.

Also I remember hearing this story, not quite sure if this exactly the version but:

A man walks into Fat Burger and orders a Double Fatburger, fries, and a drink.

Man only has $3.15 but the total comes to $7.15. The manager tells him he’s going to remove something from his order.  But the man insisted to have it all.

The manager doesn’t want to lose the customer so he walks out and finds a dead squirrel off the street.  He makes the burger by cooking the squirrel and putting it on a bun and hands it over to the man.

So if you draw the analogy of the story with the scenario above, it clearly seems that team compromises the quality just to deliver the product on time.

In order to achieve the unrealistic deadlines, first thing teams do is to discard the automated tests and stops refactoring the code. Soon after their code resembles coding they did in high school and they are making a huge mess.

But mostly I remember the metaphor of the chicken and the pig:


(Here's Vizdos' page on the origin of the cartoon)

The metaphor was that developer are the "pigs" whose bacon is on the line, so to speak, while the other people involved were "chickens" without skin in the game, and so should be quiet observers during the daily standup, for instance.

OK, for one thing, that is a WEIRD metaphor. Way back when I sketched out a different final panel:

(Ken Schwaber was amused by the panel and asked to keep it.)

But that really tied into my problem with the metaphor; Product Owners and other non-devs DO have skin in the game, their jobs and reputations are at stake as well, and in some ways it's even tougher for them because they are dependent on devs and can't just "work harder" to get better results. (also true Scrum aims to guarantee predictability over time, and has relatively little to say about efficiency and timeliness.  As my team lead Steve Katz put it: "the process isn't about not getting fired")

I guess they've moved on from the chicken/pig metaphor anyway - it was a little too joke-y, and I think other people shared my view that non-dev stakeholders are still critical to the success of a project.

Friday, April 19, 2024


Marques Brownlee reviews the Humane AI Pin... "the worst product I've ever reviewed... for now"

The form factor reminds me of this chef's kiss detail from the movie "Her" - Samantha's form factor is basically that of a foldable smartphone, but Twombly uses a safety pin to give her a boost in his pocket so she can see the world:

 (Also Brownlee had the clapback of the year to someone arguing he shouldn't have been so negative about a new striving-to-be-innovative product - "We disagree on what my job is")



on leadership

the biggest threat facing your team, whether you're a game developer or a tech founder or a CEO, is not what you think

Brilliant article on leadership. It's long and gets into the weeds of the games industry, but there is a lot that is true for the whole corporate world.

It touches on one point that is much on my mind: so much of our corporate leadership is "make number go up" (immediately! but then also forever.) Corporations generally have a legal obligation to "increase shareholder value", and in general that's on a per quarter basis. Sustainability and long term viability are afterthoughts at best.

The article points out there's parallels in that and some USA policy decisions in Vietnam:
But when the McNamara discipline is applied too literally, the first step is to measure whatever can be easily measured. The second step is to disregard that which can't easily be measured or given a quantitative value. The third step is to presume that what can't be measured easily really isn't important. The fo[u]rth step is to say that what can't be easily measured really doesn't exist. This is suicide.
But then when you combine that with leaders who view themselves as capable of finessed big picture and aesthetic decisions as, say, Steve Jobs... well, they aren't always looking to the people reporting to them as potential Jony Ives - they want to go on their own guts.

So an organization has to thread the needle between "it only counts if it can be quantified" and "it only counts if it has good 'gut feel' to topmost leadership". I think you do that by building and then trusting the expertise of the people in the middle.

Tuesday, April 16, 2024

from "Headcrash"

"I mean." Uberman cleared his throat, adjusted his necktie, and began delivering his morning whine, which is clearly what he'd been intending to do all along. "This is, what? The third network outage this year?"

I stopped. "We're having some problems porting your database to our server, sir." I edged one step closer to the exit.

"I mean," Uberman scowled, "if I can't depend on your network, I'm screwed. Just totally screwed, you know?"

Then how come you're not smiling? is what I thought, but "We'll have it back up as soon as possible," is what I said.

"I mean," Uberman whacked his PC with his newspaper again, "we never had problems like this before MDE acquired us. Dammit, our old Applied Photonics network never crashed! Not once!"

"So I've heard." And heard, and heard, and heard! And if you gave me just sixteen users in a one-floor office, I could make this network look pretty good, too.

Bruce Bethke, "Headcrash"
"Headcrash" is kind of a no-account cyberpunk-y book from the mid-90s... the technobabble is pretty clumsy, but for some reason this passage has stuck with me for 20 years so I thought I'd post it - from time to time, its reminder that little toy systems can get away with things that projects you want to scale can't is useful.

Thursday, April 4, 2024

ux ideas!

 Some UX humor ideation from Sorn Iverson ...
Some of my favorites:

easy drag-and-drop sorting/reordering with no build system vanilla js using SortableJS

I've already linked to a defense of making webapps without a build system - it really is great for long term sustainability and updates, and PHP + Vanilla JS are actually really powerful tools these days. You can even build dynamic page parts in a declarative style, using JSX looking string templates: 

const list = document.getElementById("myList");
list.innerHTML =>`<li>${item}</li>`).join("");

It's all right there in the browser these days!

One thing I didn't know how to do is add drag-and-drop reordering - at least not in a way that was mobile-friendly. (The browser's Drag and Drop API is one place where the usual abstraction between computers with mice or touchpads and mobile devices with touch screen breaks down.)

I knew of SortableJS but the README didn't make it clear that it works without a build system. ChatGPT straightened me out - using SortableJS is just a <script> tag away:

<script src=""></script>

(Hmm, there's no authentication checksum so you might want to grab the file and move it locally - I mean in general eliminating external dependencies is a good practice, tying into that long term sustainability: linkrot is real and ubiquitous, even well meaning CDNs broke projects depending on them as stuff switched from http to https...)

But back to sortable! Here's about the simplest example:
<script src="Sortable.min.js"></script>
<ol id="items-list">
    <!-- List items will be dynamically inserted here -->
document.addEventListener('DOMContentLoaded', () => {
    const items = ["Apple", "Banana", "Cherry", "Date"];

    const listElement = document.getElementById('items-list');
    listElement.innerHTML = => `<li>${item}</li>`).join('');

    new Sortable(document.getElementById('items-list'), {
        animation: 150, // Animation speed (milliseconds)
        onEnd: function (evt) {
            items.splice(evt.newIndex, 0, items.splice(evt.oldIndex, 1)[0]);

You can see it in action - everything is right there in the source.

So one slightly wonky aspect is that this kind of reverses the usual flow of declarative programming: Sortable update the DOM and then relies on the onEnd to make your internal state match. Still, a small price to pay for a mobile-friendly reordering solution; so much better than providing little /\ and \/ buttons!

You can go a little further and add some grabbable handles - here's how to make those three lines:
<span class="drag-handle">&#x2630;</span>

Add the reference to the Sortable options object:
handle: ".drag-handle",

and then a little CSS:
  ul {
   list-style-type: none;
   padding-left: 0;
 .drag-handle {
    cursor: grab; /* Changes the cursor to indicate movability */
    padding-right: 10px; /* Spacing between the handle and the text */
    user-select: none; /* Prevents text selection */

  /* Style the drag handle on hover and active states for better feedback */
  .drag-handle:hover, .drag-handle:active {
    cursor: grabbing;

Here's a working example of that.

Finally, if you DO rerender the list, you should probably hold onto the returned Sortable object and call .destroy() and then reapply. That's obviously more tied into whatever app you're actually making, but here is a basic destroy/rerender example as well, which is a bit closer to my usecase.

Wednesday, April 3, 2024


As a kid I wondered if you could make a robot trumpet player. The answer is now yes. I wonder how the cyber-embouchure works... (you can google up a robot sax player as well...)

Related Diesel Sweeties comic 10:

dangerous times

A while back I posted I’m harvesting credit card numbers and passwords from your site. Here’s how. a fake (or was it) description of how the overwhelming amount of npm-ish dependencies can make your webapp vulnerable, if a bad actor makes a helpful looking tiny utility (that the framework you like uses, even if you don't see it as worthwhile) and covers their tracks well. 

What we know about the xz Utils backdoor that almost infected the world is along the same lines, except i can't preach the gospel of "use fewer dependencies!"

None of this is new - the seminal Reflections on Trusting Trust - where a trojan could be snuck into a C compiler, covering its tracks all along the way - is 40 years old. But it's scary.

Related: You Are All On The Hobbyists Maintainers' Turf Now. The business world has absolutely embraced the Open Source paradigm - or at least decided to take freely of its fruit, and so the risk of poisoned flowers is there, even as more and more we depend on the good will "doing it for the reputation and to scratch my own itch" work of fewer and fewer - or as XKCD put it:

Monday, April 1, 2024

ObHack: see if I've hit quota

 I know I've mentioned Usenet's alt.hackers and "ObHacks" before... the latest is this:

My main VPS is pretty old (I'm migrating to a new one) and it doesn't do a good job of letting me how close to my disk quota I am - but when I start having problems, the clearest telltale is that if I try writing to a file from terminal, the file is made but is zero bytes.

But on that same server I run my personal start page, so many times during the day I'm going back to that site. So now the script that generates that page tries does this:

// Get the current Unix timestamp
$timestamp = time();
// Write it to a file named "timetest.txt"
file_put_contents("timetest.txt", $timestamp);
// Initialize $bodyclass with an empty value
$bodyclass = "";
// Open the file and read the timestamp
$readTimestamp = file_get_contents("timetest.txt");

// Check if we can open the file, if it's not empty, and if the contents match
if ($readTimestamp === FALSE
        || $readTimestamp == ""
        || $readTimestamp != $timestamp) {
    $bodyclass = "alert";

and I made the body.alert CSS to be bright red, so I'll see that something is up.

Heh, that piece of PHP reminds me of a thought I had recently; in general I don't adore TypeScript because while I like having JSON arguments described, there are better ways to do that, I find the syntax makes code a bit harder to read, and also there's more of a chance of a false sense of security, since you don't REALLY know what types are going to come back from a given endpoint at runtime.

My observation with that is that 90% of the typing issues I *do* have in JS would go away if "+" always meant addition and not string concatenation. Which is how PHP does it. But then I realized that PHP only gets away with supporting both $string.$concatenation and $object.key lookup syntax because it prefixes its variables with "$", otherwise you'd have to do object["key"] only since object.key would look like a lookup reference.