Iterative Development as Software Craft
The practice of software is part engineering and part craft. Academia is full of coursework designed to teach you the theory of computing and the engineering discipline of writing software. Learning software as a craft, though, seems to occur over time in the profession of software development.
Iteration as a process for software development, in my mind, has always belonged in the realm of "software as craft" rather than "software as engineering discipline". Granted, there is plenty of room to look at iteration as part of an engineering process, but I relate it to how writers of novels build a story and refine the story over a series of drafts until they arrive at a completed work.
My approach to software development has always been to build a working skeleton of an application and then refine and expand it over time using an iterative approach. I'm going to share, briefly, the why and how of my approach.
Iterative Development as Craft
Building complex software systems is hard. If you've worked in the field for a few years, you've probably had more than your share of frustrations during a complex software project where careful planning went into the requirements gathering and specification phase, only to have some significant aspect of the specification change midway through the project. These kinds of failures (yes, they are failures, though individually they might not doom an entire project) have become less common through the use of iterative software development.
Instead of trying to build every aspect of a software system in a single pass, iterative development encourages you to build a skeleton of functionality for the application, prove that it works, then layer in additional functionality in successive passes. The craft of iterative development begins with understanding how much you can build in a single iteration without compromising a primary goal of iterative development - building in small chunks to simplify the testing and debugging phase of each iteration. Knowing how much you can take on in a single pass requires enough experience to be familiar with the pace of development and the complexity of debugging for a given system.
By using source control and building iteratively, you can provide yourself with a history that shows in time how your application has developed over a series of iterations. On GitHub, I use semver and tags to mark my progress.
Iterative Development v. Versions
Speaking of semver, you might object, "But you are really talking about versions. Every software company since forever has made successive versions of their products/projects." In a sense, that's true, versions are a long version of iterative development. When I refer to iteration, though, I'm really talking about the process of iterating within the development process, though what that means may be a little fuzzy. In the tasklist altseven sample app, I have been slowly building more complexity into the application over a period of time to demonstrate how the altseven framework has been evolving. You can go to the repos for both projects and see the snapshots (as tags) at each step along the way. When I think of iterative development within a single version, what I am referring to is building in passes to get to a pre-defined end state. Version development (which you can see more clearly in the building of altseven) involves building new features with each successive pass.
Iteration as Exploration
Iteration Within a Single Task
Even within individual version development projects, you may have isolated tasks that benefit from an iterative process. Recently, I completed a two year consulting project that involved converting large chunks of a twenty-ish year old codebase into a new framework in the same language (CFML). If you've never taken on a project like that, you might immediately think about writing some sort of parser to read in the old code and generate output code in the new framework. While that might work in certain projects, in this particular project I felt like there was no payoff for trying to write a proper parser for old CFML. Instead, I used an iterative process where I slowly ported individual pieces of code into the new framework, tested that they worked, and made successive passes at the code until I had ported the entire chunk of functionality.
One aspect of this particular task involved porting tag-based CFML code to cfscript, the ECMA-compliant script version of CFML. I have found that a series of passes using regular expressions inside a text editor/IDE can be used to convert a lot of CFML code to cfscript with very little hassle. Because of the nature of the old codebase, this approach made far more sense than trying to write a very complex parser to read in the old code base and try to output something useful for the new framework.
I hope that I have helped you understand, in at least some minimal detail, both the motivations and the strategies behind iterative development. Going into more detail requires digging into code and showing real world examples, and might require a book length discussion to provide useful insight into the details of the process.