Saturday, July 26, 2014

Applying S.T.O.P. To Software Development

The acronym STOP (or STOPP) is used by several organizations (United States Army, Hunter's Ed, Mountain Rescue, Search and Rescue, Boy Scouts of America), often for describing how to cope with wilderness survival situations or other situations when one is lost (especially outdoors). The "S" typically stands for "Stop" (some say it stands for "Sit"), the "T" stands for "Think" (some say "Take a Breath"), the "O" stands for "Observe", and the "P" stands for "Plan" (some say it stands for "Prepare"). When there is a second "P", that typically stands for "Proceed." In other words, the best approach to use for wilderness survival is to stop, think, observe, and plan before proceeding (taking action). Proceeding without a plan based on thinking and observation is rarely a good idea in for those in a survival situation.

Our approaches to developing software and fixing issues with existing software can benefit from the general guidance STOP provides. In this, my 1000th blog post, I look at applying the principles of STOP to software development.

Developing New Software

For many of us who consider ourselves software developers, programmers, or even software engineers, it can be difficult to ignore the impulse to jump right in and write some code. This is especially true when we're young and relatively inexperienced with the costs associated with that approach. These costs can include bad (no) overall design and spaghetti code. Code written with this approach often suffers from "stream of consciousness programming" syndrome, in which the code comes out in the way one is thinking it. The problem with "steam of consciousness" programming is that it may only be coherent to the author at that particular moment and not later when outside of that "stream of consciousness." It is likely not to be coherent by anyone else. By first considering at least at a high level how to organize the code, the developer is more likely to build something that he or she and others will understand later. At some point, we all write lines of code based on our "stream of consciousness," but that's much more effective if it's implementing a small number of lines in well-defined methods and classes.

When implementing a new feature, the software developer generally benefits from taking the following general steps:

  • Stop:
    • Be patient and don't panic.
    • Don't allow schedule pressure to force you into hasty decisions that may not save any time in the long-run and can lead to problematic code that you and others will have to deal with over the long run.
    • Gather available facts such as what the desired functionality is (customer requirements or expressed desires).
  • Think:
    • Consider what portions of the desired new feature might already be provided.
    • Consider alternative approaches that might be used to implement the desired feature.
    • Consider which existing tools, libraries, and people are already available to might satisfy the need or help satisfy it.
    • Consider design and architectural implications related to existing functionality and likely potential future enhancements.
  • Observe:
    • Confirm available existing tools and libraries that might be used to implement the new feature or which could be expanded to work with the new feature.
    • If necessary, search for blogs, forums, and other sources of information on approaches, libraries, and tools that might be used to implement the new feature.
    • Use others' designs and code as inspiration for how to implement similar features to what they implemented (or, in some cases, how not to implement a similar feature).
  • Plan:
    • "Design" implementation. In simpler cases, this may simply be a mental step without any formal tools or artifacts.
    • If adhering to test-driven development principles, plan the tests to write first. Even if not strictly applying TDD, make testability part of your consideration of how to design the software.
    • Allocate/estimate the time needed to implement or effort needed to accomplish this, even if you call it by a fancy name such as Story Points.
  • Proceed:
    • Implement and test and implement and test functionality.
    • Get feedback on implemented functionality from customers and other stakeholders and repeat cycle as necessary.

The above are just some of the practices that can go into applying the STOP principle to new software development. There are more that could be listed. These steps, especially for simpler cases, might take just a few minutes to accomplish, but those extra few minutes can lead to more readable and maintainable code. These steps can also prevent pollution of an existing baseline and can, in some cases, be the only way to get to a "correct" results. More than once, I have found myself un-doing a bunch of stream of consciousness programming (or doing some significant code changing) because I did not apply these simple steps before diving into coding.

Fixing and Maintaining Software

When fixing a bug in the software, it is very easy to make the mistake of fixing a symptom rather than the root cause of the problem. Fixing the symptom might bring short-tem benefit of addressing an obviously wrong behavior or outcome, but often hides a deeper problem that may manifest itself with other negative symptoms or, even worse, might contribute to other undetected but significant problems. Applying STOP to fixing bugs can help address these issues.

  • Stop:
    • Be patient and don't panic.
    • Don't allow schedule pressure to force you into merely covering up a potentially significant problem. Although a bad enough (in terms of financial loss or loss of life) problem may require you to quickly address the symptom, ensure that the root cause is addressed in a timely fashion as well.
  • Think:
    • Consider anything you or your team recently added to the baseline that may have introduced this bug or that may have revealed a pre-existing bug.
    • Consider the effects/costs of this bug and determine where fixing the bug falls in terms of priority.
    • Consider whether this bug could be related to any other issues you're already aware of.
    • Consider whether this "bug" is really a misunderstood feature or a user error before fixing something that wasn't broken.
  • Observe:
    • Evaluate appropriate pieces of evidence to start determining what went wrong. These might be one or more of the following: reading code itself and thinking through its flows, logs, debugger, tools (IDEs warnings and hints and Java examples include VisualVM, jstack, jmap, JConsole), application output, defect description, etc.
    • Building on the Thinking step:
      • Ensure that unit tests and other tests ran without reporting any breakage or issue.
      • Evaluate revision history in your configuration management system to see if anything looks suspicious in terms of being related to the bug (same class or dependency class changed, for example).
      • Evaluate whether any existing bugs/JIRAs in your database seem to be related. Even resolved defects can provide clues as to what is wrong or may have been reintroduced.
  • Plan:
    • Plan new unit test(s) that can be written to find this type of defect in the future in case it is reintroduced at some point and as a part of your confirmation that you have resolved the defect.
    • Plan/design solution for this defect. At this point, if the most thorough solution is considered prohibitively expensive, you may need to choose a cheaper solution, but you are doing so based on knowledge and a deliberate decision rather than just doing what's easiest and sweeping the real problem under the rug. Document in the DR's/JIRA's resolution that this decision was made and why it was made.
    • Plan for schedule time to implement and test this solution.
  • Proceed
    • Implement and test and implement and test functionality.
    • Get feedback on implemented functionality from customers and other stakeholders and repeat cycle as necessary.

There are other tactics and methodologies that might be useful in resolve defects in our code as part of the STOP approach. The important thing is to dedicate at least a small amount of time to really thinking about the problem at hand before diving in and ending up in some cases "fixing" the problem multiple times until the actual and real problem (the root cause) is really fixed.

Conclusion

Most software developers have a tendency to dive right in and implement a new feature or fix a broken feature as quickly as possible. However, even a small amount of time applying S.T.O.P. in our development process can bring benefits of more efficiency and a better product. Stopping to think, observe, and plan before proceeding is as effective in software development as it is in wilderness survival. Although the stakes often aren't as high in software development as they are in wilderness survival, there is no reason we cannot still benefit from remembering and adhering to the principles of S.T.O.P.

No comments: