Spaghetti Architecture and the Importance of Starting Over

Lets say that you work for a company, and you produce shapes, depending of course on what the market desires. When you first come to market, you see that people want things that roll. So, you build a circle. It rolls all around, and your customers are happy. A few months later, people are more interested in squares; they can be stacked after all. You take your existing product, attach some corners to it, and you release your square. People are happy, your shapes are stacking up to the ceiling. Before you know it, people really want the structural integrity of the triangle! Again, you take your existing product, add some pieces to it, and you now have a triangle.

I’m sure you can start to see what the problem is. With each new major product revision, instead of starting over, you simply add more stuff to what you’ve already got. Sound familiar? I like to call this Spaghetti Architecture. It is derived from the phrase Spaghetti Code, but instead of just code, it can be applied to larger architectural decisions and even to business practices of non-technical companies.

My suggested fix for Spaghetti Architecture is not to start from scratch with each new revision, but instead to start from scratch at some semi-arbitrary interval, perhaps every few years or before every major version. Sure, that release 3 triangle is ugly, and harder to maintain than a normal triangle, but it would be too much effort to start from scratch all the time.

Starting from scratch is a scary thing. It will take a lot of work to do, the squares and circles you’ve grown to know over the years will be gone. Everything will need to be tested again. But, it is necessary.

With each additional layer of complexity added your product, the codebase is that much more complex. These problems really start to show for large companies. Suppose you are a bank, and you’ve been using the same software for a couple decades. At the heart of your business is a FORTRAN application. Around that is some COBOL. Years later you added a GUI for bankers and a bunch of VB6 code is now mission critical. Finally you added a web interface and did that with a bunch of .NET applications. By now, making the slightest changes to your system require tweaks to four different languages, and a ton of testing.

One day a new banking company comes along, lets say Simple. While you’ve got that circle square triangle product, they already came out with the pentagon everyone now desires. It will take many years for your business to wrap a giant pentagram around its existing triangle square circle, and by the time you’re done, it will probably not be the best pentagram it could have been, not to mention hexagons might be the cats meow.

We call the adding up of these shapes technical debt. You see it every day; perhaps your one-to-one relationship turns into a one-to-many. The system wasn’t originally intended to do that, so you kinda slap some code on it and call it good. When that relationship later turns into a many-to-many, you’ve really shot yourself in the foot. The code starts to look horrible and slows down.

Always keep your different systems modular. If you find yourself building a server to perform some functions of your business, clearly define what the application is supposed to do, and the communication interfaces. Always use standardized messaging protocols, the lighter the better. Abstract your databases if you can, it is much easier for a new technology to make HTTP requests than needing to implement a proprietary binary driver. Keep things well documented; you don’t need a monolithic SOAP API which explains code to the IDE’s of developers. What you do need are human-readable API calls and awesome documentation.

If you keep things simple enough and documented properly, a new hire should be writing apps within a week. Look at GitHub’s API. While it isn’t perfect, it is documented well and easy to work with. Imagine if all of your internal services are this easy and well documented! How many new features could you be churning out given a minimal number of developers?

It is also important for the companies IT department to be able to prioritize projects. Rewriting an application will not make the company money, but it will keep the company fast and able to adapt as markets change. The same thing goes for regular maintenance, which can slow down and possibly remove technical debt. This will one day make or break the company.

tl;dr

Really, what it all comes down to is this: At any given point in time, you know what your product should be. You don’t know what it will be like in the future. With each major revision to the product, you are adding unnecessary complexity to re-shape your product. This complexity adds up and makes development slower. If you don’t eventually start from scratch, you will find yourself becoming un-innovative and sluggish due to the effort required to update these antiquated systems.

Related Posts

Thomas is the author of Advanced Microservices and a prolific public speaker with a passion for reducing complex problems into simple language and diagrams. His career includes working at Fortune 50's in the Midwest, co-founding a successful startup, and everything in between.

I find that rewriting more often also helps lighten the burden of each rewrite; it’s a lot like the old adage of “many hands make light work” but changing the “many” to “often”. Also, the frequency will allow for refactoring based on lessons learned to be more effective.

Anon

Your article sucks and your opinion sucks. Learn to budget and refactor and get over yourself.

Thanks for the link. I did read Joels article while writing this one and almost threw a link to it in my article as a counterpoint. We both have extreme views on the same issue.

taelor

your comment sucks.

but you’re right, I should just stick to the same article everyone has been referencing for the last 12 years, and never think about any other counter notions. ya, that’s the way for software development to progress.

Evan

Well, that was rude, crude, and socially inept. I suppose that is why you hide behind anonymity.

Starting over is very risky and should be avoided, even more if we’re talking a about a decently sized codebase. You should read Joel’s blog post on the matter (linked in Anon’s comment) – he explains it a lot better than I ever could.

Jeff Bell

My program is about 9M-loc. I don’t think we could even retype it in a few years, much less rewrite it.

John Nelson

I think Joel’s points are very good in this regard. To paraphrase, rewriting often results in smaller code, so you can think of it as a ‘compression’. It is, however, a lossy compression mechanism. You will lose stability but more importantly, you will and must lose features. I put must in there, because if you rewrite and hope to retain all your features, you theoretically should end up with nearly the same code you started with, so what’s the point? If you can’t be sure of what features you want and what you don’t, then you cannot rewrite and the opportunity to do so has passed.

However, I do really like how you think of a system as a set of modular products. I think if you think of these products and keep them well defined, both in code and within the company, you can make large improvements, perhaps requiring a rewrite, of your products/services one service at a time. But these services have to be small, isolated and well documented.

tldr;
If you can’t describe exactly what features you will lose by doing the rewrite, you can’t do a rewrite.

Evan

I think you make some good points and there are many good counter-arguments as well. My experience lately is that there are some opportunities to rewrite business applications.

When we talk about architecture, I think about our big corporate monolithic projects. These for me have been farthest from modular, standardized, and normalized. To rewrite these types of projects would cost hundreds of thousands of dollars (if not over a million) and there is considerable risk in investing in a rewrite of this scale where no ROI is realized until you can migrate or flip the switch.

You suggest tight, consistent code with the pentagon example. You fail to consider Joel’s most valid point though, that the odd pentagon shape inherently contains more information and by rewriting it from scratch you’re discarding much of it. You’re assumption is that only waste is discarded, I’d assume not and would rather comb through and improve incrementally.

Cody

Sorry I feel this article is wrong, and based on an idealized world where time is unlimited and work is free!

I worked for a rich company with 30 years of fairly simple code in a single product, that hired a team to re-implement it in c# and sql. 5 years later the project had blown out so much with nothing to show that the new product had to be spun off and what was left of the crippled company sold to a competitor where it was destroyed.

Want to know how long it still took that project to come to market? 5 more years! That’s a whole decade of lost time and the people who were doing it weren’t stupid either. And in the end was it worth it? I don’t know… even a few years after release the new software has problems.

If I’ve learned anything from a decade of real world experience it’s that proper documentation is a dream. Wait, even process documentation is a dream. Wait, even simple commenting is a dream. So any kind of rewrite will always be going in dark; the people who originally wrote the software will have either moved on or be so bitter about what is happening that they’ll be worse than useless.

What you’ve suggested just doesn’t exist, and it doesn’t work in practice.

If you work on a system where the problem is well-defined and the feature set is stable, don’t bother with a rewrite. Just focus on testing and incremental improvement.

If you work on systems where the requirements are dynamic and where major new feature requests requiring come in frequently, it’s very easy to outgrow the design patterns you started with. I’ve seen applications morph so greatly from the initial spec that they literally did not resemble the original concept in any way. If you try to stick to old code and just incrementally adapt, you will at some point be climbing a mountain that is too high.

anon

rewrites work fine across companies – they are a mark of progress, a replacement of the old… Examples like word was a rewrite of word perfect, or excel was a rewrite of lotus 123, mac osx a rewrite of windows… eventually one wins out ;)

dave

It’s not a black and white issue. I’ve known rewrites where the “difficult” features were overlooked or ignored. Some of the time they were dropped from the new release with no obvious client dissatisfaction. At other times we had to implement them, which resulted in ugly last-minute hacking.

I know this is a regurgitation of my hackernews post, but it represents my feelings on this. Good on you for posting this article – it definitely resonates with me.

The post:

If you’ve painted a painting, and you feel as though it no longer represents the work you set out to do, would you just keep painting over it?

Would your work suffer from the same cargo cultism that affected it last time with the same brushstrokes on the canvas adding perverse guidance?

If the changes came in so quick that the paint hadn’t even a chance to dry, you can imagine as well as I can how the painting would look. A big shmear.

Sometimes it is just better to start from a blank canvas.

John Smith

Your competitors will love your view of software development. They will keep adding features, making their customers happy while your customers are waiting for re-writes. How many customers are going to stay with you while they wait?

It is very satisfying as a programmer to start from scratch. Unfortunately, it is very expensive to do that so it is usually not the best approach for the company.