Implementation

We can build it!

Subsections of Implementation

Introduction

The implementation phase of the waterfall should be the most familiar to you, as it is the actual process of creating the proposed software system. This is, after all, the subject of most of your early coursework - the basics of programming, algorithm design, and considering time and memory complexity of your employed algorithms.

It is critical that the implementation adhere to the details provided by the design, as this ensures that a large body of programmers can work independently on the aspects of the system. But despite the best efforts of the designers, it is not uncommon for some critical details to be overlooked. In a properly implemented waterfall process, this kind of “splashback” is anticipated, and a process exists for proposing, approving, and disseminating changes to the design. Because these changes can cause problems for the other programmers working in other areas of the software, it is important for the change to be communicated clearly to all parties (hence the need for a formal process).

In addition to following the design, programmers in this phase should be applying best practices in terms of documenting the code they write as well as writing automated tests. This effort ensures that the code not only meets the specification, but that it works as intended, and is straightforward to maintain. Remember, the programmers working with the project during its maintainence phase will likely not be those who created it in the first place.

Dev Environments

Implementation work takes place in a development environment - traditionally, a powerful PC with extra tools (compilers, code editors, debuggers, etc) installed. Moreover, the compiler/interpreter is typically run in a debug mode throughout the development process, which injects extra tooling into the compiled/interpreted program to allow for the display of debug information (i.e. giving memory state at breakpoints, etc.). While this makes for a more powerful and speedier development process, there are some implications to keep in mind:

  • Debug Mode
    • Compilers and interpreters will be run in release mode with the final product, without the extra debugger support. On occasion, code that works in the debug version may fail in release, so run in release mode occasionally to identify problems.
    • Because of the additional debug tooling, executables created in a debug build are typically much larger than release builds. This is one reason you never want to release a debug-built executable
    • To better support debugger processes, a debug-mode executable has many hooks for external code to access its internals. THIS IS A SECURITY RISK. Another reason we never release debug builds, only release ones.
  • Development Machines
    • A computer used for development is typically much more powerful that the machines that will be used to run the release code. Thus, algorithms that work perfectly fine on a development machine may be too slow or consume too much memory on an actual target release computer. You should periodically test your program on a target machine thorughout the development to find and address these kinds of problems early.
    • Ideally your development machine and your release machines should use the same OS, as differences between operating systems can introduce hard-to-identify bugs. Moreover, try to use the same OS version, as subtle differences in OS implementations can cause significant headaches in release.