Ruthless diligence combined with constant unit testing is the only way to prevent spaghetti code. Even then it's only a band-aid solution. As soon as you stop paying attention out comes the pasta.
Very often I find that spaghetti code is introduced because someone is just plain being lazy that day. They know there is a better way to do it and just don't have the time. When you see that happen there is only one thing to do.
Call them out on it and ask them to change it
I find that pointing out the better way during a code review is usually enough to get people going. If they check it in and I feel strongly, I'll refactor it myself.
Do I occasionally come off as a little bit eccentric? I'm sure I do. Frankly though I don't mind. I'm not a jerk about it and approach this in the best possible social manner. However letting bad code get checked in pretty much assures that I am going to have to debug it at some point in the future. I'd rather take a little flak now and get the right code in.
I also feel that a culture of unit testing also helps prevent spaghetti code. It's much harder to unit test spaghetti code that well factored code. Over time this forces people to keep their code somewhat factored.