This is a three-part post that I’ve been thinking about for awhile. It ties together all the strategies for building high quality .NET cloud apps that I’ve written about on this blog over the past year and a half, and in that sense could be considered my manifesto on the topic.
Every highly complex system needs to be built from the ground up with a minimum level of quality in mind so that any requirement change can be easily designed, developed, tested, and deployed. To that end, I’ve withled it down to nine key principles that make building high-quality products possible, grouped into three separate categories:
- Planning Principles
- Product Vision
- Technology Vision
- Developers and Processes
- Development Principles
- Patterns and Practices
- Effective Use of Data Storage
- Testing Strategies
- Operational Principles
- Early and frequent delivery
- Monitoring and logging
- Cost Efficiency
Each of these principles feed into each other to create an ecosystem that makes the code-base as robust as possible. There isn’t a sequence to accomplishing these principles either. Most of them are accomplished in parallel as the product evolves.
The scope of each of the principles is greater than can be addressed in a single post. This post and its two follow-ups provide an overview of each principle and link to more in-depth articles on those topics.
It’s near impossible to know precisely how a product will evolve. Requirements change frequently, which has led a large portion of the development community to move towards more agile software development methodologies.
Regardless of the methodology of choice, software developers needs to get involved in product planning from the outset of a project. The better the team understands why they are building something, the easier it is to invest themselves in the project. There’s nothing worse than not knowing why you’re doing something, and it can often spell doom for a project. Ideally, one to two interested developers work closely with product management to get a clear understanding of the problems that need to be solved and work together to find the solutions to be implemented.
Even though we’re developing in short iterations, the product vision needs to be a bit more forward looking in its outlook. A development team benefits from having the high-level objectives for the current release, the next release, and the one after that. Armed with this information, the team knows where the focus will be for the next while, positively affecting morale and guiding technical decisions.
The platforms and potential restrictions on which end-users will use the cloud app should be well documented. Certain restrictions, such as low Internet bandwidth or connectivity, can have a significant impact on technical decisions taken when designing and developing the application. Making these restrictions clear at the outset will ensure the development team goes down the right path from the start.
The technology vision provides direction for software architecture and design decisions. Its concerns should be higher than the programming level; it should instead answer questions like “what technology do we favor to solve this programming problem”.
The technology vision don’t need to be set in stone. It should be used as a guideline to solve 80% of problems, but there will always be a last 20% that doesn’t fit the mold. Here are some of the vision-type questions that should be answered up front for a large cloud application:
- Are the cloud apps service-oriented, microservices or monolith-oriented?
- How will communication between the cloud applications be done? Will HTTP, queues, topics or something else be used?
- What will the authentication scheme look like? Is there a need for OAuth, or is Basic authentication sufficient?
- What is the prefered way to host and run cloud apps and background workers? Containers, serverless, virtual machines, and Platform-as-a-Service can all be used to run .NET applications. These aren’t mutually exclusive, and should be used in conjunction as the needs fit.
- Are there any scalability needs for certain components of the system?
- How much redudancy is needed in case of failures in a cloud region?
- Which data storage technologies will be used? Hosted and self-hosted RDBMs, NoSQL, and Graph databases all have specific uses that make them shine.
- How is the buy vs build decision taken? What are the criteria that should be used to make the decision?
For an existing system, look at where the application is today and what needs to be happen in the next year so that it stays current and easy to work on. Lots of what you’ll find here could be considered technical debt. I prefer to see it as “planned non-obsolescence”.
- Are there any new technologies that have recently become available that could help make the system easier to use or more maintainable?
- Build prototypes of existing components with new technologies to see if they can help improve the system, be it from a business or technical perspective.
- What are the end-of-life dates for SaaS products being used? What’s the plan for upgrading or replacing them?
- Try to keep the number of technologies used to the strict minimum. It reduces the number of moving parts, as well as lower the learning curve for developers to get up to speed on the different components of the system.
Not all the items in the technology vision can be addressed immediately, but having them written down somewhere helps bring visibility to tough decisions that have been made in the interest of building the highest quality application possible with the time and resources available.
Most of the questions raised in the technology vision are the basis for the other principles I’ll discuss. The answers to these questions are a guideline, whilst the development and operational principles go about implementing that vision.
Developers and Processes
It almost goes without saying that without developers with specific skillsets that it’s near impossible to build a high-quality cloud application.
The rise of the full-stack developer over the past 10 years has skewed the process of finding people with a specific skillset. The reality of full-stack developers (of which I consider myself one) is that although they can work on the front-end or back-end, they are more proficient at one side or the other of the stack.
Specialists brings more value to the table since they can put their extensive experience at a particular skill to work for the project. Each specialist profile brings something different to the table and helps evolve a system throughout its lifespan.
- Developers who know all the nooks and crannies of C# and .NET development.
- Developers that have extensive knowledge of data storage and can lead the conversation when it comes to deciding how to store and retrieve a piece of data.
- Cloud engineers that can put in place a robust CI/CD Pipeline and automate the creation of cloud resources.
- Test Engineers that can write automated, repeatable and stable tests.
- Developers that have an interest in product development to bridge the gap with product management.
There are a ton more specialities out there, these are just a few to give you an idea of what might be needed.
I’m an advocate for letting a team decide how they want to work. There is a bit of a craze forcing everyone into Agile techniques at the moment. And while those environments do work well, they aren’t for every team. Some teams will prefer Scrum, others will prefer Kanban, or something else entirely. Letting a team choose their work methodology empowers them to do what’s right for the work they must accomplish.
Although each team can choose a different work methodology, the process of developing a new feature, improvement or bug should be the same across all teams. The design process, coding standards, branching process, testing process and deployment process should be as close to identical as possible to standardize the development cycle. This makes it a lot easier to move people around or to speed up the onboarding process for new developers.
One of the most important processes to put in place is a thorough, peer-based code review. Code review finds bugs, improves skills, and shares knowledge amongst colleagues. But most importantly, it might be the single best way to improve the quality of any application that is built.
Looking To The Next Principles
These first three principles, while not purely technical, enable the more concrete principles of delivering a high-quality cloud application and could be applied to almost any technology stack. The next two sets of principles will be more detail-oriented, and therefore more heavily focused on .NET and its related technologies.