Being wrong sucks. Unfortunately, being wrong is a fact of life for developers. Personally I have chosen the wrong technology for the task at hand, made unnecessary abstractions, named variables poorly, repeated code unnecessarily, and so much more.
There are too many factors in play to make every decision the right one. Learning how to deal with being wrong can help you become a more confident developer. Additionally, your code will benefit greatly from your ability to iterate on wrong decisions.
Blinded by the right
If you gave any software problem to a team of experienced developers, chances are each one would have an idea on how to solve the problem. When the question is which approach is the simplest and most effective, some of the developers on that team will have the wrong answer. Not all solutions are created equal, and their pros and cons are often difficult to explain.
Often times developers are blinded by their "right" approach. When that happens, the conversation becomes less productive. Developers start repeating their reasoning multiple times struggling to be understood. Developers don't typically leave these type of long conversations satisfied.
Seek to understand before being understood. Take time to fully understand the other proposed solutions, then generate your opinion. If you agree with their reasoning, be wrong and change your stance. If you disagree, point out misconceptions that the developer is making, then explain your opinion.
It's not about defense or offense
Nobody wants to be known as the person who is wrong all of the time. A lot of developers can't stand the idea of being wrong. When confronted with a wrong choice, it is tempting to defensively justify your decision or offensively criticize something or someone.
Defensive justification
When you justify a wrong decision to yourself or somebody else, you lose an opportunity to learn from your mistakes. A big part of getting better is learning from your mistakes. If you are denying yourself those opportunities by incorrectly justifying a wrong choice, the consequences are detrimental. But how do you know when you are wrong and when you are right?
While it is very difficult to be certain that some choice is wrong and some choice is right, there are lots of indicators that you can choose to appreciate or ignore. If you notice that some indicators keep popping up around a decision you made, you might consider adjusting your mental model of what the right decision is. An example is if you notice some of your code is hard to refactor because your tests keep breaking. You can justify that when you refactor your tests will break. Or you could learn how to write tests that don't enforce too many implementation details.
Offensive criticism
When somebody points out that you made a wrong choice, any number of emotions can come out. Sometimes you get angry at the person because they were "unfair" in their criticism. Other times you get embarrassed because you know you are better than that wrong choice reflects. Many developers are afraid of being wrong, so they deflect the spotlight to how other developers are wrong.
When you offensively criticize a team member, conversation goes from finding the right solution to lowering team morale. This happens a lot when the cost of being wrong is high. A project I was recently on had a high pressure work environment. In the early stages of our project, a team-member of mine made a design choice that didn't pan out and costed us some time. We pointed out to him that it wasn't working out as we progressed. He reacted by working together to find a better solution instead of pointing out mistakes that we had made in the past.
What is right and what is wrong?
Don't be afraid to be wrong. When you don't know what the right design choice is, make a decision and stay principled. If you are making a non ideal design choice but the code is clean, refactoring to the right choice down the road should be trivial. The beauty of software is that nothing is permanent. So we should act like it when deciding what design choices to follow.
Recently I was tasked with writing an application that migrates data from one platform to another. At the beginning of the project, it seemed like building up sanitized SQL statements would be the most effective solution. Eventually we realized that we would benefit from the use of an ORM. Luckily our business logic was decoupled from our data loading mechanism. Swapping the ORM in was a painless task.
The moral of the story
Look at problems objectively, don't defensively justify wrong decisions, don't offensively criticize people who let you know you are wrong, and stay principled. If we (as developers) can be comfortable making wrong decisions and iterating on those wrong decisions, we will make progress on our projects faster.