The Prisoner's Dilemma in Software Development
Last updated: April 16, 2024 Read in fullscreen view
- 01 Oct 2020 Fail fast, learn faster with Agile methodology
- 14 Oct 2021 Advantages and Disadvantages of Time and Material Contract (T&M)
- 08 Oct 2022 KPI - The New Leadership
- 15 Oct 2022 Project-based team model for one-off and pilot software development projects
- 19 Mar 2021 Selective Outsourcing of IT Functions - a new trend in business outsourcing
The Prisoner's Dilemma in Software Development
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:
- Include a software key that must be turned over for the product to work after the date by which acceptance was scheduled to occur. Such arrangements must be clearly disclosed in advance, and even then should only be done with advice of counsel. The more such an arrangement looks like an undisclosed time bomb, the more illegal it may be.
- State in your contract that you own the code until the finbal payment has been made.
- Withhold something pending acceptance, such as source code or a class library irrelevant to acceptance testing but crucial for later use of the product.
- Define acceptance so narrowly in the contract that the client knows it is a virtual certainty that, if it withholds the last payment, you will sue and win.
- Work in a niche specialty in which you are the only player or are recognized to be the best--this will increase the shadow of the future, as it is much more likely the client will need you again.
- Include a maintenance phase in the software contract, following acceptance. If the client expects to need you for maintenance it is less likely to defect.
Key Points' Summary
- Software development relationships are iterated prisoner's dilemmas, where developers exchange code for money with clients.
- The developer receives all the benefits of the transaction if the client pays for functional software, while the client gets the sucker's payoff if they deliver nonfunctional code.
- If both parties cooperate, both benefit, but less than if one takes advantage of the other.
- If both parties defect, both lose out, but the client retains the money and the developer retains the code.
- The evolution of the multi-phased software development contract has turned the game into a multi-round engagement, with each phase acting as a separate round of the prisoner's dilemma.
- The classic software development contract shifts the sequence of turns, allowing the client to determine whether the developer cooperated before deciding its own move.
- A well-drafted contract protects the developer by defining the client's expectations and restricting the client's ability to defect by withholding acceptance.
- Most defections by developers are due to negligence, not malicious intent.
- Defection by the client may involve malicious interpretation of an ambiguous requirement, or the client blaming the developer for its shortcomings.
- Axelrod's experiments found that the most effective strategy in an iterated prisoner's dilemma is "Tit for Tat", where cooperation begins with cooperation on the part of the client.