What is spaghetti code?
blog.jelastic.com
blog.jelastic.com
Given the popularity of OOP during the past few decades, ravioli may be a bigger problem than spaghetti these days.
The wikipedia page for spaghetti code actually has several pasta examples: spaghetti, ravioli, lasagna and spaghetti with meatballs!
However, I've seen a whole crapload of terrible code. You don't need goto to create code that jumps around, and where the state is very hard to determine. That can easily be caused by things like global variables, badly designed code, etc.
Me too.
> I've very, very rarely seen goto statements used
I saw them used all the time in Basic =)
> You don't need goto to create code that jumps around
Nope. All you need is a loop, with lots of continue/break statements mixed in. I have seen this quite a bit and I start twitching when I see it. That's the modern equivalent of the goto.
I use "spaghetti code" to refer to code where execution aimlessly wanders between apparent modules. You don't need goto statements to make it happen. SQL-Ledger is a good example of doing this with simple redefinition of functions. It isn't the only kind of bad code though.
"The goto statement comes in handy when a function exits from multiple locations and some common work such as cleanup has to be done."
No, we don't agree. In C, goto is very often the best way to deal with error paths. It is used in the Linux kernel and in many other important (open source or not) applications. I doubt those qualify as rare.
I think the phrase is correct changing the word programs for languages.
It argues that forward gotos (that work like continue, break, returns mid-function) don't contribute to spaghetti code, while backward gotos are more problematic.
redo: while(true) {
for(Item x : xs)
if(f(x))
continue redo;
break;
}
With goto, redo:
for(Item x : xs)
if(f(x))
goto redo;
Most people seem at first to balk at the goto, even though they're functionally identical, and the goto is much clearer and less error prone...Btw, in Ruby there are two keywords that are basically backward gotos: redo and retry.
Pulling things out into other functions makes it even clearer.
Though yes, the goto is clearer than the labelled continue. I wouldn't necessarily agree that it's less error prone though.
while (fTrueForAny(xs)) { }
boolean fTrueForAny(List xs) {
for (Item x : xs) {
if (f(x)) {
return true;
}
}
return false;
}
There isn't anything non-imperative about higher order functions. var externalDataStore = new ExternalDataStore()
[1, 2, 3, 4].each(x => externalDataStore.store(x))
externalDataStore.getItems().each(item => print(item))
Plenty of higher order functions, and plenty of non-functional, ordered, stateful, imperative code.When I started using Erlang I was amazed at how error handling and all that 'necessary' gumph just disappeared. In the Erlang world exceptions aren't handled up the call stack - when an Erlang process hits an error it just exits.
The Erlang control approach is that for each (restartable) worker process that does something there is a supervisor process whose only job is to catch 'I have died because...' messages from its children and restart sub-systems as appropriate.
It is just amazing what this approach does. There is no longer a 'fog of exception handling' necessary to keep the system running in the prescence of errors, there are clear and consistent reports of ALL errors - which means you can start squashing the bugs that cause them and iterate towards error-free programming.
'Throw' just means 'GOTO up somewhere' it is a posh goto...
The real problem is at the arrival point 'where has the thread of execution come from, and what state is the programme in'.
Exceptions have the same arrival problem 'where in the code did this come from, and what was the state when it was thrown?'
http://michaelochurch.wordpress.com/2012/08/15/what-is-spagh...
The irony of this post is that it could have been about a third of the length and seems to have been subject to a fair amount of entropy and spaghetti-fication itself.
(yes, this is actually a michaelochurch article for some reason syndicated on jelastic?)
Code that jumps around via gotos and functions in various modules can be mapped out and you can gain an understanding of what the code does, but it is less than ideal. Code that changes its behavior depending on the time and order in which it is run is way more dangerous.
Spaghetti code is simply very long functions without structure stuffed with long nested branching. I have seen 3000 lines functions, in PHP, and that's even worse, maybe like those "crossing bridge noodle" you can eat in China.
'while' and 'until' showed up in RATFOR (rational fortran) which fits into the lexical ancestry of 'C'. I think that the Algol family had these too.
without the more powerful control statements, GOTO was heavily used, and with wild abandon. Some variants even let you GOTO up and down the execution stack.
trying to trace logic (of course there weren't symbolic debuggers way back when) could be like following a strand of spaghetti.
my most (not) favorite modern examples are coroutines, but let's not forget the evergreen example of enterprise java wherein one can easily achieve stack depths that boggle the mind.
nevertheless, spaghetti code is a frame of mind in which the untutored implement minimally functional software systems that only work for trivial conditions and for which the source code itself can not be reverse engineered except with great magic, epic heroism and extraordinary luck on the attack roll.
For some though it is a job security abstraction layer.