Many Computer Science departments now offer an upper-level undergraduate or graduate Software Engineering course. Frequently, the undergraduate course is taken by all majors. The students typically have good systems skills but little systematic knowledge of Software Engineering. They need clear explanations of the fundamental principles, detailed examples of good practice, and exercises suitable for objective grading.
Most Software Engineering courses present broad surveys [1] designed to acquaint the student with the basic issues and the most popular techniques. Because these courses cover so much ground they must present the techniques briefly and can only provide abbreviated examples of Software Engineering work products. Other courses focus on formal methods [2]. Mathematical techniques, such as natural deduction, are treated in depth. These techniques are powerful but are difficult to master and apply in practice.
In our course, we make no attempt to survey the field. Instead, we examine one respected technique [3] in depth and give many examples of its application. We keep our mathematical requirements modest by using the same concepts and notations throughout, and by using informal descriptions when the formalisms become cumbersome.