Not having a problem is often the easiest way of solving it.
Lately me and the team that I'm currently working with have been joined by a couple of developers from Russia. We've been dealing with a few fairly complex problems and had some very interesting discussions. During one of these one of the Russian guys said something that resonated with me. He said something along the lines of "If it's this hard, maybe we're doing something wrong".
During my first year as a professional software developer I was very enthusiastic and ambitious. As soon as I ran into a technical field that I didn't feel that I had a good understanding of I ordered a book about it and read it, often within a week. This worked very well for me and I learned a lot. But I missed something more important than specific technical knowledge. I lacked the instincts that you can only get from experience.
Luckily I had the privilege of discussing code with Emil Cardell over beer or coffee after work from time to time. At this time Emil who had worked in the business a few more years than me became like a mentor to me. Our discussions usually followed a pattern where I would describe a specific problem to Emil. He would then not suggest a solution, which at the time frustrated me, but instead he questioned why I had that problem. It often, but not always, turned out that I could solve my specific problem not by actually solving it but by not having the problem.
Instead of spending hours working out or around some technical issue we discussed what I was trying to achieve with my entire implementation. After that we could usually find another way of achieving the same end goals with a much simpler and more elegant design. Ever since then I've always tried to routinely challenge what I'm doing, especially when I run in to a problem. Often there's a simpler design waiting to be discovered.
That's not always the case though, and I'm not saying that the solution whenever we run into a tough problems always is to toss out an existing design and create a new one. In fact, after a fair bit of discussions about our specific problem, which included listing all functional and technical requirements on a whiteboard and drawing a number of possible designs, me and the Russian guys concluded that we probably were on the right track, or at least that we couldn't find a better solution. And often that's OK.
If the business domain is complex (which is another problem worth challenging, but that’s another post) then the code should be complex as well. We just have to make sure that the code reflects the complexity of the business domain and that it isn't riddled with accidental complexity. And to me the best way of fighting accidental complexity is to challenge what I'm doing whenever I run into a problem which seems hard to solve. I might be doing something wrong.