Sunday, February 26, 2023

“Whatever you measure will improve. This is a warning”

 I don't usually get very political on this blog, but here is a great point that ties in to follies of managing technical projects:

There’s a saying from computer science. 

“Whatever you measure will improve. This is a warning”

Whether it’s metrics you’re applying to employees, or unit tests of AIs, or fulfilling statistical victories. 

Want more lines of code written? Done, now no one writes short, snappy code and every if statement uses three different lines.

Want this neural net that’s learning how to walk to reach the furthest distance? Now it makes itself impossibly tall so that when it falls down, the top of it reaches further. 

Want more jobs? Well, the finger on that monkey paw is curling up as you speak. 

(via esoteric-merit on this tumblr entry)

Friday, February 24, 2023

curl up and die

Heh, on a small slack I'm part of someone was mentioning the old

curl https://some-util-site.com/whatever | bash

which is a way of bootstrapping certain software. And I know I trust too much software but that seems to be pushing it... especially since there are ways of detecting if it's curl piped to a shell

Tuesday, February 21, 2023

thinking about the reputation of unit tests

Sometimes in my recent round of job interviews, I would let it be known that I have an unpopular opinion- that unit tests - while useful - are overrated.  Based on the reaction I get from people -- and some biased googling I do -- it feels like I've stumbled into a bit of an Emperor's New Clothes situation - many coders seem to agree with my sentiments, but are reluctant to say so, because there is a larger group of influential people - either coders or managers - who I assume would say I'm spouting lazy and reckless nonsense.


Here are some ways I have of putting it:
  • An extreme focus on unit tests - especially at the cost of distracting from or replacing higher levels of testing, or assuming "% lines tested via unit tests is another word 'code quality'" is like obsessively inspecting all your individual Lego Bricks for cracks and defects. Yes, it's important to be building with solid bricks, but honestly that's not where the problem in your structure is going to show up! 
  • Bugs are EMERGENT properties of systems. A well designed unit should be just about "too small to fail" (It's a little bit like trying to solve a biochemistry problem by thinking about the physics of atoms, or an economics problem as chemistry. (since economics comes from psychology comes from neuroscience comes from biochemistry comes from chemistry comes from atomic physics.) Like some times the underlying levels ARE the best way of thinking of a problem, but often the issue is at a less fine-grained level.
  • The problems I see actually show up in production are coders coding along the "happy path" - and then that same "happy path" is what is baked into the setup of the unit test. (I wish instead of testing the units, we had much more emphasis on firming up the contract between the unit and its environment...) 
  • And as for coders writing their own tests - it's very difficult to persuade someone to do a really focused search on something they don't really want to find - i.e. flaws in their previous work.
  • Unit tests that are too fine grained are at risk for confirming a specific implementation vs actual functioning. A good unit tests confirms that refactoring preserves functionality, but if you're too hung up on verifying "it internally solved the problem this specific way" you lose that benefit.
  •  If that's the only testing you're doing it's like inspecting 100 trees and saying "yup, I know this is a good forest with a safe path"  
  •  Unit Tests tend to be an easy metric, with tooling set up to see which lines get hit in a unit test (a metric that is less common to be derived from higher level tests). So it's a bit like the drunk guy looking for his dropped car keys and is looking for them under the streetlight instead of where he dropped them down the street "because that's where the light is good". (Also, to be fair, unit tests are more reliable in setting up their little fakey mock-up worlds than higher levels of tests.)
But despite these views, I can't afford to be "That Guy", the perennial pain in the butt about it. When unit tests are some of the music I'm being paid to dance to, I will absolutely work to boogie down in the way my coworkers think wise, and put effort into making the same kind of test writing decisions I think that they would make. 
 
Plus, I also understand there are many possible benefits to unit tests and the accompanying mindset - it can get a coder to think more clearly about the inputs to the thing, it can make future refactoring feel safer, etc. There's definitely some strengths in a "test first" kind of mentality. (And I pride myself in reliable code... I am a very incremental coder, making sure each bit is solid before moving on. But my default habit would be to throw out those inputs and outputs I did developer testing with, while I think the fervent unit testers' impulse is to preserve that data in amber to make sure nothing changes out from underneath it.)
 
(And to be fair, I mostly do UI. And the best things to unit test are "functional" - clearly defined inputs and outputs. I.e. No Side Effects. But honestly, UI is all about the side effects! I.e. the side effect of what is on screen to the user. (And the flip side of that is like the one quote about how menu commands were essentially uncontrolled "goto" statements all over your code...)
 
And when I heard my manager's manager say "well we expect as unit coverage increases, the number of incidents in production will go down accordingly" I had to bite my tongue... there are SOME cases where the unit is indeed busted and not acting according to its apparent spec, but again, the real world bugs I witness are happening as the units are unhappy in their used context... (I'm always encouraging teams to keep a collective log about production bugs - why did it happen, and was there a unit test that would have caught it?)

I liked Mark Talbot's answer to the Quora "Why do many programmers think that unit testing is not worth it?" - in part -
The problem is that as soon as you replace some dependency with a stub or mock, you are no longer testing the system in the same way it works in production. All you have done is assume that your stub/mock behaves in the same way as the dependency it is replacing (at least as far as the unit under test is concerned) and then write your tests based on that assumption. But it is not valid assumption. If I come along and modify the real dependency (maybe it’s some 3rd party library that I’m upgrading) I have no idea at all whether your code really works with the new dependency, because all the calls to it in the unit tests are stubbed out. (And I’m not going to check all 500,000 lines of code manually - what is the point in automated testing if I need to do that?)

Or as I just recently put it: Unit Tests test Mocks more than they test your Units

See also some bits I grabbed on Joel Spolsky on Complete Test Coverage...
 
Since some of the people who are STRONG unit test advocates are pretty sharp - probably smarter than I am, to be honest -  I have to hope it's one of those "different ways of looking at the world" things - Douglas Hofstadter writes on holism vs reductionism and I think it's a good example of that - reductionists assume life is mostly a matter of making sure each part does it's little isolated job. But in general, I'm always more concerned about interactions from bringing those job workers together - so I think unit tests are not worth the esteem with which they are held.

the ergonomics of the soda can

 You don't realize how ergnomic the top of a can for soda is, how it's kind of shaped to the human mouth, until something like this happens...


There are other nice small design details, like how that lip at top also adds some stability when stacking, and how they have a 2:1 height/diameter ratio.

Tuesday, February 14, 2023

the joy of task lists

Last summer I wrote about todo'ing better, where I was moving away from cramming everything into structured lists with the app "2Do" and adding in "Tot". "Tot" is a simplistic text editor app that syncs really well across devices, but purposefully offers 7 spaces to work in. (FWIW, "SimpleNote" is still another well-syncing cross-platform app for text, and I use it for my "big pile of unsorted text notes" and have given up worrying about its junk pile aspect.)

Anyway, yesterday I was having problems feeling motivated, and I realized some of it was not getting enough reward for getting tasks done. The potential list of projects I COULD do is practically unlimited, so some days the only reward for getting the more critical or useful stuff done is the feeling of "but I still have more to do." 

The simple life hack was to allow myself an indulgent "DONE" list. Items can be simply cut from the main TODO section and pasted under the list of accomplishments. (Later I even brought it into my diary entry for the day.) Sometimes, when the prospect of "Todo Zero" seems incredibly distant and maybe even self-defeating, it's just nice to have a reviewable list of what I did manage to get through.

Of course options for Todo Lists has long been an interest of mine. One DOS-era program I've always been conceptually fascinated by (though not enough to figure out how to get it up and running on modern equipment) is Lotus Agenda:

It has its own cult following - especially for its clever auto-tagging. Definitely impressive pseudo-AI, reminds me a little bit of how amazed I've always been at Zork's Command Parser's ability to understand fairly complex sentences ("throw rock at the green dragon" vs the Verb-Noun THROW ROCK style parsers that were more common.)

Anyway, despite me posting about this a year ago, having forgotten and so having to research the name - I forgot again and wasn't even able to find the previous entry, so here are buzzwords: organizer, MS-DOS, todo, Leonard, free-form.


Monday, February 13, 2023

the future of ai assistants

One of my favorite books is Greg Egan's "Permutation City" - you can get the kindle version for like $4, and while it's old, it remains one of the most thoughtful speculations about what it might be like to be an uploaded person.

Before the book really gets into its themes of Artificial Realities, the "real world" - close enough to our own to be very recognizable - has a technology that has stuck with me, a really powerful virtual assistant called "Camel's Eye":

Upstairs, in the bedroom that doubled as an office, Maria switched on her terminal and glanced at a summary of the twenty-one items of mail which had arrived since she'd last checked. All were classified as "Junk"; there was nothing from anyone she knew – and nothing remotely like an offer of paid work. Camel's Eye, her screening software, had identified six pleas for donations from charities (all worthy causes, but Maria hardened her heart); five invitations to enter lotteries and competitions; seven retail catalogs (all of which boasted that they'd been tailored to her personality and "current lifestyle requirements" – but Camel's Eye had assessed their contents and found nothing of interest); and three interactives.

and later

She started again on the letter. After three drafts of the first paragraph – all eliciting the same response from Camel's Eye: You'll hate this when you re-read it later. Trust me. – she finally admitted to herself that she was wasted. She shut down everything and crawled into bed.

With what I've been seeing from ChatGPT, I think we are on the verge of having this technological capability. (Of course, with modern tech, there's always the question of who's interesting is the software truly minding...) 

The "real world" on the book had a lot of video conferencing, but projected that often people would prefer to use software reconstructions of themselves as avatars, ala Max Headroom.

Friday, February 10, 2023

shipping your org chart

Conway's Law states

Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure.

I think a modified version of that came out in stories about Elon's irritation at losing mojo on his own platform - 

“As the adage goes, ‘you ship your org chart,’” one current employee told Platformer. “It’s chaos here right now, so we’re shipping chaos.”

Heh. 

Thursday, February 9, 2023

more wordle cheating

In Wordle today, I was a little annoyed when I had 3 guesses in a row for the one blank I was missing. I checked and it turns out there were 6 5-letter words that matched the pattern I knew, so "in revenge" I made a new page of wordle off-by-one-letter families.

like if you have _EARS or _ILLS you're hosed, each has 12 possible values (bears dears fears gears hears nears pears rears sears tears wears years and bills dills fills gills hills kills mills pills rills sills tills wills)

Oddly, I posted this on my main blog only to find out that 40-years-ago today my then local paper published me and a bunch of other school kids as the ALA Superspellers. So while World is certainly spelling-adjacent, I have since decided I am ok being a terrible speller.

Wednesday, February 8, 2023

TypeScript, using as const for a map where the values are keys to a type

Had a problem with TypeScript at work - I had a map-like object where the values would tell you which field of an existing Type to check.  Here's a (admittedly still kind of confusing) example I made - 

type Qualia = {
  look?: string;
  smell?: string;
  taste?: string;
  sounds?: string;
}
const isIntoxicating =
(impression: Qualia, organ:'nose' | 'mouth'):boolean => {
  const senseForOrgan = {
    'nose': 'smell',
    'mouth': 'taste',
  };
  const whichSense = senseForOrgan[organ];
  return impression[whichSense] === 'intoxicating';
}

console.log(isIntoxicating({'taste':'intoxicating'}, 'mouth'));

So the idea is I want a function (isIntoxicating()) that knows only smells and tastes are intoxicating. So it takes the current sent of Qualia (what I'm experiencing) and lets me find out if an organ is being intoxicated by it. (So in this case I look up "mouth", which the function knows is associated with "taste") Ok bad example but whatever.

This tends to produce TypeScript warnings or errors ala Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Qualia' No index signature with a parameter of type 'string' was found on type 'Qualia'

So the problem is TS isn't smart enough to know that "senseForOrgan" is fixed, and won't be tampered with (remembering that a const array still lets you change the contents of that array, weirdly) The trick is to reassure it by putting "as const" after: 

  const senseForOrgan = {
    'nose': 'smell',
    'mouth': 'taste',
  } as const;

Which tells TS that this isn't going to be changed. 

In a way, that "as const" is a little bit like Object.freeze(), except at TS's compile time rather than runtime. 

Here's more on 'as const'.



Monday, February 6, 2023

one page calendar

 Ethan Siegel says This one-page calendar will change how you view the year:

I've always enjoyed alternate visualizations of time and this one is pretty keen. 

A few minor notes:

  • it's easy to see which months have a "Friday the 13th" - in fact it's always the leftmost stack of months, since months that start on a Sunday will have that date
  • this calendar lacks a bit because it doesn't remind you which months have 30 days vs which have 31, so you have to use that rhyme (or the counting on your knuckles trick) or look ahead to the next month.
  • It's not clear to me why it has 4 rows for each months stack... as far as I can tell, only three months a year will share a starting day (Feb/Mar/Nov most years, Jan/Apr/Jul on leap years)

Here is an browser based version to play with.


Friday, February 3, 2023

the mysterious case of the switch(true) statement

 At work, the PO (who honestly probably has the best overall view of the Designers in Figma, Devs in CSS that is the heart our project) came up with some complex logic to deal fixed widths and heights vs flexbox (Figma is still at its heart a vector tool, and while it has some powerful tools like "hug" (i.e. stretch to fit your children) vs "fill" (i.e. stretch to fill your own parent) that map up sort of ok with CSS's flexbox, there can be a lot of weird edge cases.

One of the developers encouraged the PO to rewrite the nested if() statements as switch/case. But he came up with an interesting design that I hadn't heard of before, rather than

switch(someVar){
  case 'someValue1':
  break;
  case 'someValue2':
  break;
}


He did something like 

switch(true){
  case (someVar == 'someValue1' && someOtherConditional):
  break;
  case (someVar == 'someValue2' && someOtherConditional):
  break;
}

I had to set up a codepen to answer "does that even work?" but javascript being javascript, of course it does. (I suspect the older langauges like C wouldn't allow such shenanigans)

This article goes over some of the pros and cons... you can absolutely do some stuff that's more readable than a pile of nested if/else structures, and being able to run a function rather than compare to a primitive function might be useful.

Thursday, February 2, 2023

the ease and the lerp

I've talked about easings before, a decade ago in a jQuery context and then five years ago based on Processing.

So an easing is a way of translating a linear motion into something smoother and more organic. In general they work as a function, taking in an input from 0.0 to 1.0 (generally a value that's been changing linearly, 0.0, 0.1, 0.2, 0.3...) and outputting a corresponding "where are you at now" value (with some easings, this won't be limited to be stuck between 0 and 1, which allows for a little overshoot and correction)

Easings.net is a cute little site with a pile of these functions. (If you're writing in plain old javasript you will have to remove the "number" typings...)


P5 provides a nice function called lerp() to ease translating the "between 0 and 1ish" values to the actual start (i.e. 0.0) and end (i.e. 1.0) value you want:

lerp(startX,endX,easingFunction(timerValue));

I set up a small p5 sample, and you can replace easePatakk (from this tumblr post) with easing.net's "easeOutElastic"

Easings are also available in CSS. I admit I use them a lot less now than I did back in the jQuery days - there's always something a little weird about treating an verb + adverb (like easing) as a noun (CSS descriptor).