I’ve had the past 11 or so days free to work on some personal projects and had some ideas for a personal to-do list app I’d created and been slowly tinkering on and off for the past 2 years. Little did I know I would find out just how complicated it can be to decide what I should do next in my life. I’m not even talking about big life-changing events, but the little things done in life - the chores, the tasks, the toil.
2 years ago I wanted to build an application that could effectively model preventative maintenance and reoccurring tasks in my life, define priorities. I don’t know about you, but I used to get anxious looking at my to-do list. Too much WIP means bad service for just about any priority queue (which comes in many forms - from to-do lists, to process flows in an organization, and even computer programs). I wanted the app to cover a very wide scope, but also capture all the little details. And most importantly, a to-do list where I don’t need to review it then pondering what to work on next.
The premise is simple, I define a task template for reoccurring tasks, anything from changing the oil on the car, to cleaning the windows, servicing the AC unit, and even little things like cleaning the toilets. The task template would define how often the task would be automatically added to my to-do list, it would contain a starting weight value to define the priority of the task, and it would also define a math function that defines the rate at which the priority increases over time. I whipped together something basic in Go and a SQL backend, but it worked and met the basic requirements. Like I said at the start of this paragraph, it was simple.
Parameters of templates include:
- Task Name
- Starting Weight
- Weight Increase Function (to age out older tasks)
- Interval
This was the result.
I quickly found out that a simple model just doesn’t work for what I was trying to accomplish. There were a lot of problems that I’ve worked through over the years and I’ve learned a lot from it.
The most recent work I’ve done in the past few days, I wanted to have a better graphical view of what I need to get done and when I can expect to have time to work on things and spot out any flaws for how the app may be scheduling my time and help me get more things done but I wanted to experiment with an interesting approach - more on that later.
Real life is not so simple
After I used the app for a few weeks and had collected some data that could be analyzed, I then realized that sometimes completing or needing to complete (prerequisites) one task influenced the properties of another task. For instance, I would always prefer to clean out my fridge before I left to go get groceries. I realized it allows me to both make space for new incoming groceries, but it also gives me a really quick inventory of what I have to add any last-minute items to the grocery list. Having clean fridge as a to-do list item, scheduled on a fixed reoccurring date just doesn’t work - the fact that I needed to get groceries meant I needed to clean fridge first - not both tasks independently being scheduled by a fixed period passing. Also, it doesn’t make sense to mop the day after we last vacuumed, we only mop immediately after vacuuming, but not every time.
I didn’t necessarily need to rework the priority queue system but simply needed some channel of communication between tasks so one could make an impact on the other. Make a pathway for the information to flow, and it will. And it indeed did, problem solved (are you allowed to start sentences with “And”?). Now the task templates had a few additional parameters to define how they impact other tasks.
Keeping low priority tasks from getting stale (AKA SLAs)
Some tasks will always be important to do very frequently, such as brushing your teeth. These types of tasks start with a very high initial weight. If you miss brushing your teeth, it’s even more important to get it done. These types of tasks also have their weight (importance) increase very rapidly over time.
Some tasks will be important to do every so often, such as changing your bedsheets. These types of tasks start with a low initial weight. It’s not important that you immediately change your bed sheets every week, but by three weeks you must get it done you disgusting slob! These types of tasks will have a gradual increase in their weight over time.
Some tasks will be nice to have done very infrequently, such as washing your windows. These types of tasks start with a low initial weight. It’s not important you immediately wash your windows once 180 days have passed. These types of tasks have their weight increase very slowly over time.
Some tasks, if put off for a while will take longer to complete - for instance, laundry or dishes. These tasks will have their time-cost set at a reasonable number of minutes to clean up dishes for the day and will have increasing time-cost if it’s not completed on time. This means the app will need to look for an ever-increasing free time window to complete the task when it gets rescheduled.
Calendar Sync - via negativa
Finally the calendar sync and a somewhat original approach (I think?) I took was to have the app schedule the tasks on my calendar for me. I whipped up something quick using the Google Calendar API. Here’s the scenario, you have some free time to do some things that need to get done, but your wife wants to go out for lunch.
Instead of scheduling the activities you need to do yourself, you instead schedule the time you DON’T want to be working on activities, and so the tables have turned. This prompts you to define a reason as to why you won’t be working on to-do list toil, which was surprisingly effective to motivate me and just get the things done in my life that need to be done because it’s okay to have excuses to not be working on things at times.
It forces you to make and acknowledge the excuse you have as to why you’re not doing things that need to get done. If you’re okay with the reason, then great! If we just create a normal event on our calendar for the time we’re too busy to be working down the built-up tasklist, then all the tasks get rescheduled.
Your to-do list activities will be rescheduled into a free slot on your calendar. Notice how the order of events changes based on free space availability. If a higher weighted event won’t fit in the free space, the next highest weighted item is considered, optimizing throughput while still honoring the quality of service as much as possible.
What if you don’t have an excuse event to not do tasks?
The important part is that oftentimes, you may not have a reason in which case you’ve acknowledged there is no reason you can think of to not get some to-do list items done. This prompts you to not be a lazy ass and do some of the things that need to be done, but sometimes you just block the whole day off and feel fine about it. You feel fine because the overall throughput is higher with this approach. The WIP has been lowered.
Problems Still - Next up “Sticky Dates”
The most recent problem I’ve hit is that some tasks require a sort of stickyness or preferred date range to be completed in. I only realized that once I was scheduled to wash the windows in the middle of winter. I think I’ve got a good set of foundational parameters to build upon, so it’s not back to the drawing board entirely, but its definitely time to include just a tidbit more complexity into the model.