Notes from lecture 1 – Goals and skills
1 What this course is about
The goal of the course is to lift your software development skills from working with small programs (think CS 111) to designing and building software systems.
Supports configuration for adapting to the requirements of its environment;
Maintains a stable operational phase even under adversarial load, and supports graceful termination even under irregular conditions.
Consist of well-defined parts representing different elements of the game (like the board, players, and so on);
Create the overall game by linking together those parts;
Let its users configure whether players use a GUI or a textual interface, or whether the rules checker will use this or that version of the rules;
Maintain an operational mode where users can register, initiate and play games etc even when some users attempt to cheat or connections drop, and terminate without damaging the host environment or the users’ environment (those are not always the same ...) both when termination is intentional and when unexpected.
The above example illustrates that building a software system involves dealing with dimensions of design complexity that go well beyond those you encountered when writing small programs. To make matters worse, decisions that developers make as early as when the system is still a prototype (such as the programming language) can stick around for a very long time. See for instance all the legacy COBOL code in bank software systems. It is still there under layers of wrappers of C++, Java, and JavaScript.
So how can you cope with this great complexity? You need to develop a set of skills that will help you take good care of your code as it grows from a prototype to a full fledged system.
2 The skills this course aims to develop
Software construction focuses on three kinds of skills: technical, process, and personal skills.
Modular development;
Design of interfaces and protocols;
Integration of (heterogeneous) components in a system;
(continuous) Testing with systematically constructed test harnesses.
What is the goal of our system?
What are the pieces that are involved in our system and how do they relate to other things (internal and external to the system)?
What are the use cases of the system?
- Focusing on one use case (the most important):
How can it be decomposed into parts?
What are the requirements for those parts?
How can we represent those parts as components and what is their interface?
Can we implement these components?
Can we gain confidence that each component in separation is correct (e.g. unit testing)?
Can we integrate the components in an operational prototype?
Can we gain confidence that the integration is correct(e.g. integration testing)?
What is the next use case we should analyze?
Our goal is to implement a system that allows to automate the sales, inventory and accounting operations of the store;
The pieces include: customers(external), sales persons (external), inventory employees (external), accountants (external), registry (internal), printer (internal), inventory (internal), bank (external)
Some uses cases are: a customer wants to buy some products, inventory employees want to make orders to restock a store, the accountants want to balance the books and pay bills;
We will focus first on the purchase-of-products use case: the customer brings products to the registry, the sales person rings them in, the customer swipes credit card, the registry contacts (i) the bank to get acknowledgment for available funds and charge the customer’s account; (ii) the printer to output the receipt and (ii) the inventory to alert it that the purchased products have been removed from the shelves of the store;
One component involved is a shopping cart (imagine it runs some software) component that collects the information of all the products that customers bring to the registry and offers an interface to add a product, remove a product, ask for total value of its contents, and pay for the products it holds;
We implement and unit test the shopping cart and each other component;
We connect the components and test their connections;
We move to the next use case.
Personal skills are necessary for a software developer as software development is only partly a technical discipline. A big part of software development is communicating with other people. First, developers have to communicate with each other since they work mostly in teams and often inherit code or use components that others have built. Second, they have to communicate with their managers to explain to them what they have built, to requirement engineers to understand what the clients need, and to QA engineers to understand issues with their code. Put differently, a software developer needs to be able to (i) effectively explain their code both at a high-level and with all the nitty-gritty detail; (ii) provide constructive feedback to others code on the fly for a problem they understand well; and (iii) be open to critique from others.
This last part is particularly important as a developers ego easily becomes an obstacle to delivering successful artifacts. Programmers should disassociate themselves from their code and examine it and let others examine it as if it was a newly found artifact from the depths of history.
Members of a team of two who will practice pair programming and learn to communicate (and cope) with a partner on a daily basis;
Codewalkers who will explain their code and especially its bugs, issues and imperfections to your peers and be open to accept continuous constructive criticism;
Audience members who will have to understand and provide constructive feedback to code they see for the first time;
Panelists who will direct the discussion during each codewalk and compile a succinct memo with feedback for the codewalkers.
As a final note, developers need to be able to spot and resolve ambiguity.
Clients often leave out crucial details about what they want —
3 The structure of this class
In this class we will build a system for playing a board game. You will build it in parts corresponding to the assignments, which will be due roughly every week. Each assignment will go roughly like this: First you design and think the part of the system you need to build, and you will create tests that capture the essential requirements of the part of the system you are designing. Then you will execute your design, and you will get real-time, continuous feedback about your implementation by testing it against the collection of the whole class’s tests.
For most of the quarter, we will use the class time to review each others’ code. The next few classes will be lectures on technical topics, and then the rest of the classes will be codewalks in which one team presents their implementation of the last week’s assignment to the class. It will be the job of everyone else to think about the code, ask questions to understand it, identify possible problems, and suggest improvements. A group of panelists will moderate the code walk and discussion, making sure it stays on topic, constructive, and compiling the feedback for the presenting team.