Today’s world is in overdrive. Ideas are shared with thousands on Twitter, turned into proposals, and at a moment’s notice, you start assembling a team to build a product. You chose Agile as your delivery methodology because you need to iterate and react to changes fast. The last question before kicking things off is how much planning should you do upfront?
A few years back my laptop’s battery stopped working. I rushed to the closest repair shop to get a replacement. The price and speed pleasantly surprised me. Unfortunately, two days later the new battery stopped working and I had to go back asking for a warranty. Long story short, after one more iteration I went to a licensed shop and got a proper battery which I had to wait for a week and pay twice as much.
I was enticed by the speed and price and opted for a “cheap now, expensive later” option. Unfortunately, the same situation is present in software development. Teams would argue that “cheap now” is what Agile is about, quick iterations, “move fast and break things”. It is true if what you’re building is a proof of concept, a throw-away prototype. In most cases what business needs is a fine balance between features and time-to-market. Most importantly, everyone implicitly assumes that further iterations will be just that, iterations, not complete re-writes.
Let’s look at the “expensive now, cheap later” idea applied in the context of Agile software development. How much planning should you do on a technical part and what processes are essential to establish early on?
Engineers have countless ways of building software these days. Even for a company’s website, you have to decide if it will be SPA, SSR, SSG, or some combination of that. It’s not uncommon to get lost here even if you’re building a brown-field project under constraints of previous technical decisions.
Some technical decisions, especially around architecture and data, are hard to “reverse” and will require the team to put some time upfront.
Here’s a list of things you should consider:
- Your domain model. It will act as a bridge between engineering, product, and business teams.
- Your data model. Data outlives any implementation. You will have a chance to rewrite your abstractions, migrate from the monolith and pull everything back in, but your data will always stay with you.
- Key components of the solution. No need to go too deep into outlining every abstraction and drawing UML diagrams. Focus on what will make or break your application. Consider what can be a 3rd party solution, a SaaS integration, and what needs to be in-house.
- Interfaces and boundaries. Conway’s law says that software architecture will follow the organization’s structure so making boundaries between components explicit and interfaces defined will ensure that long-term communication overhead is minimized. For those following a “Domain Driven Design” approach, this can be included as part of defining Bounded Contexts.
- Documenting your design and critical decisions. Teams frequently mention that they would like to have better documentation. As time goes you start to forget why you chose X over Y. New team members rush into “making things better” not fully understanding the history and context. Spend some time deciding how much documentation is right for you and how you will organize it. Some helpful classifications can be found here.
- Bonus: if you’re building a mobile app in a cross-platform framework, such as React Native, consider if you want to launch both iOS and Android simultaneously or just one. It’s not uncommon to focus on one platform. It might improve your focus, however, beware of completely ignoring the other side. You still want to regularly check on Android if you’re building iOS and make sure your key libraries are compatible with both. This way you can avoid having to explain at the end “why would building an Android take just as much as we took for iOS, aren’t we using a cross-platform technology just for that?”.
Taking care of the above is not a trivial task and might take a couple of weeks to figure out based on where other things are, such as your overall functional requirements and user stories. At the same time, be careful to not waste your time deciding on the following:
- Following a monolith or microservices architecture. It depends on many factors but if you’re just starting out choosing a monolith is a safe bet.
- Choosing k8s because you want to be resilient and multi-cloud. Consider running it on Heroku and make sure your app is properly dockerized.
- Don’t be afraid to choose “boring technology”. For example, a framework like Rails might not be trending anymore, but it survived for almost two decades which means it can predictably get the job done and has earned the trust of many. Another example is Postgres. In most cases you should go with a relational database and choose Postgres.
While dealing with Technology comes naturally to engineers, thinking about processes does not. Often engineering teams view processes as constraints that limit and reduce agility. In reality, a well-thought-out process acts as an enabling constraint that reduces anxiety and allows everyone to go faster. Here’s what you should consider:
- Code review. Often, we see teams “do” code reviews but without making any agreements about what a code review is. This leads to misunderstandings, frustration and, worst of all, “just doing it”. A good thorough code review is vital to software’s success.
- Team working agreements. A team agreement is a shared document that contains written agreements the team has on various topics. For example, how many approvals on PR are needed before merging, what level of decomposition we thrive for, will we write unit tests, and how much. Of course, the document should include non-technical topics, such as communication.
- Establishing a proper technical debt management process. In many cases technical debt is not a bad thing and having no technical debt is impossible. However, it’s important to have the right process in place to keep the amount of technical debt in check and agreements to regularly eliminate it.
- Understanding DevOps practices. DevOps is not only a kind of engineering specialisation, DevOps teaches us how to deliver software faster by improving the development process. One example of what DevOps talks about is ownership. The team needs to be responsible for writing code, QAing and deploying it. Another example is deployment frequency. Your environment should enable you to deploy at least once a day and more.
- Documentation. It’s important to agree on what kind of documentation you want to keep. The bare minimum is having a README that can answer questions, such as where a development app is located, how to set up a development environment, how to make a release and link to team agreements. Good documentation focuses more on the “why” things are done the way they are vs “how”. Most of the "how" should be taken from the source of truth: code and infrastructure.
I failed to remember that cheap things can become expensive when replacing my battery. When people talk about Agile they use it as an excuse to not make plans, invest enough in architecture and development processes. Our experience shows that good planning, well designed and mutually agreed upon processes will make your company truly capable of following Agile.
Have a question or a software project to build? SVI is here to help, email us at firstname.lastname@example.org.