Pretty much all of my development activities start out with the question: “Can the website (or PC, or Smart Phone or toothbrush) do this form me?” My mind’s initial response is flood of brainstorming, ranging across choosing the best programming language and platform, which development philosophies to utilize, how this project fits into the organization’s business needs, how the project is funded, what is the ROI, and on, and on, and on.
To bring myself back in check, and to begin actually developing a solution, I’ve learned to simply rephrase the question as a a problem report.”Can the website (or PC, or Smart Phone or toothbrush) do this form me?” becomes: “When I do this to the website (computer, Smart Phone, etc.), it doesn’t do this.”
Rephrasing this “functional requirement” as a problem allows me to better identify the inputs the user intends to provide, and the outputs the user intends to receive. Of course, there are usually many different inputs and outputs, but by framing to project in terms of a problem to troubleshoot, I can begin working the various input/output pairings (or clusters, as the case may prove to be).
The most simple an effective troubleshooting technique is isolate a problem into a series of events that should work, and then to work from each end, alternating every few steps, towards the middle of the series until the problem is found.
In the case of writing code, the first steps are pretty easy: I start with one expected input and one expected output, and then I create the necessary series in the middle to create the expected output when the input is provided. I progressively add inputs and outputs to the code, increasing the complexity until it gives all of the expected outputs based on the expected inputs (and doesn’t come crashing down when unexpected inputs are provided, but that’s a different article). Each link in the development process will have its own problem cases that need to be resolved, but by working progressively to resolve each failure, the resulting code should be extremely robust and resistant to errors.
If you’re familiar with test-driven development, then this is probably starting to sound familiar. Test-driven development requires developers to create a test for a new feature before beginning development. Approaching coding as a troubleshooting process automatically requires the developer to create a test case by stating the failure state. From there, the coding is simply a matter of preventing the failure case from occurring.