Software Engineering
--------------------

Software engineering provides techniques to facilitate the development
of computer programs (one textbook definition). 
It defines the process by which programs are designed, coded, tested,
and maintained (among other steps).  

The Life Cycle of Software 
--------------------------
Many of you have likely written only simple programs so far, (for example,
for courses) that were discarded once the program demonstrated that you
could use certain skills. But, good software undergoes continuing process
that is called its life cycle.  This life cycle generally consists of:

1. Specifications:  You must first understand the problem is you are solving.
You may get an imprecise specification from a customer initially.
To be able to code a solution, you must have a complete understanding of
many items including: 
  -- the input data
  -- the valid data types 
  -- the desired interface
  -- the errors that need to be detected
  -- special cases need to be handled
  -- the output
  -- documentation needs
  -- etc.
The specifications should not include the method of solving the problem.  

2. Design:  After you know exactly the problem to solve, a solution can be
designed that includes algorithms and abstract data types.  For large programs,
this is usually broken down into well-defined smaller problems. Typically
modules are used that are reusable and as independent as possible.
A module can be a single function or a group of functions. 
The input, output, purpose, and assumptions of each module should be specified.
The design should be independent of the implementation. 

3. Risk analysis: All software projects have some risk in terms of cost and
schedule.  Many have additional risks (for example, software to control an
x-ray machine).  

4. Coding: In this phase, the algorithm and abstract data types are coded using
an appropriate programming language.  When software is well designed, this is
typically a small part of the software life cycle.

5. Testing: This phase is used to detect as many errors in the design and
coding as possible.  The program is tested as a whole and each module is
tested separately, if possible.  Testing should encompass as many special
cases as possible. 

6. Refining: Now that you have a working program, what refinements are
necessary?  Maybe your initial design accomplished everything the customer
needed, but the customer requires added features. 

7. Production: This phase includes distribution, installation, and use of
the software.  

8. Maintenance:  Once the software is in use, bugs will be found, changes will
be suggested, and new features will be requested.

