From Story to Code#
Objectives#
Collaboratively develop a plan for writing code to address specific user stories
Work together to implement this code, using the tools we’ve learned so far
Refactor the code using functions
Document the code for yourself and others
I. User Stories#
We can think about code as telling a story. A story about the intentions of those who wrote the code:
what they imagined users would do with their code,
and for what purpose,
and who they imagined those users would be.
In software development, we often make this way of thinking explicit by developing user stories.
Put simply, a user story expresses the who, what, and why in a succinct but concrete way. Written at the outset of a project, user stories provide developers both with guidance as they plan the project, and with benchmarks for measuring the project’s success.
As an example, here are a couple of user stories we could have written about the materials for Python Camp:
As a beginning learner of Python (who), I want to write code in the context of explanations and examples (what), so that I can refer back to the material for review (why).
As an instructor of Python Camp (who), I want to give learners self-paced exercises (what), so that I can focus on where individual learners get stuck (why).
Ideally, developers create user stories with input from the people who will actually use their software. But even when that’s not possible, user stories can offer a helpful framework for development.
In other cases, the only user of your code might be you! But it’s still good practice to document your intentions, and writing user stories can help you identify specific aspects or features of the code (developers call these requirements) that you need to target in order to meet your needs.
Try it out!
With you team, develop at least one user story about our bookstore dataset. The users in your story can be whoever you like, but it should be something that can be addressed using the dataset we worked with on Days 1, 2 and 3.
Don’t worry about details of implementation at this point: just focus on the who, what, and why, following the template:
As a ___________, I want to _____________________, so that ____________________.
II. Coding Your Story#
II.1 Planning#
Your team’s task now is to select a user story and implement it in Python code.
Choose your own adventure
Choose a user story that your team wrote, or one that was written by another team.
Alternately, pick one of the following user stories to implement. The prompts below are arranged in order of increasing difficulty. If up to this point, your team has worked mainly with the smaller, team-based dataset, you might want to start with the first of these user stories, which will get you working with the more complex bookstore dataset but in a more manageable way.
If you worked through yesterday’s challenges on the bookstore dataset and feel fairly comfortable with it, feel free to pick one of the more advanced prompts, or to work on your own user story.
Prompts
As a librarian, I would like to have a dataset of textbooks arranged by publisher, so that I can look up a publisher by name and see a list of their textbooks in use at GW.
As a student, I want to see summary statistics about textbook cost by department, so that I can know what to expect from various possible majors: e.g, average textbook cost, most expensive textbook, least expensive textbook, etc.
As a bookstore manager, my inventory would be a lot easier to work with if I had it in a spreadsheet. I want to have a CSV file of the bookstore dataset, so that I can open it in Excel or Sheets and filter by elements like department code, course number, textbook publisher, etc.
As a writer for the GW Hatchet, I am writing a story about textbook affordability, and I’d like to know how many textbooks for the Fall 2023 semester have been placed on course reserve with the GW Libraries. I have obtained a dataset of course reserves from the Libraries, which includes the ISBNs of books on reserve.
Once your team has agreed upon a user story, work together to develop a plan for implementation. The questions below can help you get started.
Questions
Is there more than one way to interpret this user story? If so, the team should document the different interpretations but then choose one to work with.
What tools and techniques can we apply to this problem? (Think about the Python data and control structures you’ve encountered so far: lists, dictionaries, for loops, functions, and conditionals.)
What challenges might arise during implementation? Since this user story concerns our bookstore dataset, are there aspects of that dataset that might pose problems?
What would a minimal implementation look like that would satisfy this user story?
For example, if my user story is about students’ looking up courses to identify required texts, I might start thinking about a website with a search feature, a browse feature, etc. But a minimal implementation might be a Python dictionary. Why? Because a Python dictionary is a data structure that can associate data with certain keys (like course identifiers).
Once you’ve settled on a minimal implementation, how are you going to get there? Try to describe the sequence of steps your implementation will take, and flag any steps that you have questions about.
II.2 Implementation#
Now it’s time to implement your code! As a reminder, in working together on the implementation with your team, make sure that everyone in the team has the opportunity to write code. At this stage, developing the muscle memory associated with writing Python syntax and patterns is crucial to learning.
The following hints and code snippets may be helpful, depending on which user story you’ve chosen to implement.
# As usual, we need to load the bookstore dataset as JSON before we can work with it
from urllib.request import urlretrieve
import json
urlretrieve('https://go.gwu.edu/pythoncampdata', 'bookstore-data.json')
with open('bookstore-data.json') as f:
bkst_data = json.load(f)
Try it out!
Write code below to implement your solution to your team’s user story. The Python Camp facilitators are happy to help if you get stuck!
# Your code here
# Add as many code cells below as you need
Hint
Reading and writing CSV files
Python includes a special module for working with CSV files. Like the json
module that we’ve used up to now, we need to import the CSV module before we can use it.
import csv
Reading from CSV
To read from a CSV file on the web (which will normally have the .csv
extension), we save a copy locally first, open the file, and then read in the data line by line. The code below, which stores the contents of a CSV file of course-reserves data in a variable called reserves
, is a little more complex than the code for reading a JSON file, primarily because we have to read from the file in a loop.
urlretrieve('https://raw.githubusercontent.com/gwu-libraries/python-camp/gh-pages/data/reserves-data-fall-2023.csv', 'reserves-data.csv')
reserves = []
with open('reserves-data.csv') as f:
reader = csv.DictReader(f)
for row in reader:
reserves.append(row)
The csv.DictReader
object will create a Python dictionary from every row in the CSV file, where the dictionary keys are the column headings, and the values are the data in that row. (This assumes that the first row of the CSV file contains column headings, which may not always be the case.)
Writing (saving) to CSV
To save data in CSV format, we perform a similar process. When using csv.DictWriter
, as below, our dataset needs to consist of a list of dictionaries, where every dictionary has the same keys. A list of this keys constitutes the fieldnames
argument of the writeheader()
method, which we call to create the header row.
In the example below, we save a Python list called bkst_data_csv
to a CSV file called bookstore-data.csv
.
with open('bookstore-data.csv', 'w') as f:
fieldnames = bkst_data_csv[0].keys()
writer = DictWriter(f, fieldnames)
writer.writeheader()
for row in bkst_data_csv:
writer.writerow(row)
Hint
Comparing lists
Two lists in Python, even if they contain nested elements, are considered equal only if they are exact duplicates of one another. As a minimal example, the following code produces the result False
because l1
and l2
have the same elements but in different order.
l1 = [1, 2, 3]
l2 = [3, 1, 2]
l1 == l2 # This is False
Often when comparing lists, what we want to know is not, “Are these lists equal according to Python?” but rather, “Do these lists have the same elements?” or “Which elements are present in both lists?”
Below is an example of a function that answers the second question:
def find_overlap(l1, l2):
overlap = []
for item in l1:
if item in l2:
overlap.append(item)
return overlap
We could use this function like so:
l1 = [1, 2, 3, 4]
l2 = [2, 4, 6, 8]
# This will print the list [2, 4]
print(find_overlap(l1, l2))
Note that this approach works best when the two lists contain numeric values or strings as their top-level elements.
In fact, when that’s the case, we can take an even more expeditious approach, using a Python data type we haven’t seen so far: the set.
Let’s say we have two lists of ISBN’s. Both are lists of strings. The following code finds the overlap between those two lists, returning a set of unique elements that are in both lists.
unique_isbns = set(isbn1) & set(isbn2)
Read more about Python sets in the documentation