I end up talking about “Modern Development Methods” a lot when talking about how t deliver software reasonably efficiently. “Modern” is a problematic term, so I want to say what I really mean by that “Modern”. It comes down to a few big things that we need to achieve. These aren’t exclusively what we need to do but give us most of what’s needed to deliver software effectively as a team whilst staying sustainable with it.
Let’s climb in:
How do we know how are are doing? By measuring it. In the OKRs world for example, we’d set an objective and then come up with key measurements for that. Here we’re building software and making sure we can measure how it is doing, how well we’ve solved the problem that we set out to. We need to build to be measurable from the beginning. As an afterthought, measurement is hard and it sucks.
How do we know what to make for our users? By researching their needs, understanding their pain points, testing prototypes with then, survey them on usage. We need to be user-centered if we are going to have any hope of delivery something useful. With a developers ego, one might be inclined to believe that one knows best how it should be. Prepare to learn. Be humble. This software is not for you.
From the beginning, we need to know that we aren’t making something vulnerable to attack. We’ll end up handling sensitive data of some form, and having that easily stolen is plan bad craft. So we make sure we know that we’re not exposing known vulnerabilities by choosing the wrong module, or the wrong version of the wrong module. Vulnerability scanners and data exists. We need to use if from the beginning to know we aren’t creating a problem for later.
One personal note here that has bitten me before: Be a little careful with very flexible ‘magic’ tools that do things like marshall parameters between types inside API JSON. That magic flexibility is fertile ground for bugs and vulnerabilities. Sometimes more boilerplate and more conservative coding can make like a lot easier later.
Continuous (in delivery, deployment)
It is all too easy to make a thing and ship it once. It is much harder to deliver code that can be changed, that we can trust once modified, that we can scale, deliver multiple places, test and assure.
The remedy is to adopt ways of working that make it easy to deploy changes, to trust changes will work, to know what has been deployed. While are at it, let’s get efficient as well. Let’s test things early in the process. Let’s build something and test it before deploying it. Let’s document when and how that happened. Let’s make deployments so easy and low risk that we can do them all the time. That means the size of changes can come down so releases to production are now a much lower-risk proposition.
All of that is what we call Continuous Delivery and Continuous Deployment. Basically, in an assured way, we make the code delta of releases as small as possible by using automation and sensible controls. In practice this looks like:
- A story/bug tracking system that can be trusted, is always used and is the source of truth of what a code change does. We do not want this in some developer or release managers heads. Get it in the tracking system.
- Up-to-date documentation, in the form of a Runbook how to deploy, test, maintain, diagnose, scale, and operate this service.
- A high quality, reliable, source control system with merge request support used in a consistent way. This is almost always git, in the form of GitHub, GitLab, Bitbucket or others, whether cloud or self-hosted.
- Processes to review code changes to keep quality
consistentand spread understanding of changes across the team
- Use automation pipelines (Jenkins/drone/circleCI/Travis/…) to test, build code, build images, scan images and deploy images automatically when things happen. If a human has to press a button they’ll
forget / beon holiday / be in a meeting.
- Engineer services to allow small automated releases to work well – you’ll need ways of doing automatic database migrations as a part of a release
- Build services to replicate and scale as needed.
Agile is a bit of a catch-all for all new development practices. What I mean here is that as designers and developers, we stay flexible, resilient and listening as we go on in our development. Agile practices, applied with care and holding, help humans and teams deliver well and with quality, and critically, help us deliver what is actually needed when we set it live. The agile mindset is important here. We’re experimenting, exploring, listening, testing, measuring as we go. We’re servants to needs of
I have personal favourite agile practices. However, this really depends on the team and situation. We need to pick processes that make us resilient and reliable creators of what is needed.
How do I know it works before release? How do I know this code I’ve written makes sense. How do I know that this bugfix doesn’t break something else? How do I know this release to production is going to work ok? How do I avoid debugging in production or on live hardware? How do I avoid ending up scratching around for information when a production problem occurs and nobody knows why it is happening? How do I know what we’ve made is secure?
All the above is so much hassle and so costly. To make it easier, we need to expend effort in building testing into our codebases –
A recipe — adapt as needed
So that is what I call MUSCAT, and I think it gives a good roadmap to what to establish to get development running efficiently and sustainably. There’s more to add on the details, but I’ll leave that to a later series of posts.
The most important thing: inspect, reflect and adapt as needed. There is no one answer. I like to look for the difficult edges and work them smooth – by experimenting, and seeing what happens.