Informatics 43 Spring 2009
Midterm Study Guide


Introduction

This study guide is a summary of the material covered in lecture thusfar. The Midterm will be focused on both lecture material and assigned readings, but the focus of this guide is the material that we covered in lecture.

The best advice for studying is to focus your attention as much on the "Why?" as the "What?" It's my goal to write an exam that does not depend solely on your ability to memorize terms, definitions, and facts; instead, I'm much more interested in whether you understand why things are the way they are, and in your ability to combine concepts we've learned about in novel ways that we've yet to consider in lecture.

I should point out that this study guide is not intended as a replacement for the lectures or your own notes. It's possible that something we discussed in class will have been left out of the study guide, but is still fair game for the exam. I'm not trying to cheat you on purpose, but the study guide is what it is: it's a guide.

Enjoy.


Background

This course is primarily about software engineering. That the term "software engineering" includes the word "engineering" immediately evokes a few ideas:

There are many similar definitions of software engineering; one of them is the following:

Software engineering is the application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software.

Some words stand out in that definition:

So when we move out of the realm of programming and into the realm of software engineering is when we scale the sizes of our projects up. It's about programming-in-the-large as opposed to programming-in-the-small. Programming-in-the-large includes some combination of: multiple people, multiple versions, multiple years, multiple related products.

Basic activities in software engineering include:


Process

Software is said to go through a lifecycle, in which various activities are done at various points in time. An idealized view of that lifecycle looks something like this:

Idealized Software Lifecycle

When embarking on a new software engineering project, we need to decide on a process. In general, a process is a strategy for organizing a project, which answers questions like this:

There is not broad agreement in real-world software development about what process should be used. Virtually anywhere you work will have a process that is at least slightly different than processes you'd use anywhere else. This is partly because software is a relatively young discipline, and partly because different processes work better or worse depending on the situation (e.g., How many people do we have? How much time do we have? How well do our customers understand what needs to be built?).

Processes generally fit into one of a couple of categories:

There is a spectrum of possible processes, with the most heavyweight on one end and the most lightweight on the other. We discussed the two extremes in lecture: the waterfall model and agile methods.

The Waterfall Model

The waterfall model is one well-known process model for engineering software. It breaks a project into phases, with each phase being one of the activities from the idealized view of the software lifecycle shown above.

Each phase has an output, which is some combination of documentation and code. The output of one phase becomes the input to the next phase. These outputs are depicted in the diagram above:

We can think of the design phase as, itself, being two separate sub-phases:

Once we've reached the maintenance and evolution phase, our focus is on keeping the system running and on finding new business problems that could be solved with modifications to the product. As we find new business problems, we can embark on a waterfall-style project in which we make these modifications.

Verification and validation

There are up to two additional tasks we need to perform in each step of the waterfall model: verification and validation (sometimes referred to as V&V). They sound similar, but they're not the same.

We don't do both verification and validation at every step. For example, we don't do verification during requirements engineering, since we haven't designed or implemented anything yet.

Testing and the V-model

Testing is incorporated throughout a waterfall process — as it should be throughout any process. Test plans are part of the output of each phase, describing testing that will need to be done subsequently.

One way to represent this relationship pictorially is often called the V-model, which depicts the waterfall model, along with related forms of testing that are planned early on and them performed later.

Assessment of the waterfall model

The waterfall model works beautifully in an ideal world where we always complete each phase correctly the first time. In reality, of course, we don't, so we need a way to backtrack to previous steps if necessary. The cost of that backtracking is higher the further back we have to go; for example, discovering an incorrect requirement during the testing phase requires us to revisit the requirements specification, the design documentation, and the program, along with the relevant test plans.

Not surprisingly, the waterfall model has significant downsides in practice.

Agile methods

The waterfall model represents one extreme along a spectrum of software development processes, one where planning is king and we don't act until we know exactly where we're going. The opposite extreme is a set of processes called agile methods. Agile methods arise from the basic idea that change is inevitable, because:

There are a number of variants of agile methods (e.g., Extreme Programming, Scrum), though they are generally all built according to the same set of principles. These principles are laid out in a document called the Manifesto for Agile Software Development (also known as the Agile Manifesto), the most important part of which reads as follows:

We are uncovering better ways of developing software by doing it and helping others do it. Through this work we have come to value: That is, while there is value in the items on the right, we value the items on the left more.

Agile methods have the following properties:

Extreme Programming

Extreme Programming (XP) is an example of an agile method. It is centered around a set of practices, some of which are:


Software Quality

We'd like to build quality software. But what is software quality? What should we be shooting for? Quality software...

Measuring quality empirically is a difficult proposition; despite much work in this area over the last few decades, there are not measurements that can automate the process of deciding whether you have achieved quality.

This doesn't mean that there aren't attributes that quality software tends to have. We should know how to recognize these attributes and use them as guidelines as we work.

Some of these factors trade off of others (e.g., sometimes efficiency harms maintainability, testability, and reusability).


Requirements Engineering

Requirements engineering is the process of analyzing a customer's problem, gaining an understanding of what a system could do to solve it, documenting that understanding, and checking the accuracy of that understanding. The product generated by requirements engineering is called a requirements specification; it details the current understanding of what the requirements for a system are.

First of all, we should decide what is meant by a requirement. A requirement is "a condition or capability needed by a user to solve a problem or achieve an objective." It's something that the system should be able to do, or a constraint that the system must meet. Requirements are not necessary "musts" in a system; many requirements are, in practice, negotiable.

The requirements engineering process is characterized at least partly by the need to address the concerns of many stakeholders. A stakeholder is anyone that is concerned with the system in some way:

Different stakeholders bring different kinds of requirements to the table. Those requirements can even conflict. For example, YouTube has a requirement that people be allowed to upload videos; ideally, they can upload any video they'd like. Copyright holders, however, view this requirement differently.

Requirements engineering is comprised of four tasks:

Requirements elicitation

A variety of techniques can be used to elicit requirements, including interviews, brainstorming, surveys/questionnaires, task analysis, ethnography, and prototyping. We choose these techniques based on who we need to interact with and what we need to know.

Requirements specification

A requirements specification is a document that describes the complete set of known requirements for a software engineering project. A good requirements specification has several attributes:

When writing a requirements specification, we want to focus on the "what" and not the "how." For example, we want to avoid implementation bias whenever possible. If we're building a web-based system, the underlying technology we choose (e.g., Java EE, PHP, .NET/ASP) is essentially irrelevant. Either way, a web site is a web site.

Kinds of requirements

We can categorize requirements in many ways. One way we did so in lecture was to separate them into functional and non-functional requirements.

Acceptance test plans

Part of the requirements engineering process is to draw up an acceptance test plan, which details how a system will be tested to ensure that it is acceptable to the customer. Various scenarios will be described — in relatively open-ended terms, since we want to avoid implementation bias — the successful completion of which indicates that the system is ready to be delivered.


Design

Once requirements are agreed upon, it's time to begin working on a design for your system. Design is a many-faceted task, whose complexity rises substantially with the complexity of the system being developed. There is no one "right way" to design software, but there are many well-understood lessons and "best practices," recurring problems for which well-known solution patterns are known, and qualities that we know that good designs generally have and that bad designs generally lack.

We can say that design comes in two flavors: architectural design, which focuses on the "big picture"; and module design, which focuses on details like classes, methods, and so on.

There are a number of goals we're trying to achieve during the design phase:

Moduality

Software is generally built by many people and generally has many versions over its lifetime; both of these facts pose issues that we'll need to solve. The solution to both is modularity; we should pefer to decompose our system into a collection of subsystems.

Good modules have at least three characteristics:

Qualities of a good design

It's hard to define precisely what a "good" design is, but we do know that there are some desirable qualities that good designs have.

UML

The Unified Modeling Language (UML) is a collection of kinds of diagrams that we can use to describe the design of a software system. Different diagrams address different parts of our design. We spent a fair amount of time talking about one of these diagrams: UML Class Diagrams. The discussion slides on this topic show the various notations used in UML Class Diagrams.

Use cases

Another way to view a design is in terms of problems that the system will need to solve and scenarios in which the system will be used to solve them. Use cases are a way of describing the behavior of a system from the points of view of a set of actors. Actors are entities external to the system (e.g., human users, other automated systems). Use cases are described as a sequence of events, in which an actor interacts with the system in some way.

Use cases are focused on goals: what is each actor trying to achieve and how can the system help them to achieve it? We define details like user interface only to the extent that we can describe a scenario; the use cases will eventually be used when we consider a more detailed view of our design (e.g., user interface design, module design).

There are many arrangements of use cases. One such arrangement has use cases broken up into the following sections.

An example use case, which we wrote in lecture, follows.

Architectural styles

As we start to attack larger-scale problems, it becomes more difficult to discover a methodology for arranging our modules and their interactions. Luckily, there are kinds of problems that recur, for which good architectural solutions have been designed and have proven useful. These solutions are called architectural styles. Architectural styles represent "success stories" from the work of previous designers; to understand and use them, when appropriate, is to avoid going through the process of trial-and-error that those previous designers endured in order to find their design.

Some well-known architectural styles:

It is not necessarily the case that there is one architectural style for a whole project. We often combine them together.