Agile software development is a fixed point solution to a recursive problem.
When I was a little kid, my mother put me into the local chess club. It took me until today that I realize the impact the training had on me - other than spending my weekends with a bunch of geeks and not being able to get near girls (I don't count the chess playing ones).
As I learned later when I myself became a chess trainer, one of the difficult things in training young kids is to keep them interested in 'boring' things like playing chess. They usually start with a lot of enthusiasm, learning the rules, playing their first few games - until they recognize that there's a huge difference between knowing the rules and playing chess.
I remember when I was in that situation myself. It was just so hard to figure out which of the many options is the best move. I didn't spend another thought on what happened back than for years. But today I realize that Reinhard, our chess trainer, didn't just lecture us if we made a mistake. He just said: "What was the reason you made this move?".
It didn't matter if I found the best move during a game. It just mattered that I thought about the situation for some time and found the reason why I believed my move would be a match winner. For chess there's even an interesting rule that encourages thinking things through before making your move in a rush. It's called "the touched piece rule": if you touch a piece on the board you have to move it - even if it may crush your position.
One of the interesting things of games like chess is that they closely resemble life per se. Every moment of your life you've got a myriad of options to choose from. Every moment of your life you make a decision which move is best. Being a self-conscious human being makes this experience highly recursive and results in a fixed point solution: you may even choose the best way (to choose the best way)* to find the best move.
Many people try to sell you their silver bullets for software development just like a ninety-five percent non-smoking cure. Usually those methods are presented as professional sounding TLAs, lulling you into a mood of dedicated devotion. I try to sell one single piece of the great software equation today.
Adhere to the touched piece rule.
Which basically means: Think before you write code. This sounds obvious, doesn't it? You'll always think about whether the code you just rinse from your brain is correct in exactly the same way that a child learning to play chess asks herself if the move she wants to make is according to the rules, or if there are any current threats lurking from the other side of the board.
Correctly working code is not why you made the move. It's why you moved at all, why your fingers hammer on your keyboard. So the admittedly recursive question is: what is the right question to ask?
Ask yourself for every line of code why you write it exactly that way in this very position.
Just like some moves in a chess game that don't look too bad by themselves can draw a devilish grin in your opponents face, you can easily make the god of entropy smile smugly upon you with a few lines of correctly working code that are a little out of place. Introduce some dependencies here and there and let the butterfly effect do the rest.
This strong dependency on the initial condition in a highly dynamical process like software development gave birth to a methodology of heavy up-front architecture and design. So what's the problem if we can solve our architecture and design problems by thinking things through in the beginning? It's recursivity (again).
Design is code and code is design. If you design up-front you still have to watch every step. This design will not only influence all the design you do from this point on until the project dies or you retire, but it will also influence all the code. And because at the beginning of the project you don't have any experience with the problem domain you'll make a lot of bad moves.
This all culminates in a vicious circle of inexperience and bad design smells. This is the curse of software development: you'll always find a better way to solve the problem after you've solved it. Agile development practices counter this phenomenon by using small iterative cycles in development. Specify what you want - write a solution - refactor using the experience you just gained - redo from start.
This is often criticized as trial and error programming and taken as an excuse not to think about how you write software. But it is the opposite. It's about thinking how to write software before you write it, evaluating what you did after you made the move and then adjusting the code according to what you just learned.
A fixed point solution to a recursive problem.