building slow: great bones, terrible agony.
I’ve been working on the project for years now. It is the most ambitious thing I have ever made. I’m proud of it, but I’m far from done and it has been grueling. Each time I overcome a mountain of difficulty I am rewarded with the sight of the next mountain I must climb. It feels as though I am always on the cusp of “rolling downhill”, if only I complete just another abstraction.
what’s the project?
I’m working on a CRUD app. It’s a budgeting app for people who:
- maintain a forward-looking budget;
- share expenses with other people;
- and/or use multiple currencies1.
That last point is a bit of a non-sequitur, but I think it’s valuable. Budgeting today is made pretty easy with YNAB. However, if you share expenses with a partner or roommate you have to handle that separately. This results in double the work for shared budget categories and a lack of visibility of your shared burden for those categories until you settle any outstanding imbalance.
With my proposed app, transactions are entered into the budget as normal. Transactions added to a shared budget category will be automatically “split” as configured, and the users the budget is shared with will have immediate visibility of shared spending. Reconciling will be a button push, saving everyone from maintaining extra spreadsheets.
My end goal is not actually the project, but its bones. I am building the SASS application framework that I’ll use for the rest of my freelance career. A framework so expensive to develop that I’ll have a lasting competitive advantage. Something that’ll allow me to build essentially any application with minimum long term support costs. This requirement is what makes it so painful to build
doing it wrong on purpose
The sentiment of “move fast and break things” is inseparable from startup culture. Grab whatever, duct-tape it to something else, and get a working prototype out the door as soon as possible. That’s not how want to do things.
High velocity development makes a lot of sense for an industry driven by gambling addicts venture capital. I have no investors to sell infinite growth to, I just want to make robust software that requires as close to zero upkeep as possible. I want to build once and sleep easy.
my muse and critic
I’ve become a Rust evangelist. We are the monsters that Hacker News users are turned off by. It’s the language that feels unproductive after some years. It is a subtle and deep language, and I think it’s worthy of greater faith.
My oldest useful Rust project is about 5 years old. I am very comfortable with making arbitrary changes to any part of it. It compiles fine and guides the user to getting it set up painlessly when run without a config file. I don’t even want to look at my old Python code: I’d rather work on my worst Rust code than pretty much any Python code, any day. Every block is well-behaved, every function has clear inputs and outputs. Every error is anticipated and handled: not always in the best way, but always with some consideration for the user.
The compiler has been the best tutor I could ask for. I still feel like a beginner with Rust, but it’s starting to click. It took me years to become proficient with Perl and Python; Rust will be no different.
what I love about it
I’m using GRPC protocol buffers. My API types are enforced by the compiler. If I change the definition of an API message, the code breaks on the client and server side: just like it should. Data sent over the wire doesn’t need to be transformed to ASCII, it’s tight and binary. I could run the backend on a potato. Everything about the architecture is fast and light.
Client and server are bound together by the same code outlining the rules of communication. There is one Error type to rule them all.
WASM allows me to build applications that anyone can run in their browser without installing anything, safely. This is a huge win. A very small tool I’ve published is 2.8 MB, which is a lot bigger than jQuery; but > 10 MB/s connections are becoming pretty standard today[^1]. It’s worth the third of a second initial load time; everything after that is speedy.
-
no need to maintain multiple budgets for multiple currencies ↩︎