I just read the article link you posted, I have to say Fowler has made some very good points and a lot of things he said, I've been advocating with our team for years.
IMO, if you do any decent design, you should not get into what would be considered a dead-end situation. I've always viewed software as made up of building blocks. I still believe in some up-front design, but the main goal is not to design the entire product, but to provide overall architecture/direction so your team can visualize a common picture that we are all working towards. If you have a bunch of cube and triangle pieces, it's helpful to sketch out how a castle would be put together before you simply start slapping pieces together.
Since I come from OO land, to me each block is a class and the surface area of that block is the public interface (what is visible by external or deriving classes). If you follow good SOLID principles, you will make sure that each block as extremely simply and has an intuitive public interface. Going back to my analogy, you want to make sure you code only creates simple shapes. Whenever you create classes, that are too complex (many functions, many variables), you creating shapes which are hard to reuse when requirements change.
I agree with Fowler in that the biggest risk/challenge for evolutionary design is that you leave design decisions to coding time, and you expect each individual developer to make those decisions. This is where the system can break down if you don't have proper feedback mechanisms in place. Whenever a new feature is asked for, it is extremely tempting to simply find the function that needs to be extended, put some kind of conditional inside it and just add a whole bunch of code right inside that function. And sometimes, this might be all that's needed, but this is also (IMO) the single most common practice that leads to dead-end components. This has nothing to do with evolutionary design. This is what's called "no design".
As long as you take the time to step back and say, wait a minute, this class already has 15 member variables, let me extract 6 of these and put into their own self-contained class, your software will be made up of very light-weight, flexible and reusable building blocks. Sure if PMs come along and change half the products requirements on you, you may have to take some of your blocks out, put them back on the shelf and draw up some new ones (just like when building a castle, you may not use all your cylinders). But at that point, that's just part of doing business. Requirements changed and by keeping your code flexible and modular, you should be able to change your product to align with your new business direction.
I believe this evolutionary approach to design works with every level of engineer's skill. Personally, I've done software for a very long time and before our team moved to agile methodology, I was responsible for shipping several major components from my dev PC almost directly to the customer with barely any QA. At the same time those components have always remained flexible and maintainable.
I'm only trying to say that I'd consider myself relatively decent at designing software. At the same time, if you asked me to write up a 100-page design document, give it to a coder and expect it to work, I probably couldn't design myself out of a paper bag. When starting work, I would sometimes sketch out few UML-like (very simplified, not full language) diagrams, but as I start coding, I would refactor on as-needed basis and my final code would never look like what I originally drew. Even if I spend a month or two thinking about every little detail, I can't imaging someone else being able to take my diagrams and come up with solid piece of software without modifying the design as they are coding.
On the other end of the spectrum, currently in my team (now agile and I fully support that) we have a couple of guys who joined us from embedded land where they have only done C for the last 15 years. I obviously helped with some initial planning and laying out classes but I also made sure to follow up with regular code reviews and brainstorming sessions where we discuss applications of SOLID and design principles. They did produce some spaghetti code that made me cringe a little, but with just a slight nudge from me, they started refactoring what was already produced and the funny part is that one of them came back to me few days later and says, I hate to say it but after moving that code out, this looks so much more readable and understandable. Dead-end averted. Point I'm trying to make is that even someone who is completely new to OO can produce somewhat decent code, as long as he has a mentor with more experience, to remind him that "evolutionary design" is not same thing as "no design". And even some of his "more complex" classes aren't that scary because each class doesn't have that much responsibility (i.e. not that much code), so worst comes to worse, if that one class "dead-ends", we chuck it and write a replacement class that has same public interface (so far I never saw a need for this contingency in anything we wrote and I've been doing code reviews twice a week).
As a final note, I'm also a firm believer in design documents (at least for the business conditions of my current team) but the primary goal for our design docs is Organizational Memory, so actual documents are written after the code is produced and refactored. Before coding, we generally have a quick (sometimes not so quick) design phase where we sketch out classes on napkins/mspaint/visio and I always remind people that this phase produces a path to follow, not a blueprint and as they start coding, anything that doesn't make sense should be changed. Even with these reminders, newer guys tend to try to back fit code into original design no matter how unnatural it feels even to them. This usually surfaces in code reviews.
Dang, I wrote a lot. Sorry about that.