Sufficient Architecture


“Sufficient Architecture? What does that mean?!”, I hear you say!! Bear with me.


Over a beer this week I had a good conversation with a colleague about the principles of architecture and design, and as a result I feel compelled to recount something that I have tried to adhere to for a long time. I know some people will disagree with what I’m saying, so if that’s you, shout up and let me know your thoughts.


When designing a new system I always have two principles in mind (and I’ll probably use the term “design” to refer to both Architecture and Design throughout this post, as it applies to both);


1.       Design and Build only what you need today.


2.       Design knowing that you’ll need something else tomorrow.


Let me elaborate a little.


Design and Build only what you need today


What I mean by this is that you should not try and anticipate the future. You shouldn’t add methods to classes “because in the future I might need to X”, and you shouldn’t complicate your architecture if there’s no need.


A good example that I discussed with a colleague is adding a Service Layer to an application; perhaps putting all business logic behind web services, and calling those from ASP.NET. I firmly believe you should add a Service Layer if you have good reasons for having one. If you need to scale out components separately, or perform asynchronous processing, or there are hosting prerequisites, or you have other applications that need to communicate with your application, etc – go ahead and add one.


However, if at this point you don’t have any good reason – don’t add one!! If you think an application might need to communicate with yours in the future, remember it is only that – “might”. You cannot anticipate accurately what it might need – you’d get contracts and message exchange patterns wrong, you’d be increasing the attackable surface area of your application, and you’d be complicating your development, maintenance, and deployment.


You should always build to meet the requirements.


What I don’t mean is that you should make your application rubbish – for example, having an application with a good User Experience should always be a requirement. But having one that enables the user to change the layout of your pages – that might or might not be a requirement. If it isn’t a requirement, don’t spend extra time designing and building it.


If you’re convinced that something should be done but it isn’t a requirement, you need to revisit your requirements (a great example of this is instrumentation – so often missed from non-functional requirements!). If you don’t revisit the requirements, you (the techie) are making up your own requirements, and that becomes very dangerous territory.


Design knowing that you’ll need something else tomorrow


The problem with only building what you need today is that we all know systems change and evolve, need maintaining, upgrading, or fixing. Building only what you need today compliments this though – as I’m sure regular readers know I firmly believe simplicity is something you should strive for in all your systems. It keeps learning curves shallow, and therefore helps keep maintenance and enhancement costs down. Building only what you need helps keep your application simple.


But we must also acknowledge that we know your system is probably going to change. This means you need to consider good architectural and design practices, use well known successful patterns (for example a UI pattern like MVP or MVC), write automated tests to validate your code (both now and when you’re enhancing it later, as they then become great regression tests), use clear naming conventions, ensure you can monitor your system, appropriately componentise the code, and so on.


When you design the API for your application, ask yourself something – “if in 5 years time someone comes to change this, will they understand what my code is doing?”.


Designing your application well means that if we need to add a Service Layer in the future (or perhaps just expose a small part of your logic for another application) the task of estimating, designing, and building these changes is not as complex as it could have been, and it is entirely appropriate that the effort is expended on doing this once you know you need to.


The argument against


What I am also not saying is “build applications as quickly as possible”, or “just databind a data grid directly to your database”. Please don’t just build a bad application, say “it meets requirements”, and blame me! J The term Rapid Application Development scares the life out of me – and I’m certainly not aiming at that! This is why the second principle exists. Your non-functional requirements should describe the need for the system to be maintainable, scalable, supportable, etc – and we as developers and architects know this means following good practices.


 


So what do you think?


 

The small print: Do remember that the examples in this post are primarily targeted at a single system, living in a fairly isolated world. In particular, my comments about Service Layers could be misinterpreted if you’re building an application that is part of an Enterprise’s Service Oriented Architecture – but of course you should have requirements that dictate how it should participate in the SOA, and what systems must integrate with your new application, so the principles hold true.

Comments (6)

  1. I totally agree, with a slight caveat. The problem with designing and building only what you need today, and designing knowing it’ll change tomorrow, is that you’re saying I want to embrace change, you’re not scared by it, and so change has to be easy and simple. If you don’t have a development process that is good at change then as soon as the first change comes along it’ll be hard, and all the high design ideals start to leave the building under the pressure of the change. Don’t forget that the design of a system includes it’s whole lifecycle, from birth to death and the many changes of clothes and hairstyles in between.

    Just my 2p. 🙂

  2. Simon J Ince says:

    @ Rupert

    Good comments mate – I agree. Change is indeed difficult, and actually something I conveniently didn’t mention above is how often change happens in the middle of design, not just a few years later – and that’s even harder 🙂

    Having said that, I still believe good, simple, uncomplicated, clear, minimalistic design helps you handle change… but you’re absolutely right that you need good development processes & change control handling in place to deal with it well.

    Simon

  3. Peter Morris says:

    Hear hear!

    I have my own real-life story about this.  I’ve written about it on my blog and linked it back over to your post 🙂

  4. Simon J Ince says:

    If you liked this, you might like this;

    http://www.37signals.com/svn/posts/1324-beware-of-future-creep

    Found it over the weekend. I think it is getting at a similar topic to what I’ve expressed here… although I prefer my way of expressing the mantra, but I’m biased 🙂

    I also don’t think what I explain is YAGNI as per the comments on that article – it is subtley different, and more complex. YAGNI can be a little niaeve, at least in it’s interpretation… people often miss the second part of my mantra when quoting YAGNI (i.e. know that things will change).

    Enjoy – and let me know if you agree/disagree/have any thoughts.

    Simon

  5. codegoblin says:

    Over a period of time I have this strong feeling that we need to look at these other disciplines

    which have matured over years and learn from them. E.g Civil engineering and architecture, Like no civil architects start to build a row house/House  first and build a twin tower over 10 years reusing bits and pieces from it. So over a period of time if you feel requirements have changed and now customer needs twin tower please demolish the row house and start from scratch. Essentially what I am saying is software engineering has to come to a point of accepting a practice of deprecation/demolition. We cant keep reusing and rebuilding on top of something else. This building for tomorrow kills the application performance/customer satisfaction and even the architect.  

  6. Simon J Ince says:

    @ codegoblin;

    interesting comments. Part of what you say sounds similar to a concept I have in mind that I have loosely referred to as "disposable architecture" – that is basically;

    1. We shouldn’t be afraid to throw things away when they are no longer relevant.

    2. We must design to enable elements to be thrown away without changing other components (i.e. good component design basically!).

    Simon

Skip to main content