CSC 307 Lecture Notes Week 4
Introduction to Requirements Modeling
Requirements Inspection Testing
Figure 1: Where modeling fits in the process.
void scheduleAppointment(); void scheduleMeeting(); void scheduleTask(); void scheduleEvent();
class Event { String title; Date startDate Date endDate Category category String location; } class Date { /* ... */ } class Category { /* ... */ }
Java Form | Meaning | Common Interface Form |
int | numeric integer | string editor for numbers; numeric slider bar or dial |
double | numeric real number | same as integer |
String | free-form string value | string editor or combo box |
boolean | true/false value | string editor for true/false value; on/off button |
class data fields | components of the class | box containing other types |
enum literals | one of a set of possibilities | radio buttons; fixed-length listing of selections |
Collection | zero or more components of the same type | variable-length listing of data values or selections |
Method | the type of an operation | push button or menu item |
Table 1: Java Modeling Forms.
class Date { /* ... */ }
class Category { String* list; }
class Category { String name; Color color; }
enum Color { Black, Brown, Red, Orange, Yellow or Green, Blue, Purple; }
class Calendar { void scheduleAppointment(); void scheduleMeeting(); void scheduleTask(); void scheduleEvent(); }
class Calendar { void scheduleAppointment(Appointment); void scheduleMeeting(Meeting); void scheduleTask(Task); void scheduleEvent(Event); }
abstract class Calendar { abstract void scheduleAppointment(Appointment); abstract void scheduleMeeting(Meeting); abstract void scheduleTask(Task); abstract void scheduleEvent(Event); }
"After scheduling and confirming an appointment, the appointment data are entered in an online working copy of the user's calendar."
abstract class Calendar { abstract void scheduleAppointment(Appointment); abstract void scheduleMeeting(Meeting); abstract void scheduleTask(Task); abstract void scheduleEvent(Event);Collection<Appointment> data; }
Collection<ScheduledItem> data;
Figure 2: Monthly calendar view.
import java.util.Collection; /** * A MonthlyAgenda contains a small daily view for each day of the month, * organized in the fashion typical in paper calendars. */ class MonthlyAgenda { FullMonthName name; DayOfTheWeek firstDay; int numberOfDays; Collection<SmallDayView> items; } class FullMonthName { String month; int year; } enum DayOfTheWeek { Sun, Mon, Tue, Wed, Thu, Fri, Sat } /** * A SmallDayView has the number of the date and a list of zero or more short * item descriptions. */ class SmallDayView { int DateNumber; Collection<BriefItemDescription> items; } class BriefItemDescription { String title; Time startTime; Duration duration; Category category; } class Time { /* ... */ } class Duration { /* ... */ } class Category { /* ... */ }
"A module is an independent unit that can be used to construct a more complex structure".
package file; package edit; package schedule; package view; package admin; package options;
Common UI Form | Model Object Type |
One-line Text box | Typically a string. If the requirements narrative defines specific constraints on what can be entered in the text box, then the model structure should reflect these constraints. E.g., if the narrative limits what can be typed to an integer value, then the text box is modeled as an integer. If the narrative defines what can be typed as a two-part value of some form, then the model is a two-tuple (e.g., Time and Date). |
Multi-line Text Area | A string, list of strings, ore more complex object. A single string model is appropriate if the entire text area is entered as one large block of text the system does not decompose in any way. A list of strings is the appropriate model if the line-by-line contents of the text area are handled separately, but each line is not further decomposed. A more complex object model is necessary if the system performs any detailed parsing of the text to analyze its contents. |
Fixed-length
selection list | An enum object, with each element being one of the items in the selection list. |
Variable-length list | A Collection object, with elements corresponding to the type of the selections. |
Check-box | A boolean object. When check boxes are grouped together in the UI, model the group as a tuple of boolean objects. |
Radio-button(s) |
A boolean object or enum. A single on/off radio button is modeled as a
boolean, e.g., a single radio button labeled "Yes/No" or "On/Off". When radio
buttons are grouped together as a set of alternatives, the model is an enum
with one component for each alternative. For example, with a group of radio
buttons labeled "Range", with button labels "High", "Medium",
and "Low", the model is
enum {High, Medium, Low} |
Dialog window | A class of objects that model the dialog components. |
Tabbing or
Multi-Panel dialog | A class with data fields for each tab panel, with each component class defining one of the tabs or panels. |
Specialized "widgets" | Graphical interfaces may contain an assortment of primitive-level forms, such as on/off toggles, numeric slider bars, and small icons representing single values. A good rule for the use of such forms is if the corresponding model object is not readily derivable from the widget, then the widget is probably not that easy to understand for the user and should be replaced with a simpler form. |
class Appointment { String title; Date startDate; Date endDate; Time startTime; Duration duration; RecurringInfo recurringInfo; Category category; Location location; AppointmentSecurity meetingSecurity; AppointmentPriority priority; RemindInfo remindInfo; Text Details; }
class Meeting { String title; Date startDate; Date endDate; Time startTime; Duration duration; RecurringInfo recurringInfo; Category category; Location location; AppointmentSecurity meetingSecurity; AppointmentPriority priority; RemindInfo remindInfo; Attendees attendees; Text Details; Text Minutes; }
class Task { String title; Data dueDate; Date endDate; Category category; Security security; int Priority; RemindInfo remindInfo; Text details; boolean carryOverFlag; boolean completedFlag; }
class Calendar { . . . void scheduleEvent(Event); . . . }
class ScheduledItem { title; startOrDueDate; endDate; category; } class Appointment extends ScheduledItem {...} class Meeting extends ScheduledItem {...} class Task extends ScheduledItem {...} class Event extends ScheduledItem {...}
/* * * This file defines objects and operations related to calendar scheduling. * See Sections 2.2, 2.4, and 2.5 of the Milestone 6 requirements. * */ import java.util.Collection; /** * The Calendar object is derived from an overall view of Sections 2.1 through * 2.5 of the requirements. The functionality described in those sections * makes it clear that a Calendar is the primarily data object of the Calendar * Tool. * * The data component of a Calendar is a collection of scheduled items. The * operations are those that schedule each of the four types of scheduled * item. In the case of meetings, there are two operations involved -- one to * compute a list of possible times, and another to confirm a specific selected * meeting time. */ abstract class Calendar { Collection<ScheduledItem> data; /** * ScheduleAppointment adds the given Appointment to this.data, if an * appointment of the same time, duration, and title is not already * scheduled. */ abstract void scheduleAppointment(Appointment appointment); /** * ScheduleMeeting uses the given MeetingRequest to determine possible * times that the requested meeting might be held, within the existing set * of scheduled items in the this.data. The PossibleMeetingTimes output is * a list of zero or more possible times and dates that the meeting can be * held. */ abstract PossibleMeetingTimes scheduleMeeting( MeetingRequest meetingRequest); /** * ConfirmMeeting takes a MeetingRequest, list of PossibleMeetingTimes, and * a Selected time from the list. It adds a meeting to this.data, * comprised of the given request, scheduled at the selected time. Further * details of output constraints are forthcoming. */ abstract void confirmMeeting( MeetingRequest request, PossibleMeetingTimes times, int selectedTime); /** * ScheduleTask adds the given Task to this.data, if a task of the same * time, duration, and title is not already scheduled. */ abstract void scheduleTask(Task task); /** * ScheduleEvent adds the given Event to this.data, if an event of the same * time, duration, and title is not already scheduled. */ abstract void scheduleEvent(Event event); } /** * A ScheduledItem is the generic definition for the types of items stored in a * calendar. The Title component is a brief description of what the item is * for. The startOrDueDate and endDate components indicate when the item is * scheduled. The category component is used to organize items into related * color-coded categories. * <p> * There are four extensions of ScheduledItem. They are Appointment, Meeting, * Task, and Event. A ScheduledItem is derived from examining the common data * fields of these four types of item, and the requirements narrative that * describes these items. * <p> * The startOrDueDate is a multi-purpose component of ScheduledItem. Its * purpose depends on whether an item is a Task and whether it is recurring * (Events cannot recur). For non-recurring appointments and meetings, * StartOrDueDate is used as the single date on which the item is scheduled. * If the item is recurring, StartOrDueDate is the first date on which it * occurs. For a non-recurring Task, StartOrDueDate is the single date the * task is due. If the task is recurring, StartOrDueDate is the first date it * is due. * <p> * In recurring appointments, meetings, and tasks, the endDate defines the last * date on which the item will recur. In events, the end date defines the last * date of a multi-day event. When the value of end date is empty, the * startOrDueDate component is interpreted as the single date on which the item * occurs. */ abstract class ScheduledItem { String title; Date startOrDueDate; Date endDate; Category category; } /** * An Appointment adds a number of components to a generic ScheduledItem. The * StartTime and Duration indicate when the appointment starts and how long it * lasts. The Location is where it is held. The Security indicates who can * see that the appointment is scheduled. AppointmentPriority is how important * the appointment is. RemindInfo indicates if and how the user is reminded of * the appointment. Details are free form text describing any specific * appointment details. * <p> * This object is derived from Section 2.2 of the Milestone 6 requirements, in * particular Figure 6. */ abstract class Appointment extends ScheduledItem { Time startTime; Duration duration; RecurringInfo recurringInfo; Location location; Security security; AppointmentPriority priority; RemindInfo remind; Text details; } /** * A Meeting adds two components to an Appointment. The Attendees component * reflects the fact that a meeting is scheduled for more than one person, * whereas an appointment is for a single user. The MeetingMinutes component * is a URL for the minutes of a meeting, once it has been held. * <p> * This object is derived from Section 2.4.1 of the Milestone 6 requirements, in * particular Figure 46. */ abstract class Meeting extends Appointment { Attendees attendees; MeetingMinutes minutes; } /** * A meeting request has all the components of a meeting plus three additional * components to specify the latest dates and time at which the meeting can be * scheduled. A meeting request is used to specify a range of possible meeting * times, to allow scheduling alternatives to be considered. In the meeting * request, the inherited fields for startDate, endDate, and time are used for * the earliest dates and time at which the meeting can be held, i.e., for the * beginning values of each range. The description of the ScheduleMeeting * operation has further details on how meeting requests are handled. * <p> * This object is derived from Section 2.4.1 of the Milestone 6 requirements, * in particular Figure 45. */ abstract class MeetingRequest extends Meeting { Date latestStartDate; Date latestEndDate; Time latestStartTime; } /** * The PossibleMeetingTimes object is a collection of (start time, start date) * pairs at which a meeting could be held. */ abstract class PossibleMeetingTimes { Collection<TimeAndDate> timesAndDates; } /** * A TimeAndDate object is an element of a possible meeting time list. */ class TimeAndDate { Time startTime; Date startDate; } /** * Like an Appointment, a Task adds a number of components to a generic * ScheduledItem. A Task differs from an Appointment as follows: (1) * Appointments have StartTime, Duration, and Location; Tasks do not. (2) For * Appointments, the priority is either 'Must' or 'Optional'; for Tasks, * priority is a positive integer indicating the relative priority of a task * compared to other tasks. (3) For appointments, reminders can be set to * occur at hour or minute granularity; for tasks, the smallest granularity of * reminder is a day. (4) Tasks have a completedFlag, and completionDate * components; appointments do not. * <p> * The completedFlag is true if a Task has been completed, false if not. The * system does not enforce any specific constraints on the setting of a task's * CompletedFlag. That is, the user may set or clear it at will. Hence the * meaning of the completedFlag is up to user interpretation, particularly for * recurring tasks. * <p> * The completionDate is the date on which as task is completed. The system * does not enforce any specific constraints on the setting of a task's * completionDate (other than it being a legal Date value). As with the * completedFlag, the meaning of the completionDate value is up to user * interpretation, particularly for recurring tasks. * <p> * This object is derived from Section 2.4.2 of the Milestone 6 requirements, * in particular Figure 47. */ abstract class Task extends ScheduledItem { RecurringInfo recurringInfo; Security security; TaskPriority priority; TaskRemindInfo remind; Text details; boolean completedFlag; Date completionDate; } /** * An Event is the simplest type of ScheduledItem. The only component it adds * to is Location. * <p> * This object is derived from Section 2.4.3 of the Milestone 6 requirements, * in particular Figure 48. */ abstract class Event extends ScheduledItem { Location location; } /** * An AppointmentPriority indicates whether an appointment is a must or if it * is optional. This information is used to indicate the general importance of * an appointment to the user. The operational use of AppointmentPriority is * in the ScheduleMeeting operation, where the meeting scheduler can elect to * consider optional appointments as allowable times for a meeting. */ enum AppointmentPriority { Must, Optional } /** * A TaskPriority is a positive integer that defines the priority of one * task relative to others. It's defined as a separate class in case we want * to enforce the value range restriction within the class constructor. */ abstract class TaskPriority { int value; } /** * For now, a Date is just as string. This definition will expand soon. */ abstract class Date { String value; /** * Aux function used in scheduleEvent specs. */ abstract boolean isValid(); } /** * Duration is the time length of a scheduled item, in hours and minutes. */ abstract class Duration { int Hours; int Minutes; } /** * As with Date, Time is for now just as string. This definition will expand * soon. */ abstract class Time { String value; } /** * RecurringInfo has components to specify the nature of a recurring item. The * isRecurring component is an on/off flag that indicates whether an item * recurs. The interval is one of Weekly, Biweekly, Monthly, or Yearly. The * IntervalDetails component defines the precise means to define recurrence for * the different interval levels. */ abstract class RecurringInfo { boolean isRecurring; Interval interval; IntervalDetails details; } /** * Interval specifies the granularity at which recurring items are defined. * The Weekly and Biweekly settings allow the user to specify recurrence on one * or more days of the week. The Monthly setting allows the user to specify * recurrence on one or more days in one or more weeks of each month. The * Yearly setting allows the user to specify recurrence on one or more specific * dates in the year. */ enum Interval { Weekly, Biweekly, Monthly, Yearly } /** * IntervalDetails are either weekly or monthly. This parent class is used * generically for either kind of details. */ abstract class IntervalDetails {} /** * WeeklyDetails has an on/off setting for each day of the week on which * an item recurs. These details are also used for the BiWeekly setting * of the recurrence interval. */ abstract class WeeklyDetails extends IntervalDetails { int onSun; int onMon; int onTue; int onWed; int onThu; int onFri; int onSat; } /** * MonthlyDetails can be specified on a day-of-the-week basis or on specific * date(s) basis. The two extending classes have the specific details for these * two types of settings. This parent class is used generically for either * kind of details. */ abstract class MonthlyDetails {} /* * MonthlyDayDetails contains a weekly details component for each possible week * of a month. The First- through ThirdWeekDetails are distinct for all * possible months. Depending on the configuration of a particular month in a * particular year, there is potential conflict in specifying recurrence in the * fourth, fifth, or last weeks. The conflicts are resolved as follows: * <p> * For months with 4 weeks only, the settings in FifthWeekDetails do not apply, * and the settings in LastWeekDetails, if present, override any settings in * FourthWeekDetails. For months with 5 weeks only, the settings in * LastWeekDetails, if present, override any settings in FifthWeekDetails. * (For months with 6 weeks, the LastWeekDetails component applies to the 6th * week, and there are no conflicts.) */ abstract class MonthlyDayDetails extends MonthlyDetails { WeeklyDetails firstWeekDetails; WeeklyDetails secondWeekDetails; WeeklyDetails thirdWeekDetails; WeeklyDetails fourthWeekDetails; WeeklyDetails fifthWeekDetails; WeeklyDetails lastWeekDetails; } /** * MonthlyDateDetails is a collection of zero or more specific dates in a month * on which an item recurs. */ abstract class MonthlyDateDetails extends MonthlyDetails { Collection<DateNumber> dates; } /** * A DateNumber is a positive integer between 1 and 31. It's defined as a * separate class in case we want to enforce the value range restriction within * the class constructor. */ abstract class DateNumber { int value; } /** * A Category has a name and StandardColor, which serve distinguish it from * other categories. Colored-coded categories serve visual cues to the user * when viewing lists of scheduled items in some form. Categories can also be * used in filtered viewing. */ abstract class Category { String name; StandardColor color; } /** * A StandardColor is one of a fixed set of possibilities, per the requirements * scenarios. */ enum StandardColor { Black, Brown, Red, Orange, Yellow, Green, Blue, Purple } /** * For now a Location is a free-form string indicating in what physical * location an item is scheduled. It may be refined to something like * (building,room) pair. */ abstract class Location { String value; } /** * Security is one of four possible levels, each of which is described * individually in the body of the enum. The selected level specifies the * degree of visibility a scheduled item has to other users. For an * appointment, task, or event, "other users" are defined as all users other * than the user on whose calendar the scheduled item appears. For a meeting, * "other users" are defined as all users not on the Attendee list of the * meeting. */ enum Security { /** * Public security means other users can see the scheduled item and all the * information about the item. */ Public, /* * PublicTitle security means other users can see the title of the * scheduled item but none of the other information about the item. */ PublicTitle, /** * Confidential security means other users can only see that a user is * unavailable for the time period of a scheduled item; no other * information about the scheduled item is visible. Since confidential * security applies to a specific time period, it is meaningful only for * appointments and meetings, not for tasks or events; tasks and events do * not have specific time components. */ Confidential, /** * Private security means other users see no information at all about a * scheduled item, not even that the item is scheduled. Note that private * security hides a scheduled item from the ScheduleMeeting operation, * q.v., so that a meeting may be scheduled at the same time as a private * appointment. It is up to the user to handle this situation by * accepting or refusing the scheduled meeting. Given the nature of * private security, it does not apply to meetings. I.e., only * appointments can have private security. */ Private } /** * RemindInfo has a flag that indicates if a scheduled item will have a * reminder sent and defines one of three ways that the user is alerted when a * scheduled event is to occur. OnScreen means the user is reminded with a * pop-up alert on her computer screen. BeepOnly means the user is reminded * with a simple audible tone on the computer. Email means the user is sent an * electronic mail message reminder. */ abstract class RemindInfo { boolean isReminded; HowReminded howReminded; } enum HowReminded { OnScreen, BeepOnly, Email } /** * AppointmentRemindInfo extends RemindInfo by adding information for how * soon before a scheduled item the reminder is to be sent. For appointments, * the time units are minutes, hours, or days (cf. TaskRemindInfo). */ abstract class AppointmentRemindInfo extends RemindInfo { double howSoonBefore; AppointmentReminderUnits units; } /** * TaskRemindInfo extends RemindInfo by adding information for how soon before * a task the reminder is to be sent. For tasks, the time unit is days. A * fractional day can be used for smaller granularity if desired. */ abstract class TaskRemindInfo extends RemindInfo { double howSoonBefore; } /** * Appointment reminders can come minutes, hours, or days before an * appointment. The units for these can be fractional, for maximum * flexibility. */ enum AppointmentReminderUnits { MinutesBefore, HoursBefore, DaysBefore } /** * Attendees is a collection of names of those who attend a meeting. */ abstract class Attendees { Collection<String> names; } /** * MeetingMinutes is current defined as the URL for the location of the minutes * of a meeting. This definition may be refined in upcoming versions of the * requirements. */ abstract class MeetingMinutes { String url; } /** * The details of the Text object are TBD. It may just turn out to be a * plain string. Or it may a limited form of HTML, so we can include linkable * URLs in it. */ abstract class Text {}
/* * * This file defines the objects and operations related to the different * calendar views available to the user. See Section 2.3 of the Milestone 6 * requirements. * * The structural viewing levels are item, day week, month, and year. There * are operations to go to the previous and next views at any level, as well as * an operation to go to a specific date. Lists of scheduled items can be * viewed in a variety of ways. A general view filter operation can be applied * to both structural and list views. Operations are available to view other * users' calendars and to view a list of active viewing windows. * * NOTE: this is work in progress. A good deal of objects are yet to be * defined. * */ import java.util.Collection; /** * A DailyAgenda has a full day name and a list of time-slot descriptors. The * FullDayName consists of the day name itself (e.g., Wednesday), the month, * the date, and the year. Each item in the TimeSlotDescriptor list consists * of a starting time (e.g., 8 AM) and a list of zero or more scheduled items. */ abstract class DailyAgenda { FullDayName name; Collection<TimeSlotDescriptor> times; } /** * A FullDayName has the complete and unique designation of a calendar day. */ abstract class FullDayName { DayName day; MonthName month; DateNumber date; YearNumber year; } enum DayName { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } enum MonthName { January, February, March, April, May, June, July, August, September, October, November, December } /** * A time slot descriptor represents one slot (physically, a row) in a daily * agenda. The TimeSlotName component is the start time for the slot. The * list of BriefItemDescriptors contains the items that begin within the slot, * where "within" is defined as the start time plus the current time increment. * The overlaps component is a list of items with start times that overlap with * an item in the BriefItemDescriptor list. */ abstract class TimeSlotDescriptor { TimeSlotName slotName; Collection<BriefItemDescriptor> itemDescriptors; Overlaps overlaps; } /** * A TimeSlotName consists of a numeric TimeValue and an AmOrPm indicator. * TO DO: this definition should be reconciled as appropriate with the * definition of Time in schedule.java. */ abstract class TimeSlotName { int timeValue; AMorPM amOrPm; } /** * A brief item descriptor contains a subset of the information for a full * scheduled item. The information is a Title, StartTime, Duration, and * Category. */ abstract class BriefItemDescriptor { String title; Time startTime; Duration duration; Category category; } /** * Overlaps contain zero or more BriefItemDescriptors that overlap with with * the master item in a given time slot. An overlapping item is one with a * start time within the same time slot as other items. The "master" item in a * time slot is the item that is first in a sorted order based on start time, * duration, and alphabetic title as the primary, secondary, and tertiary sort * keys, respectively. */ abstract class Overlaps { Collection<BriefItemDescriptor> descriptors; } abstract class DailyFormatOptions { NormalTimeRangeOption normalTimeRangeOption; TimeIncrementOption timeIncrementOption; int incrementHeightOption; ShowOrHide showHide24HoursOption; ShowOrHide showHideExactTimeOption; ShowOrHide showHideDashedLinesOption; ShowOrHide showHideExtensionArrowsOption; OnOrOff proportionalSpacingOnOffOption; DisplayOverlapsOption displayOverlapsOption; DefaultHeightAndWidthOption defaultHeightAndWidthOption; } abstract class NormalTimeRangeOption {Time startTime; Time endTime;} abstract class TimeIncrementOption {int hours; int minutes;} enum ShowOrHide {Show, Hide} enum OnOrOff {On, Off} enum DisplayOverlapsOption {Horizontal, Vertical} abstract class DefaultHeightAndWidthOption {int height; int Width;} abstract class Hour { int value; // Must be legal hour value } abstract class Minute { int value; // Must be legal minute value } enum AMorPM { AM, PM } abstract class WeeklyAgendaTable { FullWeekName name; Collection<WeeklyTimeSlot> slots; } abstract class FullWeekName { MonthName month; DateNumberRange dateRange; YearNumber year; } abstract class DateNumberRange { DateNumber start; DateNumber end; } abstract class WeeklyTimeSlot { Collection<WeeklyItemDescription> items; } abstract class WeeklyItemDescription { DayName day; TimeRange range; String truncatedTitle; } abstract class TimeRange { Time start; Time end; } abstract class WeeklyAgendaList { FullWeekName name; Collection<DailyItemList> items; } abstract class DailyItemList { DayName name; DateNumber date; Collection<DailyItemDescription> items; } abstract class MonthlyAgenda { FullMonthName name; DayName firstDay; NumberOfDaysPerMonth numberOfDays; Collection<DailyItemDescription> items; } abstract class DailyItemDescription { String value; // to be refined } abstract class FullMonthName { MonthName month; YearNumber year; } class NumberOfDaysPerMonth { int value; // Must be between 28 and 31, inclusive } abstract class YearlyCalendar { YearNumber year; Collection<SmallMonthView> months; } abstract class SmallMonthView { /* ... */ } /** * A YearNumber is a positive integer between 0 and 9999. It's defined as a * separate class in case we want to enforce the value range restriction within * the class constructor. */ abstract class YearNumber { int value; } /* * Model operations to place in the appropriate class: * DailyAgenda viewDay(Calendar); WeeklyAgendaTable viewWeekTable(Calendar); WeeklyAgendaList viewWeekList(Calendar); MonthlyAgenda viewMonth(Calendar); YearlyCalendar viewYear(Calendar); * */
String timeSlotName; Collection<briefItemDescriptor> items; Collection<briefItemDescriptor> overlaps;
/**** * * Class CalendarTool defines the top-level tool object that contains the * currently active calendar db, system state information, and an abstract file * space. * */ class CalendarTool { CalendarDB calendarDB; FileSpace fileSpace; SystemState systemState; } class CalendarDB { /* ... */ } class FileSpace { /* ... */ } class SystemState { /* ... */ }
This is the only import you'll need at the current abstract level of modeling.import java.util.Collection
class Whatever { /* ... */ }
Figure 3: Two views of testing in the software process.