Author Archives: Lou Franco

Progress Bars, not Time Blocks

In Deep Work [affiliate link] (and his other works), Cal Newport has been a proponent of time blocking. He even sells a planner based on his method, which is probably the best place to learn about it. In short, he gives each hour of his day a specific task. In the happy case, this works well, but it breaks down when you get interrupted, get blocked, want to extend your time, or lose energy. He does address all of that, but that’s where I have found his method to break down for me.

Instead, I’ve been doing something my friend Joel Mazza taught me, which is based on the idea of a guiderail made up of 30 minute time blocks. Like Newport’s time blocks, there are things in your day that need to happen at a specific time, usually meetings, so those go on the guiderail in the appropriate place. After that, the system diverges in that we will build up our daily tasks and assign them an amount of time, but not a specific time on the guiderail. We just need to make sure we have a reasonable amount of work that fit in our day (and make sure to have some buffer).

Instead of letting the clock decide what we will do each half hour, we can pick based on our energy (or at least, that’s what I do). I had a half-hour before lunch, and so I am writing this post. When lunch is done, I have a lot of meetings in the afternoon, so I am doing it now, so I can be free after. Earlier today, I tackled some book editing, and I have a 12:30 accountability meeting to get back to it, so that’s why I felt free to switch.

There’s a lot more to it, but the key ideas are progress and flexibility.

I Prompt Cursor Based on My Progress Bar

In Build a Progress Bar for Your Work I explained how I take a task and break it down into subtasks. Each subtask then becomes a commit. A benefit I didn’t mention is that I can look at the commits and see the time it took to do each task, which will be a good way to adjust my estimate going forward. Unlike in Using Zeno’s Paradox For Progress Bars where you have no clue how much time is left, I actually do have some idea.

Having this progress bar of subtasks has also been useful in working with Cursor. I use each of those subtasks to drive my prompt. Here’s an example:

I am working on an app that has a thing like a feed with a concept of posts and reactions, like slack or discord. My stack on the server is MySQL, a TypeScript based ORM, and a TypeScript based GQL wrapper that is served by node and Apollo. My Tasks/Subtask progress bar looks like this

  1. Add Reactions to Backend
    • Create reaction entity and relate to shared objects
    • Create SQL migration
    • Create ORM service function to react to a shared object
    • Test the service function
    • Update shared object ORM getter to have a reaction summary
    • Test the reaction summary
    • Add a field resolver to the shared object resolver to get the reaction summary

Having that, I use each sub-bullet to create my prompt. I give Cursor a lot more information though. As an example, here’s my prompt for the first bullet (I also need to put in the context files)

Add a reaction.entity.ts with a UUID id, a many to one relationship with sharedObject (and do the reverse in sharedObject). Have a reaction type (string), a User, a createdDate (like sharedObject) — do a unique that is like this UNIQUE (shared_object_id, user_id, reaction_type), but in TypeOrm syntax at the top of the class

From that it knows what fields I would likely want to index, and adds that too. It picked the delete rule I usually use (CASCADE), and it updates the User entity and SharedObject entity to have the reverse relations. It made some slight errors, but they are easy to check and fix.

Once I have that, I make a commit and move on to the next one. In that case, I use an external script for migration, so I just do that myself, and commit.

I go on like that, picking the next thing in my list, coding or generating and fixing, and then making a commit. The result is a PR that looks the way I want (not just the whole change in one commit) in the order that makes sense for a reviewer. I do this even though I am the reviewer (as I wrote in Pull Requests for One) because I do actually do a review and I want it to be easy.

This activity (to me) is very much like programming, which is what I was getting at in Can non-programmers use Cursor? A complete non-programmer? Probably not, but I do think someone could do this if they had some programming skill. The main thing I am doing is what I said in Programming is Disambiguating: “Programming is taking a nebulous problem and breaking it down, understanding it, trying to find building blocks, and then building up something that solves the problem.” Those building blocks could be prompts or code, it doesn’t matter, as long as it solves the problem.

Any Thing Can Be a Blog Post

I’m catching up on this blog (I Write for Yesterday when I skip a day), because it’s been hard for me to think of topics. For me, it’s February 7, and I just wrote the February 4 post about the Fantastic Four teaser’s portrayal of AI a few minutes ago. I actually had the idea for this post first, which was going to incorporate yesterday’s, but I broke that out to stand-alone.

This is all to say, I think it’s always (or very often) possible to turn anything you think of into a blog post, or any Thing-based media, if (like me) you spent a lot of time watching YouTube recaps of the FF teaser. I wasted a lot of time on February 4th doing that, but I believe in Monetizing Waste, and even though this blog doesn’t make money directly, I got two posts out of it, so that’s enough.

Review of the AI in the Fantastic Four Teaser

I’ll revisit this review when the movie comes out, but this is next in my series of limited perspective movie reviews, where I take a very narrow look at a movie. I haven’t done this in a while, but of the ones I have, the Oz: Review of wizard projection technology has been the most popular.

Here’s the teaser:

We don’t exactly what year or timeline this is in. It feels like space travel is relatively new, and the commercial TV sets are ancient, so the 60’s, but in an alternate timeline. They still seem to have giant mainframes with reel to reel tape. In the comic, and in this movie I’m sure, Reed Richards and the FF have technology far more advanced than the rest of the world, so what we see in their home wouldn’t be typical. I want to focus on the robot, HERBIE.

Using just the information in this trailer, HERBIE can make sauce and is able to understand natural language. We achieved that level of AI a couple of years ago, so he’s about 70 years ahead of his time. But, I don’t think the cloud infrastructure we have is available to the FF, so this might all be local, which is impressive. Maybe Reed has a super computer on a LAN, but that would make it hard for HERBIE to leave the Baxter Building (which we don’t see, so it’s possible).

I also don’t know if the tape reels on HERBIEs face are functional or decorative, but if his AI relies on that, we have to assume that Reed has built something fundamentally different from our LLMs, or has had gains on memory usage many orders of magnitude beyond what we have. Or, he might have just figured out how to do a lot more with tape. When I was a kid, we had the 2XL, which was based on 8-Track tapes.

I look forward to seeing if there’s any in-movie explanation of HERBIE, until then, I think it’s just tricks like the 2XL. Pop in a tape, it makes marinara, and you can talk about marinara. Pop in another and it’s taco night.

Sweep Edits for My Book

I learned about the concept of sweep edits from Joanna Wiebe’s talk at a Business of Software conference. The basic idea is that when you edit a piece, you pick one kind of thing to fix and do only that in a sweep. Then, you go back to the beginning and pick another problem and do a new sweep.

I hired an editor to help me with Swimming in Tech Debt, and I’m looking through the revisions and suggestions and trying to figure out a process for making the next draft. I was talking to someone about this earlier, and then I remembered that I should do sweep editing. I do this for blog posts, but for some reason, it didn’t occur to me right away when I got the edit back. The revisions and comments beckoned me to address them serially, but I should not do that.

Here is what I think my sweeps will be

  1. Make factual corrections. The editor might have inadvertently changed the meaning of something with a change. I want to get the text back to being accurate.
  2. Address comments. The editor made suggestions and I need to just go through each comment and decide what to do. I need to either reject the comment or add it to a todo list. I’ll resolve the comments that don’t need more writing and leave in the ones that do.
  3. Relate the text to my central metaphor of swimming rather than drowning.
  4. Read it aloud. I want to make sure it still sounds like me.

After this, I will have a list of things I need to write, so I’ll do that list one by one. I will try to group them into sweeps that are of a similar type and then amend the above list to make it easier for the next chapter.

I am sure that this list is wrong, but it’s a starting point for now.

Can non-programmers use Cursor?

I wrote Can non-programmers make applications with AI? last month. TL;DR: Yes. But, I hadn’t used Cursor yet. Now, I’m pretty sure that to use Cursor well on a real project, it helps to know some programming. But, if you do, it’s way more useful than it would be to an expert, which is saying something, because I find it very useful.

As an expert, my coding session today was maybe 2x faster for the same code. But, a non-programmer would have taken weeks to do what I did (if they could even do it). I think they have a chance to get close with prompts—I almost did, and they would try harder.

For what I needed to do today, in the first 5 minutes, Cursor did a good first pass. I fixed its syntax errors and the result “worked”. It looked terrible (this was implementing drag drop in a React app)—it took me a couple of hours to get it exactly how I liked it and then polish the code. But, getting me started quickly gave me a ton of momentum, and then I had time to make it exactly how I wanted it.

For a less skilled programmer to do this task, I think the first five minutes goes the same way. I know from experience, that it’s easier for me to just fix little problems, but I think it could be done with prompts. Then, the rounds of successive improvement were helped by autocomplete, but I initiated all of it. I relied on my knowledge of CSS and React to fix issues. I haven’t had good experience with the LLM’s for this—they can’t “see” the problem in the browser yet, and all of my problems were UI nitpicks and complicated Drag/Drop issues (not a static render I could screenshot or easily describe). All of the different modes of Cursor LLM integration have strengths for different uses—but some rely more on your ability than others.

From my use, it feels like knowing some programming is required. But, if it took a less skilled person from 2 weeks to 1-2 days, that’s more like 10x for them. What’s more, I go from 20x faster than them to 4x for this task, and they have more to improve, where my gains are asymptotic.

Three Days of Cursor

I tried out Cursor three days ago. But, before I did, I really did try to give GitHub Edits a chance. I used it for a few things, and it was more trouble than it was worth. I mentioned this to a friend at lunch on Tuesday and he asked why I hadn’t tried Cursor yet. I said I was worried it would interfere with my setup too much, but he confirmed that it reads your VSCode settings and extensions and (for him) just works. I use extensions as Tech Debt Detectors, so they are important to me.

So, the next day, I gave it a try. At 3:15 on Wednesday, I started the download. By 3:20, it was installed and working as I expected. I wrote a prompt to do the thing I needed to do next and its change was perfect. It was 3:27.

My next request did not go as well, but it was a complicated one involving a package I wanted to try. It would not install properly, and neither I nor Cursor could figure it out.

Since then, I’ve been using Cursor a lot. There are three main ways it’s better than GitHub CoPilot.

  1. The Generation from chats is much better than the GH equivalent.
  2. The autocomplete doesn’t require me to place the cursor. It anticipates what I am going to do and offers changes in different parts of the file. Sometimes all at once.
  3. There’s a hotkey for inline generation that works well too. I had been doing this with comments, but this is better because it just lets me type (without interruptions) and it knows I want it to start a generation when I’m done.

For all of these features, I feel very much like I am still programming. I am sequencing the work. It feels like it’s reading my mind since I do know exactly how to do what I am asking, but it’s saving a lot of typing.

This is helped by my app’s code being very regular. There’s only one way to do DB code, one way to wrap it in GQL, one way to call it. My UI is regular. The code has established patterns, and I put example files in the context before I prompt (and mention that I want it done like those files).

The main way it helps me though, is to keep me in flow. I am not constantly juggling files and typing out simple things. I say I want a table with an id, name, and a specific relation, and it knows my id is a UUID, and how I typically name relations. I say I want a cross table and it knows to set up the relations between the tables and the new one (in the way I have done it before). It intuits that I want cascading deletes without me asking. It’s just a lot of little things that save time and let me move on to something else.

January 2025 Blog Roundup

In January, I posted every day. Here were the themes:

I brought my podcast back. I kept it in season 4, which is about the lessons I’m learning while writing a book about tech debt.

Writing every day is part of my marketing strategy for the book. I outlined that here:

I wrote a bunch of articles about Code Review. I had written If code reviews take too long, do this first in December. Here are some follow-ups.

I did a series of 3 posts about how to triple the number of posts you write:

I wrote a few posts about AI

I’m also proud of this toot:

Post by @loufranco@mastodon.social
View on Mastodon

Which I thought of while revisiting We Keep Reinventing Injection Attacks

I’ve been getting interested in helping entry-level developers more. These posts are what I think about it:

Write While True Episode 46: Write as Yourself to Yourself

This is the 7th episode of season four. I started this season in January of 2024. My intent was to document the process of writing a book. But even though this season is over a year long, there have only been 7 episodes, and that’s because I took a 9 month break. I want to talk more about what happened during that break, and how I was derailed from my plans, and how I recovered.

Transcript

How to Increase Story Points Per Sprint

Story points are not a basis for measuring and improving productivity because points are just an abstract measure of time. That’s why I said you should Be Skeptical of Points-based Productivity Claims. Any systematic productivity improvement would decrease the points for a future story, and the velocity would go back to a steady state.

If you had a way to compare stories over time to each other, you might see improvement in an individual story. If you literally are doing the same story over and over—like, for example, a set of recurring tasks—then, you could absolutely see its points decrease over time if you automate it. So, one way to get more done per sprint is to automate repetitive tasks, but once you do that, the points assigned to that task will go down and the velocity will not change. But the thing to look at is the comparison of this story in your sprint with its past incarnations, not velocity.

This is why I Estimate Using Time, not points. They are the same thing, but everyone understands time, and no one understands points. If you reread the first two paragraphs, but substitute “hours” instead of “points”, then they are obviously correct. If you automate a task then the number of hours it takes goes down—no one disagrees with that. If I use CoPilot to get systematic productivity, then my estimate of the number of hours it takes to do something will go down. Points obscure this.

There is a problem with using time (which is also true with points, but it’s just glossed over), which is the difference between work time and calendar time. If you estimate with work time, and report that, you will confuse people, because the only time that matters is calendar time. But, Story Points are often a proxy for work time, so I’ll assume that’s what it is for you too.

Given all of that, it’s easy to see how to increase the number of points done in a sprint. You need to either create time or decrease the difference between work time and calendar time. If you do that, you will find more stories get pulled into a sprint and get done, which will show up in velocity because it probably won’t cause the points for a particular card to go down, because most teams estimate points using work time.

So, how do you create time? Easy. Hire more developers. Despite what you have heard, you can add developers to a team to get more done, as long as they don’t need to communicate with each other.

To reduce the difference between work time and calendar time, you need to concentrate on everything that’s not sprint work. The main culprit is unnecessary meetings, but another is long waits for feedback. There are lots of times developers might need to wait, but waiting for code reviews is probably the biggest one because it happens to everyone all of the time. To work on that, read: If code reviews take too long, do this first.