Thursday, 31 March 2011

OOP Spaghetti code explained

The term "spaghetti code" is usually attributed to pre-OOP code, but there is a lot of OOP code out there that is definitely entangled and a mess. I have seen quite some of it in my carreer, and this kind of spaghetti is characterized by its dependencies.

An class is nothing else than a data structure with associated code, mainly written in a way that puts both into the same source code file. However, if a method for class A depends on a class B, it generates a dependency from class A to class B, no matter if this method is used or not. If class A is about business logic (e.g. "Customer"), and class B is an API thing (e.g. "File"), then the problem isn't that big. A smart compiler can figure out that the method is not used, that there is no active reference to "File", and then maybe not include the File object in the final app. However, if both class A and class B are of the same level in a hierarchy, for instance, if A is "Customer" and B is "Product", then it is usually the beginning of a messy friendship. It doesn't take a lot of these to create a hairball. It gets really bad, if a lower-level class depends to an upper-level class - for instance, if a MySortedListImplementation depends on AppSettings, which depends on Customer.

4 comments:

rick-wheeler said...

Ok, so the explanation is fair enough. But what about a solution? Are you proposing the use of interfaces? Or design patterns? Or both?

The questions remains for small teams/individuals as to how to improve code quality/reuseability and so forth. Many of us or stuck working on:
- old code bases with legacy design issues
- temporary hacks which now seem permanent
- poor/naive initial design which has been progressively refactored but still carries the ghosts of Christmas past

I dont have the time (and perhaps not all the expertise) to fix the spaghetti code, so can do I do? Are there any experts out there who can consult on small once-off projects to help us get a better design and framework for our code which we can then learn and maintain?

Newgroups/books/google only get you so far. I'm not afraid of rolling the sleeves up and getting the work done, but sometimes it is just not that easy.

Lars D said...

I have spent a significant part of my work life rescuing large messy software projects. The solution involves a range of techniques, and somebody even wrote a book about some of them. I think it was called "Refactoring large software projects". The main problem here is, that normal refactoring techniques assume that the code is not buggy, but in large projects you sometimes need to refactor before bugfixing... long story.

Dan Cook said...

I've spent a couple years investigating this, and I've actually come to some determinations and gained some new views on what it means to write software. There's too much to list here, but I'd like to share more with anyone who is interested. For now, look up "simple made easy", "why DCI is the right paradigm for right now", "screaming architecture", "Christopher Alexander, the road, and good software", and find the speech by Christopher Alexander at OOPSLA '96 on YouTube, and peruse worrydream.com. It will take more than an afternoon or even a week to see the connections, but it comes down to thinking about human mental models instead of programmer mechanisms, and I've been able to tie it down to concrete practices as well. For one thing, proper OOP will have a behavioral hierarchy that matches the object-hierarchy (none of this class A calling into class B), otherwise you get OOP spaghetti as described here.

Lars D said...

Many hardcore programmers think very abstract and have a hard time filling out mental models. I often use simple criteria to find the best design: simplicity, robustness, maintainability, performance. If it isn't all 4, find another way to do it. This often leads to great designs. Do they follow a particular methodology? Rarely. But they work extremely well, have few lines of code that are easy to read, and are really easy to maintain.