Working software runs locally
35 points by nickmonad
35 points by nickmonad
Nice article! And I agree with it 100%.
A slightly out of fashion (but nonetheless still valid) approach that I find very useful to simplify running things locally is programming to interfaces and, crucially, testing to interfaces.
Say I need a database to store todos. I define the TodoRepository interface, I write black-box tests for it, and I then write two implementations: one for the deployed environment (e.g., PgTodoRepository) and one for the local one (e.g., MemoryTodoRepository). Tests run against both implementations, so the local one stays functionally ~identical to the "real" one. But it's much easier (and faster) to run, so I use that while developing.
This is nothing innovative, of course, and the example I gave is rather trivial to explain the point. But when I force myself to use this approach for all external dependencies (dbs, queues, 3rd party services, etc), then spinning up the local environment stays hassle-free even when the whole stack around it becomes complex.
Lately I've been pushing this even further, for an all-js app I'm working on, where I made it possible to run everything (frontend+backend+services) in the browser, which I found incredibly powerful, because then everything is in one place, and it's very easily debuggable and modifiable. (This could probably be done even for non-all-js apps via wasm, but I haven't yet had the chance to experiment with that.)
Thanks for reading!
That's totally still a valid approach! An idea I wanted to explore more in the post, but didn't in the interest of keeping it relatively short, is that a ton of systems we use can actually be modeled very simply at a high level, using common data structures. Need a fake Redis? Any standard library hash map will do the trick. (For the most part... yes Redis has a ton of data structures beyond string key to string value, but if you need those, it just makes the fake marginally more difficult.)
Of course, the production-ready systems we rely on have real implementations that introduce some complexity, because they have to be performant, reliable, persistent, etc. But, the fundamental conceptual model can usually be mocked/faked pretty easily.