Values are statements of belief — that if these attributes are present, we’ll be able to build software that will not only delight users and customers, but will also allow for rapid change with confidence, both in the short and long term.
I’ve chosen four core values to present here. These are the values we apply whether we’re building a scripted deployment to cut days of manual effort and risk, or creating a new mobile application for retail fun, or building a data pipeline to process terabytes of data.
Figure 1: Core values and practicesThen there are eight core practices, each of which supports one or more of those core values. Practices are the actions we actually perform, the methods or approaches that we apply.
None of these values and practices are new, in fact, some I’ve lifted directly from the XP values and practices. I’m trying to focus in on a small set of core values and practices that I prioritize regardless of context.
Core valuesAt the core of the illustration above are the four core engineering values.
Fast feedback: We value being able to find out whether a change has been successful in moments not days. It might be that unit tests have passed, or that we haven’t broken production, or that a customer is happy with what we’ve built.
Repeatability: We value the confidence and predictability that comes from removing manual tasks that introduce weird inconsistencies. We also want to spend time on activities that are more important than troubleshooting something that should have just worked.
Simplicity: We value software that contains no more complexity than it needs to do a good job. We build for what we need now, not what we think might be coming*. But we make choices that allow our software to rapidly change to meet the requirements that are coming.
Clean Code. We value software that’s easy to understand and maintain and is intention-revealing, as we know that this allows us to continue making changes with confidence, as we learn more about the problem.
Core practicesThe next ring outwards on the illustration contains eight core engineering practices — methods and approaches that support the core values. I won’t go into detail about each of the core practices in this article, as there are many wonderful references for each of them.
I’m a ‘DevOp’: does this apply to me?Some of us identify as being on the path to mastery in a particular technical domain. Examples of domains where people may have particular depth include mobile development, data engineering, cloud infrastructure and DevOps. A few years ago, I deliberately invested in learning cloud infrastructure and automation and worked almost entirely in that area for a while.
I believe that even when I was building infrastructure and automation tooling, I applied the same core set of values and practices that I applied when I was building application software. Those values and practices helped make sure that the work I did was always delivering valuable outcomes with short feedback cycles and that we could continue to maintain that pace of change.
So, I believe that specialized technical domains are built on top of the same core of values and practices. Like this:
Figure 2: We take the same common set of core values and core practices into our work in data, or cloud, or mobile, or machine learning, or robotics.
But I’m working on an MVP!Of course, there are trade-offs that can be made when a piece of software is genuinely throw-away. However, these are core values and practices that always apply — even for a short-term delivery, with an uncertain ongoing viability. Dropping these practices will make you slower, even in the short term.
Everything in the core practices applies to prototype development, MVP, test and learn, any other explanation you might use to cut corners. There are tweaks we can make. For example, we might turn down the level of investment in supporting infrastructure in the very short term. If you have a team of three developers building a two-week prototype, they might choose not to spend a day configuring and troubleshooting a Continuous Integration server. The team should still practice Continuous Integration — committing to a single code branch and validating many times a day that the software still works. If they don’t do this, the slower feedback cycles are very likely to cause rework and delays that will cost them precious time when they can least afford it.
Should you use test-driven design (TDD) on a two-day piece of coding to prove a hypothesis? You might tweak your focus in TDD, using tests to drive your design but reducing the emphasis on comprehensive coverage. But if you drop TDD altogether, you will almost certainly build more than you need — and what you’ve built will suffer in terms of good modular design and be harder to complete, even in the short term, and to comprehend.
So what?These are the core practices empowered developers apply by default. If we compromise too far on these core practices then this is a big deal. We’re being untrue to our own values and we’re being negligent.
So what if you don’t use TDD? Then, I’d be asking what you have in place to ensure your design is simple and you have good, fast feedback. If you can convince me that the thing you’ve replaced TDD with is working (or that you’ll know when it’s not), then I’ll be happy. Same with pair programming, or any others of those core practices. If you don’t have an effective alternative in place, or you’ve swapped out more than one or two of those core practices, then I’ll be very worried indeed.
Finally, if you’re an enlightened software engineer who recognizes these core values but the organization you work in prevents you from applying these core practices: don’t give up! Educate, evangelize, form a cohort, build a case. There’s no joy in working in a way that’s not consistent with your values.
Maybe you should join me and help with our mission to put a dent in the software industry?
*YAGNI is a very nuanced concept, and I don't trust most of us to get it right including me. But try we must! Do not fall into the dark side of speculative engineering. Remember: there’s a subtle distinction between building a really great implementation of only what we need now; and building the dumbest thing that could possibly work.