Well, #2 should be "the code is a mess" which sometimes is a result from too many layers of abstraction, sometimes from improper abstractions, sometimes from lack of abstractions. In my experience novices underengineer, while experienced coders do tend to overengineer.