Dash Cycle #01: (re)organising

I'm building DashDot: a privacy-focused interval training app that doesn't suck. The second cycle of development lasted March 15 - April 12. Let's look at where we are.


Here are the things I wanted to achieve in this cycle:

  1. ✅ Finalise the code architecture and restore tests
  2. ✅ Allow someone to complete a (timed) timer
  3. ✅ Focus on the persistence of timers and workouts. Make sure that relationships between these entities are persisted.
  4. ✅ Buy domain names (for app and company)
  5. ✅ Decide on ticketing / management software and method. JIRA vs. Linear
  6. ✍️ Solidify and scale-back the UI design
  7. 🙅 Make the UI nice
  8. 🙅 Continue with TDD and high test coverage

Designing Code Architecture

This cycle I started running into the limitations and assumptions of my previous software architecture. Four weeks ago I did not have any strong opinions or experience on architecture for a SwiftUI app, but now I do. I wrote about my experience with this pretty extensively elsewhere. In summary, I've taken a very Rails-esque approach to the design: splitting my software into models, views, view models, and interfaces. Dividing by function rather than domain model will make some people mad, but it's actually really helped keep everything clear in my head.

I ended up doing a pretty major refactoring of the architecture, which mean that a lot of my previously-written tests were no longer useful, and had to be deleted. I was only attached to them via the sunk-cost fallacy, so away they went.

I also got to draw some pretty gnarly, sprawling UML-style diagrams in this process to help me really flesh out my thinking. That was cool.

I've still not reached the same level of test coverage as I had before, but I do have a much more readable and consistent code architecture so I think the pros outweigh the cons.

Allow someone to complete a timer

Creating a timer and doing a workout are the two core workflows in DashDot. This cycle I focused on that user journey: letting someone select a timer they wanted to complete and then start doing it.

There are a couple of complications here (obviously) but this workflow now functions. In DashDot you can now select a pre-existing timer, and start doing it. The app will persist your progress and process as you go, and progress you through the intervals, etc.

So far you can only complete timed intervals (not distance). That'll be one of two focus points for Cycle#02.

Persistence and relationships

I spent a good few days really getting into CoreData, managed object contexts, and the ORM-like way of managing relationships between entities.

DashDot now persists records of your activities, your workouts, and your timers - all without any fuss. This is an essential feature and I'm glad it's done

I have created an Active Record-like pattern for my business entities, as I didn't like the idea of manually modifying the generated classes from CoreData. This allows me to have some helper methods on my models to access related data, and to treat what's in the persisted CoreData layer as DTOs. This is definitely my web influence coming through: treating the data persistence as dumb and largely stateless objects. I'm not sure if this is the best, or most Swifty, way of doing things - but it's the way that lets me move faster.

Purchase domain names

I needed domain names for both the app and for the company I'd be publishing it under. I've purchased both of those and I'll share when there's actually something on them.

Project management: JIRA & Linear

I had previously been using JIRA to manage my tickets and things to do. I discovered Linear (I think because someone on Under The Radar mentioned it).

I've completely switched to Linear for managing my tasks. I like it because:

  1. It has a native app, even if it's just an Electron wrapper, it feels surprisingly native
  2. It's free (for me a one-person team)
  3. Phenomenal keyboard shortcuts that let you move between tasks and screens, update and create tickets, and do all sorts.
  4. Their idea of "cycles" fits almost perfectly with how I want to think about software development. They're essentially four-week sprint-like phases. You pick a four week period, acknowledge what you can/not get done during that, and make sure things stay in scope.
  5. Nice integration with GitHub - generating branch names for tickets and tracking their progress through PR to merge status. Even working as a one-person team, this helps me focus on "one things at a time".

Using Linear comes with a lot less friction than JIRA.

Scale-back the UI

I had a bloody massive Figma file with a whole bunch of screen prototypes and idea exploration. By the time I had spent four weeks doing more code-heavy tasks I had lost track of what was where, what I liked and didn't like. There was too much in the Figma file and things were too hard to find.

So I copy-pasted everything into an "archive" tab in the file, and largely started from scratch. I used a more simple and iOS-like design. It's a lot more boring, yes - but it's also a lot more achievable.

Every now and then I go back to the archive and look to see if I had any interesting UI ideas, bits of data, or conventions that I'd like. In general however I am trying to stick to a very simple and limited UI. No fiddly bits or tricky bits, I want to get something out there.

I have started this process of redesign, and it'll continue into Cycle#02. The UI I have in the app at the moment is... not good or consistent, but it is functional for testing. So I need to improve it.

I've become a lot more involved and aware of the iOS-specific design scene. Reading a lot of app reviews and listening to podcasts so I can get a better sense of "what makes a well-designed app".

Make the UI Nice

I wanted to have a fully redesigned and implemented UI by the end of this cycle. That did not happen, I had other things to do. I'm working on it though.

Continue TDD

I wanted to continue to develop with tests are the forefront, however the severe refactoring and reorganisation I've done have left a lot of my old tests useless, and I decided to move with greater speed by not having as many tests before I commit code.

This decision will come back to bite me, I'm sure, but I want to focus on producing something usable and interactable. The code is not the message, the code is the vehicle.