This is an AMP version of the article, its original content can be found here.
Puzzle Driven Development
PDD, or Puzzle Driven Development, is a method used to break down programming tasks into smaller ones and enable their implementation in parallel. The PDD method is used widely in XDSD methodology. The method is pending a USPTO patent (application no. 12/840,306).
Let's review the method with an example. Say, for instance, you are a programmer
and have been tasked to design and implement a Java class. This is the formal
task description: "class
DBWriter has to extend
class and save all incoming data into the database".
You have one hour to implement this task. It is obvious to you that one hour is not enough because the problem is much bigger and requires more work than the slotted time allows. Additionally, there are a numerous unknowns:
- What information do we need to save, and in what format?
- What is the DB schema? Is it an SQL or NoSQL database?
- How to connect to the DB? JDBC? JPA? DAO?
- How to handle exceptions?
Let's keep all these unknowns in mind as we try to solve the problem on the highest level of abstraction. Of course, we start with a test:
In the above test, we define the expected behavior of the class. The test fails to compile because there are two missing classes:
DBWriter. Let's implement the bridge first:
Next, the writer itself:
Using the above code, we solve the problem. In the example, we successfully
designed, implemented and tested the required
DBWriter class. Subsequently,
the class can now immediately can be used "as is" by other classes.
Of course, the implementation is not finished, since we are not writing anything to the database. Furthermore, we still aren't answering the majority of questions asked in the sample scenario. For instance, we still don't know exactly how the database needs to be connected, its type (SQL or NoSQL,) the correct data format and so on. However, we've already made a number of important architectural assumptions, which allowed us to implement the class and make it usable by other classes.
Now it's time to identify the unknowns in our code and mark them with puzzles. Every puzzle is a request for refinement. We want to ask someone else to help us refine and correct our assumptions. Here is the first puzzle we need to add:
The puzzle has three elements:
#123 locator and a comment.
Locator displays the following: "The puzzle was created while working with
Let’s add one more puzzle:
This puzzle indicates one of our concerns because we are not sure that the architectural decision is right. Actually, the design is very primitive at the moment and very likely to be incorrect. To refine it and refactor, we require more information from the task specifier.
The task is finished. Now, you can reintegrate your branch into
return the ticket to whoever assigned it to you. His task now is to find other
people who will be able to resolve the puzzles we just created.
Every puzzle created now will produce other puzzles, which will be resolved by
other people. Consequently, our simple one-hour task can potentially generate
hundreds of other tasks, which may take days or even years to complete.
Nevertheless, your goal of working with your specific task is to finish it as
soon as possible and reintegrate your branch into
There are a few simple rules that help you to place puzzles correctly.
First, you should put your
@todo annotations at the point where your code hits
a stub. For example, in a unit test. You're implementing a test and it fails
because the class has not yet been implemented. You skip the test with the
@Ignore annotation and add a
@todo puzzle to its JavaDoc.
Second, your puzzle should remain as near as possible to the code element that is hitting the stub. Say that you have a unit test that has three test methods. All of them fail now because the class has not been implemented. The best approach would be to ignore every one of them and create three (!) puzzles. Each one of the puzzles should explain what you expect from the class and how it should be implemented.
Third, be as descriptive as possible. Your puzzle will soon be a task definition for someone else. So, explain clearly what you expect the next person to implement, how to do it, which documentation to use and so on and so forth. There should be enough information present that the next person assigned to the puzzles is able to implement your required classes without additional input from you!
BTW, puzzle collection process can be automated by means of our PDD Ruby gem.