The implementation of the class projects is organized around a series of sprints. Each sprint is approximately one month in duration, which is longer than recommended by many agile processes but much more appropriate given the (relatively) limited time available for a class project. The sprints are designed to provide experience with agile practices, and as such have the following deliverables:

  • Specification
  • Implementation (e.g., source code)
  • Retrospective

    • Issues encountered
    • Proposed (process) changes for the next sprint

Each deliverable is described in more detail in the following sections.

Specification

For this project, your requirements are not intended as a contract – i.e., if you implement all the stipulated functionality, then you will receive a good grade. On the contrary, that particular assignment is intended to make you think about the system as a whole and allow you to focus your work on a (potentially) small subset of the system’s overall functionality. A specification, on the other hand, formally defines what you expect to complete in each sprint. That is, the specification is an efficient way to communicate your work with others and ensure that you have consensus on the design before implementation begins in earnest.

[…] on any non-trivial project (more than about 1 week of coding or more than one programmer), if you don’t have a spec, you will always spend more time and create lower quality code. ~ Joel Spolsky

Specifications generally cover the following information:

Overview
At a high level, what are you trying to do? Why is it important?
Problem
Describe the problem in greater detail. What are the functional and non-functional requirements of the solution? It is often very helpful to include a use case that describes the issue from a user’s perspective.
Design
What specifically do you intend to do? Here is where you include technical details: someone else who reads your specification and is familiar with the system ought to be able to implement the design without any additional information. It’s also helpful to identify alternatives for consideration, both to show that you’ve thought about them and in case your initial plan doesn’t pan out as you intend.
Work Items
Who is responsible for the work? What is the breakdown of tasks?
Testing
How do you intend to show that you’ve addressed the problem?
Documentation
What updates must be made to the system’s documentation so that others benefit from the work? Source code comments are generally expected, but user-facing functionality requires documentation in other formats for the new capabilities to be useful.

Each team is responsible for collaborating on a single specification. It is recommended that you complete your specification early in the sprint so that you have time to solicit feedback and allow time to (possibly) change its design and implementation.

The specification template is derived from those used by OpenStack. As an open source project, the quality of the specifications varies, but those of the compute service are generally well-written. If struggling to understand what amount of detail to include in the specification, one approach is to review a half-dozen or so OpenStack specifications to get a feel for what is required to manage a large open source project. (Hint: More information is generally better, and although exhaustive detail is neither required nor appropriate, always trend toward including more information whenever in doubt.) A more entertaining resources is Joel Spolsky’s series “Painless Functional Specifications,” which addresses this topic humorously and pragmatically.

Implementation

Project artifacts will reside in a Git repository, which provides permanent record of all changes. The basic workflow is

  1. fork the project repository,
  2. clone your fork,
  3. make changes, and
  4. create a pull request for those changes.

If you aren’t comfortable with Git, then Pro Git is an excellent resource that not only walks through its basic use but also goes into considerable depth on its internals.

When committing anything to the repository, remember that each “logical change” should appear in its own commit. A logical change may be a complete specification, the cleanup of existing source code (e.g., reformatting it to follow an agreed-upon coding standard), or the addition of a feature. In general, the following should be avoided:

Mixing functional and non-functional changes
Create separate commits for the non-functional change (e.g., code cleanup) and the functional change; starting with the former ought to simplify the latter.
Mixing two unrelated functional changes
Break the changes apart into separate commits.
Having a giant commit for a feature
Start with the minimum functionality that provides business value (i.e., value to the end user) and add capabilities incrementally.
Mingling auto-generated with hand-written code
Often a gotcha when using web frameworks, clearly delineate the project initialization (e.g., the scaffolding provided by the framework) from its project-specific modifications to aid with review.

Typically this means that each commit has fewer than 200 lines of changes. Why is this important? Larger commits are more difficult to review, increasing the likelihood of mistakes. In addition, knowing the context for the change (e.g., who changed the line and why it was modified) is often critical to maintain the system’s functionality during later refactoring.

All changes (specifications, source code, documentation, etc.) must be reviewed prior to acceptance. Reviews ensure that others understand and agree with the proposed changes – another set of eyes often finds mistakes that the original author(s) missed!

Retrospective

During the last week of each sprint, your team should hold a retrospective to discuss the good, the bad, and the ugly. The retrospective is an opportunity for reflection. Think about the issues that your team encountered during the development cycle, consider their cause(s), and discuss possible resolutions. The retrospective is not the place for finger-pointing; rather, it is an invitation to explore how to improve the process so that the team is more successful the next iteration. (If individuals aren’t contributing equally to the project, the cause may be related to the rest of the team or the process, and soliciting their perspective is critical; otherwise, it’s appropriate to schedule a meeting with the instructor to address this issue.) Also be sure to celebrate the team’s achievements and what went well. There may even be additional opportunities for improvement in these areas.

You’ll probably benefit from appointing a scribe to take notes during the retrospective. Organize these notes into short synopsis (1/2 – 1 page) of the sprint as a whole and what would make the team more effective in the future.

Resources

Scott Chacon and Ben Straub, Pro Git, Apress, 2nd ed., 2014

Mike Cohn, “A Simple Way to Run a Sprint Retrospective,” Mountain Goat Software (blog), 26 January 2016

Joel Spolsky, “Painless Functional Specifications,” Joel on Software (blog), October 2000

OpenStack, “Git Commit Good Practice,” OpenStack wiki, accessed 27 September 2018