Famous Braun designer Dieter Rams writes about simplicity in his 10 Principles of Good Design. At AnsibleWorks, we try to extend that quest for simplicity all the way down to our engineering process. I thought it might be interesting to take Rams's principles and show a bit how they apply to software engineering in general, because, as an industry, I think often we're often playing catchup and don't have time to think about these kinds of things enough. This isn't really specific to IT automation software, it applies generally to all types of software.
So, simplicity... How to apply it to software?
Dieter Rams says Good design:
- Is innovative - When designing a solution, step back and decide what you would build if nothing had come before. If a solution seems obvious, what choices are in fact your own? Are their preconceived ideas that should be revisited?
- Makes a product useful - When choosing what to develop, prioritize things your users need most, not a feature that's designed to be shiny on the blogosphere. A good wrench is usable a lot more times than a plasma cutter, so don't build the plasma cutter until you have the wrench. I know everyone thinks they want a sports car, but have you seen the trunk size on a Lotus?
- Is aesthetic - It's easy to let the underlying technology in a system bubble up into a user interface, leading to something that wasn't made for humans. Keep the amount of cruft and needless steps out of the system as much as possible. Reduce jargon, even when the underpinnings may be complex.
- Makes a product understandable - Find ways to build a technical solution so a question that is asked today doesn't have to be asked tomorrow. Make the product straightforward enough to use that the documentation can be printed without cutting down a forest. As features get added, make sure the basics can still be learned in minutes or hours.
- Is unobtrusive - If you don't use a product today, and pick it up three months from now, it should still be working and you shouldn't have to relearn how to use it again. Seek obviousness and intuition in all things.
- Is honest - Realize when someone else has built a software component already that is better than one you could design. This applies to job queues, message buses, cryptography systems, web servers, and more. Of course, don't be afraid to reinvent square wheels -- that's never a bad thing! I worked at a startup in the past that somehow invented and shipped three separate job queues, at the same time, in the same product. It was as awesome as you might expect.
- Is long-lasting - Optimize for stability in each release. If running an open source project on GitHub, take time to review each pull request, decide if it should fit, and don't just hit the green button immediately to make a ticket go away, thinking you'll fix any lurking problems later.
- Is thorough down to the last detail - A hard to explain (or fiddly) technical feature that confuses people is often worse than not having the feature, in the end, for the trouble it causes users. No matter what your product is, think about error cases and how you will detect them, and how the software might evolve or work with a future component that might come along tomorrow. Does doing a feature one way today make it harder to do it the way you really wanted to do it later? It doesn't mean you should say no to the feature, but it might mean you need to take some time to think about it and incorporate it later.
- Is environmentally friendly - Build applications efficiently to conserve CPU resources, disk, and more. It's not uncommon that I see similar web application stacks (in the same industry) and workloads where one can run on 10 servers, and another runs on 500. I read recently the average VM utilization in the world might be 7%. If that's true, I believe the polar bear situation might be on us, not the coal plants. This is one of the reasons Ansible uses an agent-less architecture -- if you aren't managing your systems, nothing extra is running. We didn't do it for the polar bears though (sorry, polar bears), we did it so to maximize compute workloads and free RAM.
- Is as little design as possible - Software is more reliable when it has less moving parts. Products are better when they are easy to explain, and should have a soul and purpose, rather than being a collection of features. As Spock said, the needs of the many outweighs the needs of the needs of the few, or the one. Identify your core user personas and use cases and concentrate on them.
Because the underlying parts move so fast, software is still one of the hardest things anyone can build reliably. The engineering and scientific processes that have evolved around architecture, fluid dynamics, and medicine have yet to really solidify around software engineering. Further, the technology of today is vastly different than it was 5 years ago, and will be vastly different 5 years from now. As software developers, we have to be cognizant of that every day, how to balance the expectation of blindingly fast innovation with the need for engineering rigor. We must move quickly, but also always thinking about whether we are creating the ideal interfaces.
Robots were originally conceived of (as an idea) to make life easier -- to be servants. I believe Technology should be servants also, but often we serve technology, instead of it serving us.
By always striving for simplicity -- and some of those 10 Principles -- we can have a chance for taking technology back into our own hands, once again.