Architecture is a Second Order Effect
Posted by Uncle Bob on 10/20/2007
We often argue that in order to achieve flexibility, maintainability, and reusability, it is important to have a good software architecture. This is certainly true. Without a well ordered architecture, software systems become masses of tangled modules and code. However, the effect of architecture on the ‘ilities is secondary to the effect that a good, fast, suite of tests has.
Why don’t we clean our code? When we see an ugly mass of code that we know is going to cause of problems, our first reaction is “This needs to be cleaned up.” Our second reaction is: “If I touch this code I’ll be spending the next two weeks trying to get it to work again.” We don’t clean code because we are afraid we’ll break it.
In this way bad code hooks itself into our systems and refuses to go away. Nothing stops clean code from going bad, but once it’s bad, we seldom have the time, energy, or nerve to clean it. In that sense, bad code is permanent.
What if you had a button? If you push this button a little light instantly turns red or green. Green means your system works. Red means it’s broken. If you had a button like this, you could make small changes to the system, and prove that they didn’t break anything. If you saw a batch of tangled messy code, you could start to clean it. You’d simply make a tiny improvement and then push the button. If the light was green you’d make the next tiny change, and the next, and the next.
I have a button like that! It’s called a test suite. I can run it any time I like, and within seconds it tells me, with very high certainty, that my system works.
Of course, to be effective, that test suite has to cover all the code in the system. And, indeed, that’s what I have. My code coverage tools tell me that 89% of the 45,000 lines in my system are covered by my test suite. (89% is pretty good number given that my coverage tool counts un-executable lines like interfaces.)
Can I be absolutely sure that the green light means that the system works? Certainly not. But given the coverage of my test suite, I am reasonably sure that the changes I make are not introducing any bugs. And that reasonable surety is enough for me to be fearless about making changes.
This fearlessness is something that needs to be experienced to understand. I feel no reluctance at all about cleaning up the code in my system. I frequently take whole classes and restructure them. I change the names of classes, variables, and functions on a whim. I extract super-classes and derivatives any time I like.
In short, the test suite makes it easy to make changes to my code. It makes my code flexible and easy to maintain.
So does my architecture of course. The design and structure of my system is very easy to deal with, and allows me to make changes without undue impact. The reason my architecture is so friendly, is that I’ve been fearless about changing it. And that’s because I have a test suite that runs in seconds, and that I trust!
So the clean architecture of my system is a result of on-going efforts supported by the test suite. I can keep the architecture clean and relevant because I have tests. I can improve the architecture when I see a better approach because I have tests. It is the tests that enable architectural improvement.
Yes, architecture enables flexibility, maintainability, and reusability; but test suites enable architecture. Architecture is a second order effect.
omments
Washu 5 days later:
I’ve been interested in how you deal with environments where there are no existing automated test, a whole lot of dirty code, and the very likely chance for side effects.
Clearly this is a case where you need to write tests before you refactor, however how can you be sure of the coverage of your tests when your dealing with languages like C++, where ones tools are so much more primative?
I do realize that on platforms like java and .net the tools are significantly more mature, but one doesnt always have the luck to work in one of those languages.
Its amusing to note how much better the tools are for such young languages than for those older ones like C+. One also notes the lack of a proper C+ compiler, guess kiss holds even in language design. :)
Ashok Gudur 14 days later:
Currently I’m working on a project where the whole application is written in SQL Server 2000 Stored Procedures. It runs as a SQL job and updates the 2-3 tables with final results.
The application is a vehicle transport routing logic. It calculates the low cost route from various locations to various destinations by applying different business rules. The database size is very huge. The existing application takes lot of time (4-5 weeks) to complete the whole process.
My task is to improve the execution performance of the application but the final results should be same. It’s exactly like what we do in Refactoring where the internal design/structure is improved but the external behavior will remain same.
There are 2-3 tables where the final results are stored once it processes the entire database. I can use these tables to compare the final results of both new code and old code.
The whole process takes lot of time to complete even if I take small set of data. Initially I prepared some tests by taking several possible combinations and started doing improvement by running these tests for each single modification. Gradually my numbers of tests are increased and my development is progressing.
Now the problems are like:
1. since the process takes lot of time to execute tests. My development cycle: Modification – run tests – very the results: are taking lot of time.
2. Is with test code coverage. I fear that, whether my tests are still covering all of the code? i.e. even though the tests are passing but they are doing on small set of data. So if I take it to production, will it pass? What if I get some wrong results? How should I know which change caused that?
jewellery over 3 years later:
am preparing the manuscript for production
carmeron over 3 years later:
I have a button like that! It’s called a test suite. I can run it any time I like, and within seconds it tells me, with very high certainty, that my system works.
bag factory over 3 years later:
wever, the effect of architecture on the ‘ilities is secondary to the effect that a
Pandora over 3 years later:
In short, the test suite makes it easy to make changes to my code. It makes my code flexible and easy to maintain.