Code in which you need to know everything to do anything is particularly bad code. Some development environments preferentially generate such code over time.
"Spaghetti code" is an epithet too easily flung, and it often signifies nothing more that "code I don't like." But the term "spaghetti code" once marked a particular and singular form of bad code: one characterized by non-locality.
In the beginning was the GoTo statement. Most early languages and compilers had a form of this ultimate abstraction for flow control, and when Edsger Dijkstra declared the construct harmful, in 1968, no small amount of controversy erupted. GoTo had its dedicated adherents.
The problem with GoTo is that it can send program flow anywhere at all. Nothing prevents a program from embodying a dozen code paths that all travel through hyperspace and arrive at the same point. The presence of GoTo greatly reduces the size of a program that can be incomprehensible to a single human mind.
The above insights, and many more besides, can be gleaned from Michael O.Church's blog post What is spaghetti code?. It's a long read at over 3,600 words, but will amply repay your time.
Spaghetti code was not banished when the GoTo dropped out of use. Spaghetti code is created all the time, mostly in enterprises, mostly because code ownership passes from hand to hand and every change to the code tends to weaken it. The transformation of what might once have been a well-understood program into spaghetti code is gradual; it isn't usually any one person's fault; and it won't be caught by code reviews.
Church believes that spaghetti code breeds in the presence of what he calls Big Code: programs that embody the opposite of the Unix code philosophy of doing one thing and doing it well. Church gives some reasons why Big Code becomes unmaintainable:
...Big Code just doesn't work. Dynamic typing falls down in large programs, but static typing fails in a different way. The same is true of object-oriented programming, imperative programming, and to a lesser but still noticeable degree (manifest in the increasing number of threaded state parameters) in functional programming.
Modular programming, unit testing, transparent interface definition, and, to a certain extent, object-oriented programming were all invented to fight against programs creeping towards the land of Big Code.
But Church warns that O-O is regularly abused, especially in large organizations, and is a major cause of the growth spaghetti code in the current age. The problem is that O-O provides great expressiveness and power; but "power" in the sense of programming constructs tends to benefit the writer of code and disadvantage the reader. Church gives a concrete example:
...single-writer code usually remains fairly disciplined: the powerful abstraction might have 18 plausible uses, but only one of those is actually used. There's a singular vision (although usually an undocumented one) that prevents the confusion. The danger sets in when others who are not aware of that vision have to modify the code. Often, their modifications are hacks that implicitly assume one of the other 17 use cases.
Please go read Michael O.Church's essay and let's hash it out in the comments below.