A pleasant walk through computing

Comment for me? Send an email. I might even update the post!

Git commit/checkout is a snapshot, not a delta

For many of us with past source control experience (Subversion, Team Foundation Version Control, Visual Source Safe), there's a subtlety to a Git commit that can trip us up when it comes to build/deployment pipelines. We mistakenly think the pipeline will "get latest."

A Git commit is a snapshot of the entire source tree of the developer's workspace. It's not a record of only that commit's changes. This is why it's critical, before submitting a branch pull request or a commit to mainline (depending on your workflow) that you pull the remote repository's latest code into your local repository.

Imagine two developers, Jasmine and Sabrina. They're going to work on a repo with two files.

|_princess.txt
|_witch.txt

At 1pm, they both clone the remote, so both their local repositories exactly match. I'm showing the SHA hashes below.

HEAD aaaa111  <== this is the commit number
|_princess.txt  bbbb111
|_witch.txt     cccc111

Let's be really clear. Git doesn't know about the files. It knows about the hashes it uses to name its copies of the files. So Git's commit tree is:

aaaa111
|_bbbb111
|_cccc111

They each create a separate branch. At 1:30pm, Jasmine changes her file, commits, and creates a pull request. Her commit tree is:

HEAD aaaa222
|_princess.txt  bbbb222
|_witch.txt     cccc111

When the PR is approved and commit aaaa222 is deployed, those files are deployed.

At 2:00pm, Sabrina changes her file, commits, and creates a PR. Her commit tree is:

HEAD aaaa333
|_princess.txt  bbbb111
|_witch.txt     cccc222

This is the important part: Sabrina didn't pull from the remote, so her commit tree doesn't include Jasmine's changes.

When the PR is approved and commit aaaa333 is deployed, Git does not get the latest princess.txt nor should it. Git checks out the named commit tree, and that commit has the earlier princess.txt.

What Sabrina needed to do before the PR is:

git checkout main
git pull --rebase
git checkout myfeature
git rebase main
git push
# OR git push --force <== if the branch was previously pushed

If she does this, her commit tree for the PR will be:

HEAD aaaa444
|_princess.txt  bbbb222
|_witch.txt     cccc222

Now the PR will deploy the latest files because that's what's in commit aaaa444.

What do you mean by automated tests and continuous integration?

I had a client ask me this posts's title question recently. It's a good one. In this case, the person asking develops internal Python software, but that's not his primary job so he wasn't familiar with the deep world of enterprise-level development.

How do we explain this to a newcomer? Here's my answer, rooted in Azure DevOps. Perfect? No. Useful? I hope so!

Automated Testing

Any tests that don't require human interaction. These include:

  • Unit tests (testing discrete code elements such as a single function)
  • Integration tests (testing that modules all communicate with each other, external sites, back-end databases, etc)

Automated testing is essential, not optional. When practiced well, developers routinely have more test code than app code. Unit testing improves architecture by encouraging loose coupling. It also dramatically improves confidence when making changes.

Continuous Integration and Continuous Deployment

Typically, when there's team development, the "main" version of the source code is kept on a remote server. In our case, that's the Azure DevOps Git repositories.

That main branch is what's been deployed to production users, and must always be working. So, how do we ensure that our changes don't break the main branch? That is, how do we safely integrate our code to what's already there?

The two parts to the answer are branching and building.

  1. Develop new features in a short-lived branch (short-lived branches exist no more than a day or two)
  2. Pull the main branch code to your local workspace
  3. Rebase your feature code onto the main, so it's as if you just made your changes. You've integrated locally.
  4. Rebuild the application locally and run all tests.
  5. Push your feature branch to the remote Git server and create a pull request, saying "Hey, I want this branch merged into main!"
  6. Someone approves the PR, integrating into main.
  7. The main branch automatically builds and tests the code from scratch. This is key. It's as if a new developer is working on a new computer. We build/test the code once, then deploy it to different environments. What could go wrong?
    1. The code doesn't build.
    2. The tests fail
  8. If anything goes wrong, we're notified and the bad code doesn't get released to users.

It can be counter-intuitive, but the safest development method is to push changes frequently. Why?

  • Fewer changes are easier to fix
  • Rolling back a PR with only a few changes isn't a big deal
  • Integrating multiple times per day means the latest changes are working

When there is high automated test coverage and frequent integration, there can be enough confidence in the system to enable continuous deployment. That's where the code is automatically released to users as long as all environments build and test successfully. If there's a problem in a release deployment, it's easy to either roll that back or, better, rapidly fix the issue since there will have been a small number of changes.

A Simple Intro to Scrum in Azure DevOps

Azure DevOps is a flexible--yet opinionated--application to use for Scrum. It's got a large number of settings, and sometimes how things are named is confusing. This is a "get up and running" guide that includes the basics of the Scrum framework and a daily flow for your team.

What's included:

  • Scrum basics
  • A "Day in the Life" of your dev team
  • My recommended configurations of the default Scrum Process Template

What's not:

  • Getting an Azure DevOps free account (I assume you've done this)
  • Security
  • Deep reporting
  • My preferred really simple process template. That's a future post.

Contents

Scrum Basics

Scrum is not a methodology. It's an Agile framework that methodologies are based on. Scrum mostly describes what you should have but not how you should do it.1 This will come as a surprise to most readers, since "Scrum means boards and points and velocity and charts" is what the consultants sell. The truth is, those are applications of Scrum that have proven successful over the years, and I'll be including some of them below.

Important
Scrum is Agile, but Agile isn't Scrum. Agile is a set of four values and twelve principles2 established by a bunch of software developers in 2001. If a framework or methdology supports those values and principles, it's Agile. Other such methodologies incude Kanban, Lean, eXtreme Programming, and Crystal.

The core flow of Scrum is:

  1. Capture all potential work in an ordered3 Product Backlog.
  2. Define regular iteration periods of work called Sprints.
  3. Define a valuable Sprint Goal and pull work into a Sprint Backlog that will meet that goal.
  4. Complete the items in the Sprint Backlog during the Sprint, meeting daily for fifteen minutes to review progress.
  5. Review the Sprint results with stakeholders.
  6. Reflect inside the team on how the process can be improved, and add those improvements to the Product Backlog.
  7. Repeat, maintaining a sustainable pace

A Sprint is a contract to complete the Sprint Goal. The team commits to achieving the goal, and the customer commits to not adding work during the Sprint that inhibits the goal.

A Scrum team has three roles:

  • Product Owner, who represents the customer's interests and is responsible for which work will get done next.
  • Developers, who decide how the work will get done.
  • Scrum Master, who guides the team to successfully use Scrum.

There is no Project Manager in a Scrum team. The team works together as peers using their skills to best effect.

Tight Feedback Loops
Scrum--and Agile in general--prefers rapid, regular feedback to allow early self-correction.

Configure a New Project

Open your Azure DevOps site and select your organization (which should already be configured).

Create

  1. Choose + New Project.
  2. Enter a Project name, Visibility = Private, and open the Advanced settings.
    1. Version control = Git
    2. Work item process = Scrum.

    The differences between the "Agile" and "Scrum" processes is primarily terminology.4 A Scrum Product Backlog Item (PBI) is an Agile User Story. A Scrum Impediment is an Agile Issue.

  3. Click Create.

Our project has one team. Configuring multiple teams is outside this guide's scope. A large enough project could have many teams, each with its own iterations and board configurations.

Configure Iterations

  1. Open Project Settings (the gear icon at bottom of the left sidebar menu).
  2. Select Boards > Project configuration.
  3. Delete all of the sample iterations (named "Sprint 1" etc) leaving just the top-level iteration.
  4. Add one New Child named "Product Backlog" with no dates. Select this item.

Configure the Team

  1. Open Project Settings (the gear icon at bottom of the left sidebar menu).
  2. Select Boards > Team configuration.
  3. In the General tab
    • Check Epics, Features, and Backlog items.
    • Select "Bugs are managed with requirements"
  4. In the Iterations tab.
    • Set Default iteration to "Product Backlog".
    • Set Backlog Iteration to "Product Backlog".
    • (We'll create sprints in a later step.)

Opinion
Why not use @Current as the Default iteration? Because whenever a work item is added, it will automatically become part of the current sprint. This promotes a poor practice: not honoring the Sprint contract. Also, it's way too easy to forget to change the work item to be part of the backlog.

This guide doesn't show customizing work item types, which can be very useful. My advice: do as little customization as needed, and almost none at first. Don't assume you need it.

What is "Manage Bugs With Requirements"?

Setting Effect
Manage with requirements Bugs are the same level as PBIs, appear as cards on the Story Board, can have tasks.
Manage with tasks Bugs are added to BPIs just like Tasks, and cannot have Tasks themselves.

It may seem counter-intuitive, but I recommend managing bugs with requirements, which is the Scrum process default anyway. With this configuration, it's easier to define bugs as post-release issues and report on their impact.

Day in the Life - Capture Epics, Features, and Stories

We need to capture the work we think we're going to do. The only requirement for Scrum is a Product Backlog which can contain any kind of work item. It's often convenient to group work into features and epics.

  • Epic A high-level objective such as "Implement broad accessibility." Usually a longer duration like a year.
  • Feature An objective that will take multiple Sprints. For example, "Make site blind-accessible."
  • Product Backlog Item (Story) The work items to achieve in Sprints. PBI's can be part of a Feature, or independent. These typically take a few hours to a few days.

I call PBIs "stories" out of habit. I think it's easier to capture work in terms of stories.

Important
Epics and Features are things you finish, not areas of effort. Epics appeal to executives as high-level objectives.

  1. Open Boards > Backlogs

  2. Open View Options and set

    • Forecasting On
    • In Progress Items On
    • Completed Child Items Off
    • Side Pane = Planning
  3. Add three, two-week sprints. I like ISO naming because it's clear and cross-cultural. Be sure to choose the correct Location ("Product Backlog").

  4. Select Epics from the "Backlog items" dropdown

  5. Add a New Work Item of type Epic named "Implement broad accessibility".

  6. Click the + sign at the left of the epic and Add Feature "Make site blind-accessible"

  7. Switch to Backlog items view.

  8. Add some stories, both independent and for the feature. We'll link to the feature in a little bit. Notice how you can add either a PBI or a Bug. If "Manage Bugs with tasks" had been selected earlier, you could only add PBIs here.

Opinion
The default for adding new work items is "Add to Top". Change that to Add to Bottom. As you'll see, the Product Owner prioritizes work to the top. Don't step on her effort.

  1. Open View Options and change the right side panel to "Mapping". You should see the feature.
  2. Select, drag, and drop the first four stories onto the feature to link them.

Day in the Life - Plan the Sprint

Sprint Planning is one of the Scrum events. Normally, prior to this, the Product Owner has prioritized the backlog so that the highest value (to the customer) stories are at the top.

Sprint Planning is done by the team.

  • Work item Effort is estimated.
  • The work itself is discussed in more detail and captured in the work item.
  • A Sprint Goal is agreed to, and work is assigned to the Sprint.
  1. Open View Options and change the right side panel to "Planning" so show the sprints.

  2. Reorder the work items, give each an Effort, and change its State to "Approved".

  3. We've enabled Forecasting. Set the Forecasting velocity to 20 as our best guess for what we can get done this first sprint. This shows how many stories can go in the Sprint.

  4. Select, drag, and drop the top four stories onto the current Sprint.

  5. With the top four still selected, right-click and choose Edit. Select the State field and set to Committed.

Since this walkthrough sticks to the defaults as much as possible, I'm using the intended Scrum flow which is "Items ready to estimate are Approved. Items in the Sprint are Committed."

I personally modify the process and use these states: New, In Progess, Done. This allows a work item to remain New in the Sprint Backlog. When it's dragged to another column, it's now In Progress.

Advice
DO NOT plan future Sprints. That's Waterfall thinking.
DO estimate effort for all stories. This helps the Product Owner.

What about assignments?
The common recommendation is to not assign stories. Instead, let developers pull from the top as they are ready to begin work. The idea is anyone on the team can work on any story.

My experience is that the team knows who's best suited to work on stories and will often assign stories during Sprint Planning.

However, I don't recommend assigning stories before they make it to a sprint. Don't try to predict the future, and don't pigeonhole developers.

Time Out! What Makes a Good User Story? And What is Effort?

Work Item Descriptions (Stories)

There are plenty of opinions about what makes good work item descriptions. In my view, work item descriptions come in three basic types

  • User Stories, which are user-centric items
  • Bugs, which are for post-release defect reporting
  • "Whatever" stories which are often internal/development items

In all cases, the most important thing is to capture early, and enough information to ensure you can discuss the work item later. Stories are the beginning of the conversation, not the end.

User Stories
I like the now-classic template "As a ROLE, I want WHAT, because WHY". For example:

As a Security Admin, I need to be able to assign read-only to some screens because only accounting should be able to change the values, but everyone can see them.

The "why" is important because it tells us the value of the story. Work with the end-users to create these stories. The further you are from the actual end user, the more you're playing the game of Telephone5--and ensuring you're not getting accurate info.

The other quality of a good story is the acceptance criteria. That is, how will the user know the story is complete.

Important
You should expect the user story, and especially the acceptance criteria, to change as the story is developed. The conversation continues until the story is completed. These are not specifications!

Bugs
The two most important parts of a good bug report are:

  • Who reported it.
  • Clear, accurate steps to reproduce the issue.
  • Expected vs Actual result.

The person who reported the issue should be the person who confirms during development (or after deployment) the bug is fixed.

Steps to reproduce require coaching. Very few people do this well at first because we tend to assume the reader knows the software as well as we do. That's never true. Instead, assume you're training a new hire.

  1. Don't use slang or insider terms
  2. Write down the same terms/menu items, etc on the screen
  3. Provide the exact values used

Whatever Stories
These are often things like "Prepare stakeholder presentation" or "Review database indexes for performance." I try to keep these to a minimum.

The bulk of your work items should be stories because that means you're satisfying the customer's needs.

Effort

How hard will the story be to achieve? "Relative to what?" you ask me. The answer is, "relative to the other stories." A team gains a sense of how hard their work is in the context of their skills. The purpose of estimating effort--which typically occurs before prioritizing work items--is to help the developers decide how much work they can complete in the sprint, and help the Product Owner with determining story value.

Effort is traditionally measured in something other than hours. Azure DevOps uses Fibonacci story points. I have a couple of opinions and recommendations about this.

  1. Don't go beyond 13. There's really no value in going up to 100 like some overly-formal systems suggest. You're just after a numerical sense of "easy, not bad, pretty hard, too hard for one sprint." Keep it simple!
  2. Think in terms of "can I get this done in the sprint?" Most of your stories should finish in a day or less.

The developers agrees on effort for each story during Sprint Planning. This provokes necessary conversation.

Points What it might mean
1 Pretty easy, less than a day
2 Easy, probably a day
3 Might run into trouble, a few days
5 Tough, maybe depends on other people or complicated problem
8 Hard, might need further breaking down
13 Too much! Should become multiple stories

Configuring the Story Board

An unfiltered Story Board shows the flow of stories through four overall states:

  1. New (not estimated or approved)
  2. Approved (estimated and ready for a sprint)
  3. Committed (in the current sprint)
  4. Done

Option
You could just use the Story Board to manage all work items. In this way, it's exactly like a physical board with sticky notes. However, you may have too many backlog items to make this enjoyable.

A Story Board filtered for a Sprint has just two states:

  1. Committed
  2. Done

The default columns for a team (using the Scrum template) are: New, Approved, Committed, Done. You can use these if you want, but you'll probably want to modify it.

The first thing about the board columns is: the board reflects your flow. So make sure it's telling you the truth.

The second thing about board columns: Avoid creating a Waterfall board with "Planning, Design, Development, Testing, Release" etc. Your stories are better off when you don't force their states. It'll depend on the business whether there's a firm hand-off such as to a QA team member.

The third thing about boards is: They're a pull system. You work on the story. If there's a hand-off, you put the story into a "ready" column so the next person can pull when she's ready.

Let's configure our board to include a QA team member handoff.

  1. Open Boards
  2. Choose the Backlog Items view
  3. Open the Board Settings and Columns tab. When you add or rename columns, be sure to set their State.
  4. Configure the columns as shown.

Now we're ready for people to start work! Go ahead and drag a couple of stories from Ready for Dev to Developing, and assign them. (I previously added some Users.)

Time Out! There Sure Are a Lot of "States"

Yeah, it's confusing with all the layers of abstraction. Here's a chart to help you understand what the states are and what level they're configured at.

Important
Even if you customize a process, at story is only ever in one of three conceptual states: New, In Progress, Done.

Day in the Life - Daily Standup

The purpose of the daily standup meeting is to communicate progress. It's part of the rapid feedback loop. I like using Azure DevOps the following way in the meeting.

Your Custom Stuff

The Scrum Master shows whatever charts the team is using to help progress toward the Sprint Goal. The most useful, in my view, are:

  • Burndown Chart
  • Cumulative Flow Diagram

The Story Board

Next is the Story Board showing everyone's stories. This gives the best overview and is the first place to spot bottlenecks. As the Sprint progresses, stories move from left to right. (I've added some Tasks and a Test to make things a little more real.)

Tip
Don't assume you must use Tasks. If your project is simple enough, or the team is mature enough, viewing the stories' progress through the board is often enough.

Rule
Do the simplest thing that works.

You can filter the Story Board to show each person's work in progress. Note that this filters on who owns the story. This may be all you need for short-lived stories that don't have multiple people working on them.

The Task Board

If you do have multiple people assigned to stories' tasks, then the Task Board is valuable. Open "Sprints" from the left side menu.

This view shows the Committed (in progress) stories on the left hand side, and any tasks in progress. Just as with the Story Board, you can filter by person. Nicely, if the person is assigned a task belonging to another developer's story, she's still shown in context.

Day in the Life - The Review and Retrospective

There's no particular Azure DevOps screen I know of for recording reviews and retrospectives, except that whatever you want to improve should become stories on your Product Backlog.

Suggestion
Instead of "rolling" unfinished stories to the next Sprint, try setting them all back to the Product Backlog iteration, but without changing their states. In other words, a story that's Committed remains that way. This makes the forecasting easier and lets the team "reset" their thinking. Why assume a story that wasn't finished must be on the next Sprint. Maybe, under reexamination, it shouldn't. If it shouldn't, it can be set as New. That's OK. Don't get hung up on keeping track of how much work was already done. Scrum is supposed to help you ship.

But do them. Really.

Crucial
The Sprint Retrospective is the most important part of the process. Without it, it's hard to improve.

Resources and Footnotes


  1. Scrum Guide | Scrum Guides

  2. Manifesto for Agile Software Development

  3. Myth: In Scrum, the Product Backlog is prioritized | by Christiaan Verwijs | The Liberators | Medium

  4. Choose a process like Basic, Agile, Scrum, or CMMI - Azure Boards | Microsoft Docs

  5. Children sit in a circle. The first child whispers a longish sentence to the next child, who whispers to the third child, and so on. The last child compares what she heard to the original. Inevitibly there's significant drift. When I was a kid, it was called the game of Gossip.

   Older