Author Archives: Lou Franco

Minimum Blog Feed Criteria

There was a post on HackerNews recently asking for everyone to post their personal blog. A few days later, some people had hacked up projects based on that data, including this OPML file, which you can import into a feed reader to follow all of the blogs.

I imported it and realized immediately that there were way too many to follow, so I started to cull them. I still have a long way to go, but I noticed a few things that made me want to delete feeds from my list immediately.

Here’s my list of things your feed should have:

  1. A title. For some reason, there are a bunch of untitled feeds. The <link> tag has a title attribute, and I’m pretty sure that if you leave it blank, most readers will pick up the site’s <title> tag.
  2. The full post. I don’t know if it’s intentional or just a default of some blog software. If you have a feed, I recommend putting the full post in it.
  3. A recentish post. I know it’s hard to keep a blog up-to-date, but if you are going to add your site to a list, go put up a new post if your latest is very old. Even if it’s just a short intro and a few links to your best posts.
  4. Not too many posts. I possibly post too much, but there were a few blogs with several posts each day. They were short posts, but I still found that they dominated my unread list too much, so I ended up deleting them.

There were other reasons I deleted blogs, but most of them had to do with the general topics of the blog, which were just not interesting to me personally.

Thinking Fast with Keyboard Shortcuts

The book Thinking, Fast and Slow [amazon affiliate link] by Daniel Kahneman describes our brain as having two thinking systems, a fast one and a slow one. The fast system is automatic and multitasking, while the slow system is methodical and single-focussed. When you are doing something complex, you are usually concentrating your slow system on the main problem, while the fast system can be doing several related (and even unrelated tasks).

This is the main reason I try to memorize and practice several keyboard shortcuts for the programs I use every day. I am trying to get as much of the mechanics of the code editing into my automatic, fast thinking system.

There is a common belief that mousing is faster than keyboard shortcuts, which probably originated with this AskTog article:

We’ve done a cool $50 million of R & D on the Apple Human Interface. We discovered, among other things, two pertinent facts:

  • Test subjects consistently report that keyboarding is faster than mousing.
  • The stopwatch consistently proves mousing is faster than keyboarding.

This is probably true for the general case and for when the user is learning a new UI. But, the study, Comparison of Mouse and Keyboard Efficiency, suggests that:

[…] for heavily-used interfaces, keyboard shortcuts can be as efficient as toolbars and have the advantage of providing fast access to all commands.

For me, the key is that shortcuts have to be able to be deployed with no conscious thought.

Programming often requires you to keep several interrelated thoughts in your head until you get the code written and working. For example, even for simple web UI blocks, you have to think of the semantic structure of the tags, the layout, and the style. To write that code, you will have to possibly jump through a few files and parts of those files. So, to keep from adding more cognitive overhead, you want to make the manipulation of the editor as automatic as possible.

This is something I think that can never be accomplished with the mouse, but is possible for a small set of shortcuts. That set should be the most common actions that happen while you are actively programming. The goal is to keep your slow system and short term memory focussed on the programming task at hand.

For me, that is:

  1. Cut, Copy, Paste, Undo, Redo
  2. In-file navigation with arrows and modifiers (including using Shift for selection)
  3. Find and multi-file Find
  4. Show the current file in the project navigator
  5. Open another file, tab cycling
  6. Jump to the definition of the identifier under the cursor
  7. Comment (or uncomment) the current selection

I do these commands all of the time. I often need to string a series of these commands together. Doing the equivalent without the commands risks engaging your slow thinking system and breaking you out of flow.

Write While True Episode 25: Stopping vs. Quitting

I reread the book Art and Fear by Bayles and Orland and they had so many ideas for how to get people to make art, that it worked for me to start my blog going again, and then ultimately restarting this podcast.

For part two of this four part series on Art and Fear, I’m going to share the what they said that inspired me to not quit. Here’s the quote.

Quitting is fundamentally different from stopping, the latter happens all the time. Quitting happens once. Quitting means not starting again, and art is all about starting again.

That quote is really the inspiration behind season two, and the episodes I’ve made since I restarted.

Transcript

Observations on the MIT Study on GitHub Copilot

I just saw this study on GitHub Copilot from February. Here is the abstract:

Generative AI tools hold promise to increase human productivity. This paper presents results from a controlled experiment with GitHub Copilot, an AI pair programmer. Recruited software developers were asked to implement an HTTP server in JavaScript as quickly as possible. The treatment group, with access to the AI pair programmer, completed the task 55.8% faster than the control group. Observed heterogenous effects show promise for AI pair programmers to help people transition into software development careers.

The researchers report benefits to less experienced developers, which is at odds with this other study I wrote about and my own intuition. However, all of the developers were experienced Javascript developers, and not literally learning programming, which is where I think the more detrimental effect would be.

Using Zeno’s Paradox For Progress Bars

When showing progress, if you have a list of a known length and processing each item takes about the same time, you can implement it like this pseudocode:

for (int i = 0; i < list.length; ++i) {
    process(list[i]);
    // notifyProgress takes a numerator and denominator to 
    // calculate percent of progress
    notifyProgress(i, list.length);
}

One common problem is not knowing the length beforehand.

A simple solution would be to pick a value for length and then make sure not to go over it.

int lengthGuess = 100;
for (int i=0; list.hasMoreItems(); ++i) {
    process(list.nextItem());
    notifyProgress(min(i, lengthGuess), lengthGuess);
}
notifyProgress(lengthGuess, lengthGuess);

This works ok, if the length is near 100, but if it’s much smaller, it will have to jump at the end, and if it’s much bigger, it will get to 100% way too soon.

To fix this, we might adjust lengthGuess as we learn more:

int lengthGuess = 100;
for (int i=0; list.hasMoreItems(); ++i) {
    process(list.nextItem());
    if (i > 0.8 * lengthGuess) {
        lengthGuess = 2*i;      
    }
    notifyProgress(i, lengthGuess);
}
notifyProgress(lengthGuess, lengthGuess);

In this last example, whenever i is 80% of the way through, we set lengthGuess to 2*i.  This has the effect that the progress goes back and forth between 50% and 80% and then it jumps to the end.  This won’t work. 

What I want is:

  1. The progress bar should be monotonically increasing
  2. It should get to 100% at the end and not before
  3. It should look as smooth as possible, but can jump

An acceptable effect, would be to progress quickly to 50%, then slow down to 75% (50% of the way from 50% to 100%), then slow down again at 87.5% (halfway between 75% and 100%), and so on.  If we keep doing that, we’ll never get to 100% in the loop and can jump to it at the end. This is like Zeno’s Dichotomy paradox (from the Wikipedia).

Suppose Homer wants to catch a stationary bus. Before he can get there, he must get halfway there. Before he can get halfway there, he must get a quarter of the way there. Before traveling a quarter, he must travel one-eighth; before an eighth, one-sixteenth; and so on.

To do that we have to keep a factor to use to adjust the progress we’ve made (playing around with it, I found that using a factor of 1/3 rather than 1/2 was more pleasing).

int lengthGuess = 100;
double begin = 0;
double end = lengthGuess;
double iFactor = 1.0;
double factorAdjust = 1.0/3.0;
for (int i = 0; list.hasMoreItems(); ++i) {
    process(list.nextItem());               
    double progress = begin + (i - begin) * iFactor;
    if (progress > begin + (end-begin) * factorAdjust) {                   
        begin = progress;
        iFactor *= factorAdjust;
    }               
    notifyProgress(progress, lengthGuess);
}
notifyProgress(lengthGuess, lengthGuess);

The choice of lengthGuess is important, I think erring on too small is your best bet.  You don’t want it to be exact, because we’ll slow down when we get 1/3 toward the goal (factorAdjust).  The variables lengthGuess and factorAdjust could be passed in and determined from what information you have about the length of the list.

How to fix WCErrorCodePayloadUnsupportedTypes Error when using sendMessage

If you are sending data from the iPhone to the Apple Watch, you might use sendMessage.

func sendMessage(_ message: [String : Any], replyHandler: (([String : Any]) -> Void)?, errorHandler: ((Error) -> Void)? = nil)

If you do this and get the error WCErrorCodePayloadUnsupportedTypes this is because you put an unsupported type in the message dictionary.

The first parameter (message) is a dictionary of String to Any, but the value cannot really be any type. If you read the documentation, it says that message is

A dictionary of property list values that you want to send. You define the contents of the dictionary that your counterpart supports. This parameter must not be nil.

“property list values” means values that can be stored in a Plist. This means you can use simple types like Int, Bool, and String and you can also use arrays and dictionaries as long as they are of those simple types (e.g. an Array of Ints)

I ran into this issue because I tried to use a custom struct in the message dictionary, which is not supported.

Note: I made this post because google is sending people to Programming Tutorials Need to Pick a Type of Learner because it mentions WCErrorCodePayloadUnsupportedTypes incidentally, but isn’t really about that.

Pre-define Your Response to the Dashboard

A few days ago, I wrote about using Errors Per Million (EPM) instead of success rate to get better intuition on reliability. I also recently said that Visualizations Should Generate Actions. Sometimes it’s obvious what to do, but if not, you can think through the scenarios and pre-define what actions you would take.

Here’s an example. This is a mock up of what a dashboard showing EPM over time might look like. The blue line is the EPM value on a date:

The three horizontal lines set levels of acceptability. Between Green and Yellow is excellent, between Yellow and Red is acceptable, and above Red is unacceptable. When we did this, we thought about using numbered severity levels (like in the Atlassian incident response playbook), but we decided to use Green/Yellow/Red for simplicity and intuition.

We also pre-defined the response you should have at each level. It was something like this:

LevelResponse
GreenNone
YellowThere must be at least one item in the current sprint with high priority to address this until the level is back to Green. It can be deployed when the current sprint is deployed.
RedAt least one person must be actively working to resolve the issue and doing hot fix deploys until the level is back to Yellow.

The advantage of this was that these actions were all pre-negotiated with management and product managers. This meant that we could just go ahead and fix things (at a certain level) instead of items getting lost in the backlog.

When we created this dashboard, we were in the Red, but we knew that going in. We worked to get ourselves Green and in practice, we were rarely not Green. This is another reason to pre-define your response, as it becomes too hard to remember how to handle situations that rarely happen.

Writing by Speaking

A few weeks ago I wrote about the tools and materials of writing and concluded that using clauses to make interesting, well-ordered, complex sentences was a core skill.

I got this idea from David Lambuth’s book, The Golden Book on Writing [amazon affiliate link]. This is a book a lot like The Elements of Style [amazon affiliate link] by Strunk and White. Like Strunk, he was an Ivy League University English professor and turned his class notes into a pamphlet sized book.

Here’s another gem from the book:

Write down your idea as you would in speech, swiftly and un-selfconsciously without stopping to think about the form of it at all. Revise it afterwards.

I can’t easily write “as you would in speech”, so I’ve been trying to learn by speaking my writing. To be fair, extemporaneous speaking is also difficult, but it does feel like something that I can improve with practice. I talked more about the details in Write While True Episode 20: Extemporaneous Writing.

Costly Signal Theory Applied to Job Applications

If a particular job is your top choice, you should be willing to do more than is necessary to get it. In evolutionary psychology, this is called a Costly Signal.

A costly signal is something we evolved to show genuine fitness in a world where there has been an arms race between deception and deception detection. You prove your fitness to a skeptical evaluator by doing something that is relatively easy for you, but would be too hard for someone less fit. It has to be something that is hard to fake.

Because it can’t be fake, the first step is genuine two-way fitness between you and the job. In a normal job search, it’s likely that you will know this before the employer. So, if you feel like a job would be an excellent choice for you and that you would be the top candidate for it, your behavior should reflect this belief.

The extra work you do should be relatively easy, but not necessarily easy. If it feels like too much work, then that might be an indication that the fit isn’t good. I would caution that some people undervalue themselves. If you have this tendency, then I’d get an opinion from a colleague or mentor of what they think your chances are.

Related articles

Write While True Episode 24: Thousands of Variations

One of the things that got me back to podcasting after a two year break was rereading Art & Fear by David Bayles and Ted Orland.

This time, while I was reading it, I kept a lot of notes and found four themes that resonated with me and helped me get going again.

The first theme is very practical. It’s what they think is the secret to being prolific. For the past two months I have been applying it a lot.

Transcript