You, the developer, intend to exchange code for money with your client. If you deliver something that does not work, and the client pays for it, you have received all the benefit of the transaction and the client has gotten the sucker's payoff. If you deliver functional software, and the client keeps it but fails to pay, the tables are turned and you have received the sucker's payoff. If you both perform cooperatively-- you deliver working software and the client pays--you both benefit, but arguably less than if one of you had taken advantage of the other (you have worked harder, presumably, than if you had delivered minimal, nonfunctional code, and the client is out the money it could have kept.) If you both defect, you both lose out but at least the client has kept its money and you retained your code.
In a perfect world, the client would pay you the whole price at the outset of the software development project, and you would always deliver working code. Since this is not a perfect world, the multi-phased software development contract has evolved, with payments made against successfully completed milestones. This style of contract turns what might have been a one-turn game, with no shadow of the future, into a multi-round engagement; each phase of the contract is in effect a separate round of the prisoner's dilemma.
The classic software development contract, with its guarantee and its acceptance machinery, shifts the sequence of turns so that the client, on each round, may determine whether you have cooperated (by examining your code to see if it meets the spec and is functional) before determining its own move.
However, the contract, if well-drafted and fair, also protects you, the developer, by tightly defining the client's expectations and by restricting the client's ability to defect by withholding acceptance. Without such an agreement (which represents an advance compact by the parties to play the cooperation card on each round), it is all too common a spectacle to see a client withhold payment on the last round, to force the inclusion of additional requirements not previously thought of. Even with a contract, this may happen; since the iterated prisoner's dilemma is for a known number of rounds, the client, not expecting to deal with you again, may defect on the last round, simply hoping to keep the balance of its money. But a well-drafted contract will at least limit its ability to get away with such a defection.
By contrast, most defections by developers are the result of negligence, not malicious intent. The shadow of the future lies more heavily on developers, who wish to remain in the business and obtain good recommendations from clients, while most clients are not themselves in the computer industry, don't expect to need further services immediately and do not anticipate any problems finding software developers eager to serve them even if they have burned one or two.
Defection by the client may take other forms than the withholding of money. It might involve a malicious interpretation of an ambiguous requirement, to include functionality that the developer cannot possibly deliver for the agreed price and still make a profit. Or the client may blame you for its own shortcomings or inability to meet its commitments, making you the scapegoat for an internal political struggle.
Axelrod's experiments determined that the most effective, yet simplest strategy in an iterated prisoner's dilemma is "Tit for Tat", in which you begin with cooperation on the first move but then echo whatever your partner did on the last move. Effectively, what this means is that cooperation is always rewarded with cooperation, while defection is immediately punished with defection. Surprisingly, most software developers are constitutionally unable to apply this strategy to their clients, for a variety of reasons. Project managers may be overruled by salespeople or account managers, who think that being soft on the client is the best long term policy. Sometimes a sense of guilt--did you really do a good enough job on the first deliverable?--intervenes. In any event, whenever I hear of a software development contract in which the developer has commenced Phase II even though Phase I has not been accepted and paid for, I know the developer is playing "All Cooperate", a strategy which will certainly motivate the client to play "All Defect", as it has nothing to lose. And the developer will now receive the sucker's payoff on every round.
The moral is that the developer, to protect itself in an unethical world, must be ready to stop performance on the round following a defection by the client. Of course, before deciding to do so, the developer must conduct an objective review, preferably involving peers not involved in the project, to determine its own responsibility--perhaps the client justifiably withheld acceptance because the developer defected on the last round, and does not know it! But, assuming that you delivered working code and the client has failed to pay, going forward and hoping that all will come out right in the end is a sucker's move.
Since a software development contract is almost always for a known number of phases (and therefore the associated prisoner's dilemma is for a known number of iterations) preventing your client's predictable defection on the last round is a knottier problem. By now, the shadow of the future may be relatively slight; the client has a satisfactory product, but can certainly spot some minor bugs, which, instead of submitting to maintenance, it can pleasantly rely on as an excuse to withhold the last payment. The benefit of the acceptance payment retained in its pocket may seem far greater than the benefit of knowing you are happy and available to do business with it again. Here are some strategies developers use to assure cooperation on the last round: