The problem is not that the coder has a vague idea of what they are coding, but the requester only has a vague idea of what they want.
No amount of engineering is going to fix that. And the requester has the money that pays you. Nor do they want to be educated, either. (How <dare> you tell a senior manager that they don't understand what they are asking! Ahem. . . not habit forming. . .)
Let me give you a real life example. I was working for one of the top three US banks. (For legal reasons, don't ask who. At the time, they were the largest handler of mortgage security payments in the world. Yes, <that> big.)
The US law prevents banks for paying interest on cash balances for non-profit organizations. (At least at that time. Who know what the law is today.) But top management wanted to pay interest to get more business. The question was, how can we cheat and do this anyways? (This goes on all the time with the "Big Boys" in the financial industry.)
The lawyers said, 'You can pay rebates for fees legally. Everybody charges fees out the wazoo, so you can reduce their fees up to zero amount, and get away with it. It's not interest <wink>!"
So my phone rings. Can I code non-profits to get interest without calling it interest? Of course, they want it flexible, based on a widely available index, like Fed Funds rate, or LIBOR. Example, non-profit X would get rebates at Fed Funds rate - X percent. And could they have it yesterday?
Yes, I can do it, but it will take a couple of weeks to code and test, and another month to get it through the bureaucracy.
I will now ask, where is the major flaw in the request. Not from a legal standpoint, not from a moral standpoint, but from a sheer design/implementation standpoint. The flaw that will cause an emergency call a couple years later?
The hand grenade was - "rate - X percent". What to do if the base rate fell below minus percent? The calculated rate would become negative, which would cause fees to jump even above what was legally allowed. Not good for the business - potentially. . .
After an hour or so of analysis (I'm a full service programmer), I point this out. I was firmly told that base rates would never get that low, don't code a negative branch. (Remember, these are the people who sign the checks. . . ) I went back to my desk, shook my head, and murmurer "morons", and coded a negative branch to load zeros to the rebate amount anyways, so I wouldn't get that 2 AM phone call, and just didn't bother to tell the stupid user.
Sure enough, 2 years later, I'm sitting at my desk, contemplating the latest user idiocy, when the phone rings. "OMG, rates are dropping below our rebate contracts! How can we fix it before the customers get overbilled!"
I replied, "Rest easy, I put in a negate rate scenario fix when I put in the project." 'But I told you not to." "Yeah, well, you're calling me for it now, right?" "Ummm. Yes." "It's called 'being proactive'. Now I defaulted the amount to zero if it calculated out negative. Is that what you want?" "Yes." "Ok, Relax and have a cup of coffee. You can tell the brass you already had the possibility thought of and prepared for." "You'd let me take the credit?" "Sure, if you put me in for a bonus." "Fine!" (Note, I never got a bonus.

I did get my just reward. I was laid off a year later. No good deed goes unpunished. That little patch, 3 lines of COBOL, saved the bank more money than than my entire salary for my entire career there. So they had to save more . . .

)
My point on this yarn is that you can't have engineering discipline when you don't have fixed definitions. In an environment where laws and rules are always changing, there can be no "by the book". There's no "book" to be by.
That's why I'm a programmer, not a Software Engineer.