Dunelm Engineering Principles
At Dunelm we have refreshed our Engineering principles to drive where we want to go technically and reflect on the journey we’ve been on over the past few years.
As explained here principals trump processes and determine whether you thrive or fade away.
Here are our new Engineering Principles to help guide our Engineers when designing and implementing our systems. Some of these principles we have been doing for years in most areas, others will push us to make different or harder decisions about our technology.
We’ve broken our principles down into 2 groups. The first is Technical Excellence. The principals in this section focus on the fundamental beliefs of our technology.
Everything as code
Enable automation, consistency, and traceability throughout our development
This principle emphasises the use of code to automate, manage, and deploy all aspects of our development process. By treating infrastructure, configuration, and processes as code, we can achieve greater automation, consistency, and traceability, which helps us to deliver high-quality software more efficiently.
Here are some examples;
- No use the AWS console for resource changes — this has to go via our Infrastructure and code and our pipelines
- Constantly challenge 3rd parties to provide IaC capabilities.
Think asynchronously
Enable non-blocking, concurrent processing and improve scalability, responsiveness, and fault-tolerance.
Always look to utilise asynchronously technologies as a first point of call for solving problems. So problems will naturally fit into asynchronously techniques much easier than others. But always be thinking about if the advantages of asynchronously code/architecture/systems can help.
Make sure you assess the value — including the added complexity of asynchronously systems — to any decision you make.
Performant, Secure, and Testable
Fast, protected against threats and good quality — basic expectations from our customers.
Ok, so this is kind of 3 principles in one — but we think these are the base level requirements that our customer expect from us.
By being performant we make sure that our systems do not frustrate our customers. We make sure we’re constantly thinking about systems which perform at scale.
Secure is just mandatory — our customers trust us with there data, we need to make sure that trust is respected. That means building systems that do not leave themselves open for attack, it means protecting and securing our customer data and it means making sure we are always aware of the OWASP threats.
And final, but certainly not least — the code we write and the systems we create should be tested using automation.
Build for people, not compilers
You read code 10 times for every change. We value readability of our code over complexity.
When you write code, think about the person who will read it next. Write code that is easy to understand, with clear naming conventions and logical organisation. Avoid overly complex solutions that may be difficult for others to understand. So think twice about the 3 times nested reduce function.
Simplify complex systems
Look to abstract or hide complexity behind APIs or libraries.
By breaking down complex systems into smaller, more manageable parts, developers can make the overall system easier to understand and work with.
Keep it Simple Stupid.
Architecture Principles
Here at Dunelm our Engineering teams own our physical architecture and make vital decisions on how our systems work. Our Engineering Architecture principles act as a guild when we are designing and building our systems.
Design for extensibility
We work in a changing industry — our architecture should be able to evolve with business requirements.
Naturally things change over time. It would be boring things didn’t. How your architecture can adapt to changes over time is vital to provide flexibility we change and the problem domain evolves.
Does your architecture have natural extension points?
Pro Tip: When designing an architecture throw some “What if” scenerios to stress test your extensibility.
Create Loosely Coupled Systems
Hide implementation details, take time and effort to defined APIs and contracts to be used as integration mechanisms.
There are some problem domains that are solved when systems are tightly coupled — for example performance or other non-functional reasons.
But at Dunelm we believe that we should start with a loosely coupled system and then understand if we need more cohesion depending on the problem. This ties into our want and need to have an extensible architecture — loosely coupled systems are naturally more extensible.
Services for breath, Libraries for Depth
Promote modularity, reuse and maintainability. Smaller specialised libraries. Larger distributed services.
Services for breadth, Libraries for depth” is a fancy way of saying we should build things in small pieces that can be used in many different places (services) and create specialised building blocks for use within those pieces (libraries).
We want our code to be modular, easy to understand, and easy to reuse. This approach can help us build software that’s more maintainable and scalable, and can save us time and effort in the long run. But it’s not a magic bullet — it requires thoughtful design and can be more complex to implement than just writing a monolithic application.
Serverless By Default
Look to leverage the powerful and flexibility of serverless technology.
Dunelm has had a huge amount of success with Serverless technologies. they have allowed us to implement at large amount of the principles outlined here.
We believe we should continue on our serverless journey and make sure we’re utilising all the different technologies and products that move us to meet our goals.
This doesn’t not mean EVERYTHING should be serverless. But if its not — lets talk about that different problem that is being solved that does not fit into some of our currently used technologies.
Design for failure
Design systems with minimal blast radius and self-healing capabilities.
Making SREs and 3rd line support weekend as quiet as possible!
If there are failures, we make sure you use architectural bulk heads to limit the blast radius.
We should make sure that in event driven systems we implement guaranteed message deliver patterns so we never lose customer data.
If something does go wrong — we should be already investigating and fixing before our customers have noticed — or reported it. We do this by making our systems observable and alerting on observed events.
Conclusion
We hope that you have enjoyed reading our Engineering Principles.
They engineering principles serve as guiding lights in the complex world of software development. By embracing these principles, teams can foster collaboration, encourage innovation, and ultimately deliver software that meets the needs of users while adapting to changing business requirements. It’s important to remember that these principles are not rigid rules, but rather flexible guidelines that can be tailored to the unique context of each project.
What would your Engineering principles be? Which do you like and what have we missed?