The idea of a force multiplier comes from the military, but it can broadly apply to any arena in which any attribute, behavior, or advantage increases the effectiveness of a group or individual.
In the realm of programming and programming languages, increased capacities for abstraction are obvious force multipliers. It's easy to list several such leaps in the history of computing: the Von Neumann architecture, symbolic computing, compilers, structured programming, interpreters, libraries, portable programming languages, higher-order programming, and garbage collection for example.
Tools are also a component of this evolution. I don't know where I'd be without GDB, Valgrind, and Kcachegrind, and I can't imagine giving up several GCC flags and attributes. I'm happy to mention Vim, ctags, ack, and grep, but other people consider all-in-one IDEs to make them more productive.
All of those debates are old and well-established. It's more interesting to discuss development practices which increase productivity and make individuals and groups more effective. My non-exhaustive list includes:
- Comprehensive testing. By developing the habit of writing a test, watching it fail, writing code, and watching the test pass, I have confidence that my code is testable, and that my test coverage is sufficiently high to identify further mistakes and regressions. This doesn't guarantee that my software is bug-free, but it establishes a known-good baseline of behavior.
- Diffs. I can't imagine a world without
patch. On the occasion when I need to massage a patch by hand, I recognize how fortunate we are to be able to identify only the differences between systems.
- Reviewing diffs. Similarly, having a commit list where any interested party can read every change made to a system helps spread knowledge of the whole system and identify potential problems and opportunities for improvement.
- SCM/request tracker integration. Pervasive and promiscuous links between a source code repository and open bugs, comments, and feature requests mean that I don't have to keep the state of the system in my head. Just as the repository stores the code and its history, the request tracker stores the vision and future of the project.
- Pair programming. The most satisfying moments of programming, whether fixing bugs or adding features, I've spent working closely with other people. The stuffed Pikachu on my desk or either of my cats is a poor substitute for having a conversation with another person who's just as intent on the problem as I am.
- Roll-your-own tools. Rakudo's velocity increased substantially with improvements to the Parrot Compiler Toolkit. My productivity increases sharply whenever I notice a pattern of working and automate it. I could never remember the exact order and combination of Valgrind arguments to report specific memory leaks in a precise way, so I captured the most recent successful invocation into a shell alias and promptly forgot everything other than
vgp. Perhaps I should label this item "the ability to create your own abstractions".
- Distributed version control. The ability to fork a project locally, using version control habits I've already developed, and then coalesce all of that work into a patch or series of patches makes contributing to upstream projects feasable and much more pleasant than working through a maze of hardlinks and recursive diffs.
I'm sure there are many more force multipliers I've forgotten to mention. On their own, perhaps none of these represent Brooks's "single silver bullet" -- but together, they may produce multiple orders of magnitude improvement in productivity.
What's your force multiplier?