02 Mar 2020

Rough project size estimation

History / Edit / PDF / EPUB / BIB / 3 min read (~415 words)

How do you estimate the size of a project roughly?

When I am asked to provide a rough estimate of the required effort on a project with a lot of requirements or user stories, I first want to make sure that my estimate is in the right order of magnitude. That means that I want to estimate a project that takes 1-10 weeks to be in that range, but not estimate less than a week or more than 10 weeks. Similarly, a project that takes one or more years should not estimated as a job of a few weeks.

My orders of magnitude are as follows:

  • 1 day
  • 1 week (5 days)
  • 1 month (20 days)
  • 1 quarter (60 days)
  • 1 half-year (120/125 days)
  • 1 year (250 days)

As such, when estimating a task, I will say that the task will either take 1 day, 1 week or 1 month. In general, any task that is estimated at 1 month long (or above) needs to be broken down into sub-tasks as it indicates that the task is hiding a lot of complexity.

With this kind of approach, one can estimate that a developer can do approximately 250 small tasks (1 day), 50 medium tasks (5 days) or 13 large tasks (20 days) per year.

Start by creating an estimate of the overall project without thinking about any of the underlying tasks. This is done to have a quick idea of the scale of the project.

Then list and estimate the tasks that will need to be accomplished to complete the project. You might be forgetting a few, but it is fine at that moment. Think mostly of the most important tasks and also the riskiest.

If the sum of the efforts you estimated is in the same order of your original project estimate, then you are done. If not, then you need to investigate and explain what led you to either over or under estimate. Did you forget to estimate some tasks? Did you ignore some tasks when you did your initial estimate? What were the assumptions you made that were right/wrong? Once you are satisfied with your explanation, you are done with estimating.

02 Mar 2020

Quickly recording notes using VS Code

History / Edit / PDF / EPUB / BIB / 3 min read (~417 words)

I want to quickly take notes in the same file throughout the day using VS Code. How do I do that?

My approach has been to use my VS Code extension Run Me, which I use to bind a keyboard shortcut to one of the commands I created. In my particular case, on any VS Code window I can press CTRLNumpad 2 and it will open a file under the following path: buffer/YYYY/MM/DD.md, where YYYY/MM/DD is replaced with the year/month/day. In this file I record all my notes within the day.

I use the following snippet, which I can trigger using dt, then pressing TAB. This replaces the dt string with a string of the form YYYY-MM-DD HH:MM:SS, which is the current year-month-day hour:minute:second.

{
    "Datetime": {
        "scope": "",
        "prefix": "dt",
        "body": [
            "$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND"
        ],
        "description": "Date time"
    }
}

I also use the Script Commands extension to do something slightly more complicated, which is to create strings of the form 2020-03-02 21:19:05 [nid://952], where nid://952 represents a unique note id (nid). The number that is generated is unique and is tracked by storing the last generated number in a text file that is read/written on each call to this command. A cheaper approach could have been to simply use the timestamp as unique note id. One downside of the timestamp as note id approach is that you don't have an idea of how many notes you've recorded so far, other than searching your notes and then counting the number of unique instances.

01 Mar 2020

Read more books

History / Edit / PDF / EPUB / BIB / 2 min read (~217 words)

How can I read more books?

Make it a priority to read books. Replace some of the existing habits you have with reading books instead.

If you like to spend time reading reddit or hackernews or watching videos on youtube, replace that with reading a book. Of course, it's easier said than done. The best way I've been able to transition from those activities to reading books was to progress slowly. Don't replace reading hackernews one day by reading a book instead. Instead, simply spend 5, 10, 15 minutes reading a book, and then the remainder of the time on reading hackernews. Spend the same amount of time every day reading a book for a week. When a week has passed, increase that amount of time slightly (e.g., go from 5 minutes per day to 10 minutes per day).

As you increase the amount of time you read, you will find it easier and easier to spend time reading instead of doing other activities you might consider harmful or less valuable.

01 Mar 2020

Visual Studio Code templates

History / Edit / PDF / EPUB / BIB / 3 min read (~418 words)

I use VS Code and I'd like to insert templates into my documents. How do I do this?

In VS Code, the concept of templates is called snippets. It is fairly easy to create a snippet, so I won't go into the details. Here's an example of a snippet I use to insert the date and time quickly into my documents.

{
    "Datetime": {
        "scope": "",
        "prefix": "dt",
        "body": [
            "$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND"
        ],
        "description": "Date time"
    }
}

With this snippet, I only have to type dt and then press TAB and dt gets replaced by the current date and time.

I use snippets to create the template of my questions and problems articles. My current approach is to open a non-existent file by calling code /path/to/new/file and VS Code opens the editor with this file. I can then write the content of this file, which will not automatically save until I manually save. Once I'm happy with the content of my article, I manually save, which means that in the future, any edit I make and then have the editor lose focus will be automatically saved and commit to git (my current workflow).

One of the things I don't particularly like with the current implementation of the snippets system is that the body needs to be a list of strings, where each item represents a new line. It is possible to create a single entry and use \n and \ to format the string, but that is not a clean approach. Those are limitations of jsonc. If it was possible to link to a file, then it would be "easy" to create a clean template.

29 Feb 2020

Improving the performance of a slow click CLI

History / Edit / PDF / EPUB / BIB / 3 min read (~494 words)

My click CLI is slow, even just to show the help. How do I make it go faster?

In most cases, the reason your click CLI is slow is that you have large imports at the top of the files where you have declared your commands.

The typical pattern is as follows:

cli.py

from train import train
from predict import predict

@click.group()
def cli():
    pass

cli.add_command(predict)
cli.add_command(train)

train.py

import click
import pandas as pd
import torch

@click.command()
def train():
    pass

predict.py

import click
import pandas as pd
import torch

@click.command()
def predict():
    pass

Notice that in both these files we import pandas and torch, which can account for a large chunk of script execution time simply due to importing them. You can verify that by simply running python -X importtime train.py 2>tuna.log and using tuna (run tuna tuna.log) to inspect the results and convince yourself.

The suggested pattern is to move the imports inside of the function itself, as such:

train.py

import click

@click.command()
def train():
    import pandas as pd
    import torch

    pass

predict.py

import click

@click.command()
def predict():
    import pandas as pd
    import torch

    pass

This will shave off a large amount of time spent importing those packages (pandas and torch). They will only be loaded when you need to run the command itself, not every time you invoke the CLI.

Another pattern which is more complicated is to move the logic of the functions in separate files. This is done to avoid the common mistake that will happen over time that developers will add more logic in those command files, adding imports at the top of the file and slowing the CLI again. By moving the complete implementation to a separate file, you can have the imports at the top of the file and it is not possible to make this mistake again.

train.py

import click

@click.command()
def train():
    from train_implementation import train
    train()

train_implementation.py

import pandas as pd
import torch

def train():
    # Implementation is now here
    pass