Software Development Methodologies
This page is a brief introduction into some modern strategies used in the software creation process. The seven development phases are: analysis, design, coding, testing, debugging, production and maintenance.
System Analysis
Analysis is the process of determining what is actually required of the proposed software system. This includes the initial problem definition statement and a detailed requirements specification. Data and functionality are specified using a limited set of operative nouns and verbs so that automated techniques can be used to investigate completeness of specification and allow design validation. A model of interactions is also developed.
Design Methods
Design uses the analysis model and requirements specification to develop a detailed class specification. The two fundamental goals used in designing data structures and algorithms are correctness (aka robustness) and efficiency. Academic research and software engineering case studies have shown the need for specific methodologies to attack issues such as:
| Program Design Goals | Implementation Goals |
|---|---|
|
|
The following solutions for designing computer programs are listed in a rough chronological order of development. Bear in mind that early projects focused on a single homogeneous user group with tight constraints in functionality. Major projects now tend to be generic toolboxes that let users refashion to their own requirements.
Paper Methods
Data Flow Diagrams (DFD) which included decision charts as well as Input-Process-Output mapping formed the rudimentary tools for design in the fifties and sixties. A modern object oriented version is CRC cards which outline class responsibilities and collaborations.
Whiteboarding and Prototyping
Once simple languages like Basic and interactive terminals were readily available, quickly programmed overview programs which provided whiteboarding and/or prototyping helped identify many user interface issues and the requirements and expectations of clients.
Computer Aided Software Engineering (CASE) methods
Commercial programs are so complex that rigorous design methodology must be enforced through software tools. Too bad many commercial and institutional sites have not grasped this yet :-(
Coding Solutions
Coding is programming in the small. Functionality and appearance have already been determined in the design phase. Readability, reusability, predictability and efficiency are the major goals at the coding level. And of course there are always tradeoffs to consider!
Structured Code
Structured code was designed as a remedy for the ills of spaghetti code languages like assembler and Fortran. In early programs the functionality was often scrambled and undecipherable even to the original coder. Data checking was a required part of the program itself and each writer had his own techniques and failings.
Structured control flow with code block structures, closed loops, selection mechanisms and function calls reduced or removed the need for 'goto' transfers as well as keeping the algorithm 'together'. Structured data also forced early declaration and often initialization prior to use. This helped trap many 'change of type' errors and initialization assumptions.
Streamed IO
Streamed IO allowed programs to consume and produce data with no regard to source or destination. This allowed programmers to focus on functionality. The operating system allowed redirection and piping of data which allowed programs to be written as data 'filters'
Virtual Machines
The advent of microcomputers in 1975 emphasized the difficulties in implementing larger systems on a multiplicity of divergent platforms. To promote the use of Pascal over a wide range of micros, the Computer Science Department of UCSD used a virtual machine metaphor in its implementation of the language. A 'p' code machine was designed and their UCSD Pascal language and operating system was written in 'p' code. They then implemented interpreters for several microcomputer platforms to run the 'p' code. Other virtual machines followed such as the Forth f-code machine [this author's thesis was based on porting f-code to several microcomputers that were state-of-the-art at the time].
The main problems virtual machines had were:
- Lack of machine code optimization due to differences in the real machines that they will run on.
- The inherent slowness of the interpretation process.
These issues were solved with:
- Optimization techniques applied directly to the p-code
- Development of faster CPUs
Java is the most common modern example of the virtual machine metaphor. Java also exhibits object oriented, event driven and platform independent features.
Threaded Interpretive Languages
Threaded interpretive languages have three advantages over previous offerings: rapid edit-run-debug cycle times, extensibility, and easy mini-language construction for special tools.
Object Oriented Languages
Object oriented languages use objects and messages as metaphors for dealing with things and actions affecting those things. Object structures have properties (ie. qualities or states) and methods (ie. procedures) associated with them. Objects allow encapsulation (ie. properties and methods are contained within the object itself and information hiding (ie. they can contain properties that can only be accessed by using a method associated with that specific object). Classes (eg. Java and C++) and prototypes (JavaScript) are models for making new objects. Object classes|prototypes can inherit properties and methods in a hierarchal manner from other classes|prototypes while adding their own as well. This capability makes object oriented languages reusable and extensible. Object oriented methods exhibit polymorphism. That is they can perform alternate actions based on the objects they are fed as parameters. JavaScript, Java and C++ are examples of modern object oriented languages.
Event Driven Languages
Event driven languages 'react' to activities initiated by the system or user rather than following a sequence of operations as older languages did. Examples of system events are timers, file load, and file unload. Examples of user events are mouse clicks and cursor movement.
Scripted Languages
Scripted languages are text based and interpreted rather than being compiled into specific machine code. This allows you to write with any editor and use a simple edit, test, change routine for development. It also exposes other author's examples to your eyes. This gives you lots of programming examples to work from as well as a cookie cutter approach to application writing.
Third Party Code
Utilities and toolboxes provided by third parties (other than the language or operating system vendor) are popular with those who prefer not to reinvent wheels. Careful consideration most be given to several factors including: source code availability, documentation, support, cost and trust.
Open Source Code
At first glance revealing the source seems to be a bad idea. However this strategy allows many eyes to evaluate, suggest improvements or spot flaws in code design, structure and efficiency. This has lead to software that is even better than commercial products (such as seen in the browser game) and to a freer exchange of ideas among programmers. It has also created a split between the C.I.S. mindset and the skunkWorks operations guru spirit.
Platform Independence
Platform-independent programs can operate on various operating systems (eg Windows, MacIntosh, Linux, Sun, etc.) and produce similar results. There may be some variations due to speed, memory size, or other physical limitation but in theory the operation and results are the same. Originally programs were rewritten for each platform they were to operate on. This led to maintainability problems as functions didn't perform identically and new functions were not consistently added to each platform.
Once languages that could be compiled on several platforms were created, programs were designed with platform dependent functions such as i/o and display isolated into separate modules. These modules were then replaced with the appropriate platform dependent elements at compile time using a make utility. This methodology placed the burden of independence on the programmer.
The next technique developed was the platform-independent toolbox API. wxWidgets is an example of this technique. Programmers only needed to learn the toolbox hooks but they had to rely on a third party for support of the toolbox. The major disadvantage is that multiple (ie one for each platform) 'executable' packages needed to be made available.
Platform-independent languages normally use a virtual machine to achieve independence.
Testing Methods
Compilation guarantees correct syntax but not necessarily quality code. Testing is essential to confirm that a system meets the requirements specification. Static testing using lint-like analyzers help in writing better code. Some of the problems that they can detect are:
- variables being used before being set
- conditions that are always true/false
- calculations whose result is likely to be outside the range of values representable in the type used
Automated scripted tests are used to identify conformance issues as well as catching regression errors. They are developed in the design phase. Testing is divided into unit tests, integration tests and system tests.
Unit tests are written for each class and must exercise each method (especially end of range values) and produce predicted output. A test harness replaces the main program and exercises all methods and constructors. Stubs replace the units not being tested as these may still not exist. Stubs normally return a 'got to xyz' message and a valid return value if a function method.
Debugging
Debugging involves determining which class or part of a class is not performing as required and changing the code to correct the problem.
![[logo]](images/inria.gif)