Technologists love to disrupt other industries. We’ve got app-first banking, self-driving trains, one-click vacuum cleaners, and Blockchain-powered cats, all because a technologist wasn’t satisfied with the status quo.
The only industry we’re scared of disrupting is our own.
There’s something about programmers that makes us incredibly conservative when it comes to programming. My text editor of choice, Spacemacs, is a nice skin on top of a 40-year-old one, I can’t live without my repository of shell scripts, and if it weren’t for GIFs of Izzy 🐶, I’d abandon Slack in a heartbeat.
Clinging to the past definitely has some downsides, but I can’t think of a single place where it’s worse for our productivity than the humble file system.
The tree structure to my left is a common one — in fact, it’s part of the file tree for prodo.dev, our new product. Some files we wrote, some were generated or downloaded. There’s React components, application functionality, stylesheets, little helper widgets… you name it. But mostly, what I see is a mess.
The file system is a limiter, getting in my way. It’s an ancient piece of infrastructure designed for a hundred different reasons that I have to navigate and understand every time I do anything. And the promised benefit— that any tool can work with files — doesn’t hold water when we now work at the level of repositories, projects, components and functions.
Here’s just a few ways that the file system is letting me down.
- Saving a file is somewhat atomic. Working with multiple files isn’t. If I rename a component across several files, anything watching those files — the hot reloader for my website, my test runner, whatever — is going to trigger multiple times. Jest, especially, is a real pain, running my tests several times whenever temporary files are created by my editor.
- There’s very little difference between files I care about and files I don’t. The former, I want managed in version control, backed up, and shared with my colleagues. My node_modules, not so much. Having them in the same directory as everything else does a lot more harm than good.
- The files are in a tree, but my code is a graph. The files above were separated so that all the UI components live together, which is somewhat helpful if I’m working with components and not useful at all if I’m working with one component and its state. If that’s the case, I want to see the component code, its test code (which is far, far away), and the stuff in the redux directory. Jumping around between files across the repository is a level of cognitive overhead I don’t need.
- Files can be sorted by path. Marginally useful when I’m grepping for something, but this has become a crutch. In a pull request, GitHub sorts by file path, even when it’s nonsensical. Why on earth aren’t my unit tests next to the implementation code? Because I put them under a test directory, because my test runner demands it.
- My source files contain text. Text is great because it’s universal, but otherwise it’s a horrible way to represent code. It can be completely invalid or ill-formed (for example, you could reference a function that doesn’t exist), and it needs to be parsed before you can do anything useful with it. My code is an interconnected graph of modules, functions, classes, variables and other concepts, and representing them as text means all my tools — my test framework, bundler, linter, etc. — are 10 times slower than they should be.
- It’s assumed that code that’s closer together is more coupled and cohesive, and code that’s further away is disconnected. This couldn’t be further from the truth. It appears that way because we visualise it that way, but typically, our applications are a mishmash of cyclic dependencies that work mostly by accident. Our file system is lying to us.
I could go on, but I think you get the idea.
As programmers, we work with thoughts, shaping them into something concrete and well-defined, and encoding them in such a way that a computer can enact our desires. We use concepts such as functions, modules and repositories to represent these thoughts, name them so we can find them and reuse them, and author test cases so that we can make sure they work.
Where do files play into this?
At Prodo, we’re working on something a little different. When you use our new product, prodo.dev, to author a React component, you author a component. You write JSX, not a .jsx file; the plumbing is irrelevant.
Stop thinking about the means by which the computer serialises your code to disk, and start thinking about the code itself.
Try out prodo.dev.