
I tried learning about project management
This page has been translated by machine translation. View original
Project management and product management have different centers of gravity. The difference lies in whether you are strongly responsible for predictably delivering defined outputs within certain constraints, or whether you continuously track what outcomes have been generated for customers and the business through those outputs.
Of course, this doesn't mean projects don't need outcomes, or that products don't need outputs. The difference between the two lies in which one is more strongly managed.
This time, I've summarized what I learned and incorporated into practice regarding project management. I'll write not only about what went well, but also about what broke when I tried things.
Project Management
I have concluded that project management is the activity of facing uncertainty and anxiety while bringing required outputs closer to a predictable state within limited time, budget, and personnel.
To do this, it's necessary to "handle uncertainty itself" and "handle the anxiety in people that is created by uncertainty."
Breaking Down Uncertainty
Uncertainty cannot be handled as-is. Being in a state of "somehow feeling like things won't go well" doesn't lead to concrete actions. Therefore, uncertainty is broken down into the following perspectives.
- Risk: There is a possibility that an undesirable event will occur in the future
- Hypothesis: It's unclear whether what is assumed as a premise is correct
- Decision: It hasn't been decided which option to choose among multiple alternatives
For example, the uncertainty of "I don't know if Feature A can be released as planned" can be broken down like this.
- Risk: "The external API might not be provided as planned"
- Hypothesis: "This design should deliver sufficient performance"
- Decision: "Should we prioritize performance or the deadline?"
Even with the same "unknown," different types lead to different subsequent actions. The purpose of breaking things down is not to completely eliminate uncertainty, but to reach a state where concrete actions can be taken for each one.
Reducing Anxiety Through Information
Separate from uncertainty, there is "anxiety" in projects.
Regardless of their position—whether engineers, project owners, or executives—people feel discomfort when they are in a state of "not knowing what will happen next," "not knowing how far things have progressed," or "not even knowing whether a problem has occurred." The anxiety that arises from this lack of visibility is what we're dealing with.
It's impossible to eliminate it entirely. However, anxiety can be reduced by sharing information about the current status and future outlook. Test results, milestones, risk lists, and decisions along with their deadlines are examples of such information.
What's important here is that managing these things itself is not the goal.
There is no inherent value in drawing milestones, creating roadmaps, or measuring test coverage. These are all information for creating a state where stakeholders can understand "where we are now, what is known, what is unknown, and what will happen next."
Outputs are visible. This is also one of the reasons why, even though outcomes are said to be important, outputs are strongly focused on in projects.
In that sense, outputs in project management can be considered to have not only the role of deliverables, but also the role of providing current status and outlook against an uncertain future.
Facing Uncertainty
In project management, it's impossible to predict everything accurately from the start. First, we clarify "what is unknown," then break it down into manageable units. Here we'll look at the actual procedures.
How to Break Down Uncertainty
First, put "what is unknown" into words. It's fine to start from a large anxiety like "I don't know if we can release by the end of September." However, since that alone doesn't lead to concrete actions, further breakdown is needed.
Here, we think in terms of "what must be in place for us to release by the end of September." For example, the following would be fulfillment conditions.
- Requirements are finalized by the beginning of August
- API specifications are finalized by the beginning of August
- The necessary engineering resources are secured
- Testing and performance requirement verification are completed by September
- A release go/no-go decision can be made by September
The first question to consider is: "What must be true for this output to materialize as planned?"
In PMI as well, Assumptions in a project are treated as correct for planning purposes, while also being treated as not yet verified. If such premises turn out to be wrong, they become risks to the project.
Don't make an ass out of you and me--using assumptions effectively
Therefore, after listing the fulfillment conditions, we verify for each one "whether it is a confirmed fact, or merely something we believe to be true." Even for a single condition like "API specifications will be finalized by the end of August," there are the following differences.
- The contract explicitly states that finalization by the end of August is required
- The API team says "it'll probably be ready in time"
- It hasn't been confirmed at all
All of these can be written as "will be finalized by the end of August," but the strength of the evidence differs greatly.
In practice, it's not uncommon for an API that was contractually agreed to be possible to arrive with specifications completely different from what was expected. Therefore, "someone said so" and "it has been confirmed to actually be in place" need to be treated as separate things.
In PMI as well, Assumption Analysis—examining the inaccuracy, instability, inconsistency, and incompleteness of assumptions—is treated as one method for identifying risks. In other words, the purpose of listing fulfillment conditions and their basis is not to eliminate uncertainty on the spot. It is to identify where uncertainty remains.
Understanding Risks
Once fulfillment conditions and assumptions become visible, the next step is to consider "what would happen if that assumption breaks down."
NASA's Risk Management Handbook expresses risk using the following structure.
- What is the current situation
- What deviation from that situation is possible
- What is affected by it
- What is the ultimate consequence
Condition → Departure → Asset → Consequence
NASA Risk Management Handbook
For example, "there's a possibility that the API specifications won't be decided by August" alone is not yet concrete enough as a risk. Breaking this down yields the following.
- Currently, 12 items in the API specifications remain undecided
- Therefore, there is a possibility that the API specifications won't be finalized by August
- In that case, the start of front-end implementation will be affected
- Implementation startup will be delayed, and ultimately there is a possibility of missing the deadline
By organizing things this way, we can handle "a vague feeling of danger" in a form that connects from currently verifiable facts to future impacts. Rather than writing risks as mere speculation, it's necessary to express what could happen as a causal relationship, grounded in the current situation.
Writing this form as a convention is effective. A risk that ends with just "there is a concern" communicates nothing to anyone other than the person who wrote it. Without the current situation being written, others cannot determine whether it is a genuine risk or just a feeling.
Verifying Hypotheses
How can we reduce uncertainty itself? One approach is to transform hypotheses into verifiable forms.
For example, suppose you're implementing based on the premise that "the new search method should be able to respond within 100ms." At this point, you're advancing the project while depending on an unconfirmed hypothesis that "performance will be sufficient." Since saying "I don't know if performance will be sufficient" forever won't move the project forward, we define what needs to be observed to make a judgment.
So we define: "Load test with 1 million production-equivalent data entries, and if p95 is under 100ms, adopt it." By doing this, we can convert it into the following form.
- Uncertain premise
- Verifiable hypothesis
- Observation method
- Judgment criteria
The important thing is not to keep staring at uncertainty as "something unknown," but to design what needs to be observed in order to reach a state where it can be known.
Convert What Cannot Be Verified into Decisions
Not all uncertainty can be verified. The question "should we postpone by two weeks to prioritize quality, or cut features and release on schedule?" cannot be verified. This is less an uncertainty and more a decision involving value judgments.
In this case, the following needs to be clarified.
- What needs to be decided
- What options are available
- What the judgment criteria will be
- Who will decide
- By when it needs to be decided
The UK Government's guidance for large-scale projects also requires that important Assumptions, Dependencies, and Decisions be made explicit, and that it be recorded who will resolve outstanding matters, through what process, and by when.
In other words, the purpose of breaking down uncertainty is ultimately to reach a state where concrete actions can be taken. If it's a premise, confirm it; if it's a hypothesis, verify it; if it's a risk, monitor it and prepare countermeasures; if it's an undecided matter, convert it into a decision.
How to Handle This in Practice
After identifying uncertainties, they need to be managed continuously.
UK Government's Project Delivery uses an organizational method called RAID, which stands for Risk, Assumption, Issue, and Dependency. Adding Decision to this makes it easier to organize many of the uncertainties in a project.
- Risk: Something that hasn't happened yet but has a possibility of occurring
- Assumption: Something planned as if it's correct, but not yet verified
- Issue: A problem that has already occurred
- Dependency: Something that depends on other work, organizations, events, etc.
- Decision: Something where it hasn't been decided which option to choose among multiple alternatives
In the first half, I divided things into three categories: risk, hypothesis, and decision, but RAID is a form that separates "already-occurring problems" and "dependencies on others" as independent categories.
In practice, I manage these as GitHub Issues. The Issues here are not mere "tasks to be done." They are treated as "units of uncertainty" that need to be resolved, judged, or adjusted as the project progresses.
Note that since I attach a label called raid:issue to GitHub Issues, the word "Issue" becomes doubled. The GitHub container called Issue and the "already-occurring problem" in RAID are separate things. Below, I'll refer to the latter as RAID Issues.
The operation itself is simple. Labels such as raid:risk, raid:assumption, raid:issue, raid:dependency, and raid:decision are attached, and Issues are created following the RAID concept. After that, on the GitHub Projects board, Issues with these labels are displayed in a RAID view, and the rest in a regular view.
Regarding the content of Issues, it's fine to standardize them as Issue Templates. However, in our case, we define how to write Issues in a document within the repository, and operate with AI referencing that content to create Issues.
The following is what was actually done in development with a few people running for a few months, and what was stumbled upon. Only one GitHub Issues board and one GitHub Projects board are used.
Expressing Fulfillment Conditions
I first turned the large anxiety equivalent to "I don't know if we can release by end of September" into a single Issue. Then I cut out each fulfillment condition into sub-issues.
The parent is created as "what must be true for this output to materialize," and the children are created as those conditions. This way, the Sub-issues progress in GitHub Projects becomes directly a display of "how many of the conditions have been addressed." The Issue completion rate becomes the progress of fulfillment conditions as-is.
When I actually broke it down, there were 7 child items. The breakdown was 1 Risk, 2 Dependencies, 1 RAID Issue, 1 Assumption, and 2 Decisions.
After trying this, what I understood is that this is completely separate from PR decomposition. The basic concept is 1 issue per 1 PR, and when that's not possible, sub-issues are created. This couldn't be handled with the previous method, so the convention itself was changed to treat RAID as a separate category.
Facing Anxiety
Separate from uncertainty itself, we also need to face the "anxiety" of stakeholders.
Anxiety doesn't simply arise from a lack of information. It intensifies when stakeholders can no longer understand the following.
- How far things have progressed
- How things will proceed from here
- What is not proceeding as planned
- What has not yet been decided
- Who will make a judgment and when
That said, sharing a large volume of information is not necessarily the solution. What's needed is to create a state where necessary information about three things—current status, the future, and decision-making—can be continuously observed.
Information That Shows the Present
First, it's necessary to be able to observe "how far we've come." For example, the following types of information.
- CI execution results
- Test results
- Test coverage
- Completed outputs
- Incomplete outputs
- Currently occurring Issues
- Progress status
One thing to be careful about here is the progress rate.
For example, even if there are 100 Issues and 80 have been closed, expressing this as "80% complete" doesn't necessarily mean the project is truly 80% complete.
If among the remaining 20 items there are important items such as:
- Production migration
- Performance testing
- Integration testing with external systems
- Security review
then the important conditions for making the deliverable work have not yet been confirmed.
Therefore, rather than looking at the simple Issue completion rate, it's more important to see what has been established against the completion conditions of the deliverable. For example, the following expression is far more accurate as a representation of current status.
The implementation of the course information retrieval API is complete.
Unit testing is also complete.
On the other hand, integration testing with the external API has not yet started, and performance testing has not been conducted either.
In other words, "showing the present" should be thought of not as reporting on workload, but as showing "which of the fulfillment conditions have already been confirmed and which have not yet been confirmed."
The same applies to CI and test coverage.
The goal is not that CI is Green or that test coverage is 80%. The value lies in being able to judge from that information which parts of the deliverable have been mechanically verified and which parts still have uncertainty remaining.
Knowing Whether the Information Being Shown Is Broken
I maintained a mechanism for recording sprint completions via automation that ran daily. The processing was simple: link Issues closed during a period to sprints that had passed their deadline, close that sprint if everything was done, and create the next sprint.
One day, this automation started failing every day. The cause was a specification change on GitHub's side—passing only a date to the due date field started returning 422. A syntax that had previously worked stopped working one day. As a result, the next sprint was not created. The 20 items closed that week remained unattached to any sprint. It took about a week to finally notice... What was surprising was that nothing appeared to be broken. CI was green, the board was operating normally, and Issues were being closed steadily.
From this, I learned two things.
One is that the mechanism for outputting information is itself a deliverable with fulfillment conditions. "Running every day" is an unverified premise. If scheduled execution keeps failing but no one looks at it, it's the same as not being visualized.
The other is that "sharing information reduces anxiety" has a prerequisite. The shared information needs to match reality. Information that doesn't match reality doesn't reduce anxiety—it prevents you from feeling anxious when you should be. I think the latter is more dangerous.
Information That Shows the Future
Even if the current status is understood, anxiety remains if what lies ahead is not visible. Therefore, what's next needed is information showing "what is planned to happen from here."
The following types of content apply.
- Milestones
- Roadmap
- Dependencies
- Target Dates
- Risk list
- Unverified Assumptions
Here too, simply listing dates is not sufficient.
In the following example, you can tell what will happen on those dates, but you can't tell what is expected to be established.
8/1 API work
8/15 Front-end implementation
9/1 Testing
More important is showing what becomes possible afterward, like this.
8/1 API specifications finalized
→ Front-end implementation can begin
8/15 API implementation complete
→ Integration testing can begin
9/1 Integration testing complete
→ Release go/no-go decision can be made
For example, right after a product starts and development is moving rapidly, I don't think it's necessary to forcibly set milestones. Instead, it's necessary to summarize what was done and what became possible with each sprint or iteration.
In the case of GitHub Projects, you can share project updates, so that feature is used effectively.
I placed one update per sprint, summarized in a few lines what became possible in that sprint, and also included a link to the list of Issues and PRs for that period. The intent is to make it possible to drill down to the source, since just a summary doesn't allow you to verify "is that really all there is."
Showing Dependencies
Among all factors in creating a future outlook, dependencies are particularly important. In projects, there are vast numbers of "cannot start B until A is done" relationships. Without these dependencies being visible, "individual tasks are progressing smoothly but the deadline suddenly slips" can occur.
In GitHub Issues, blocked by / blocking dependency relationships can be set between Issues. In other words, "what needs to be finished before the next step can proceed" can be expressed directly as relationships between Issues.
There is also an approach of creating a Blocked Status and placing Issues there, to use this feature or to express being impeded by external factors that cannot be turned into Issues.
When actually tried, blockers fell into two categories. One kind can be expressed as Issues, and these are linked with blocked by. The other kind cannot be turned into Issues—things like finalization of contract terms, cost decisions, release timing decisions, and waiting for specific people's work. The latter cannot have content written if turned into Issues, because they don't exist until someone decides them.
So a separate field was added to the board to write "what is being waited for" in one line. Things like "waiting for finalization of paid plan costs and contract terms" are written—the waiting condition itself. If the blocker is an Issue, the dependency is the record and the field just holds the reason in one line. If the blocker cannot be turned into an Issue, the field alone becomes the record.
What I noticed at this point was that blockers that couldn't be turned into Issues were almost always Decisions. "Waiting for finalization of costs and contract terms" is resolved when someone decides. In other words, this is not a wait but an undecided matter. Looking back with this perspective, some fraction of what was placed in Blocked and left there was actually waiting for a decision.
Through these mechanisms, it becomes possible to see which incomplete Issues are blocking which future outputs. This is important for reducing anxiety. The following is superior as decision-making material compared to simply "there is a delay."
- The API specification finalization Issue is 3 days behind
- This Issue is blocking front-end implementation
- As of now, there are 2 days of buffer remaining until the integration testing start date
Visualizing Decision-Making
Even when current status and future are visible, projects can stall.
A typical case is the state of "someone needs to decide before we can proceed." For example, problems such as the following.
- Should we use the new API or the old API
- Should we continue performance improvements or cut features
- Should we postpone the release or launch as planned
These are not tasks. Managing them with Statuses like "in progress" or "in response" makes it hard to understand what is happening. Therefore, the decisions themselves are made into management targets.
These can also be managed in GitHub Issues and handled by attaching labels. Then, by creating a list of Issues with that label that have not been closed on the project, it becomes possible to confirm undecided matters currently remaining in the project.
Here, just one view was added. A table showing only Issues with the Decision label that have not yet been closed. The columns show the decision-maker and the deadline.
Operating a Project
A project is not something that ends simply by making a plan and executing it. It's necessary to proceed by reviewing premises and plans based on information obtained during execution, and making necessary judgments along the way.
Since uncertainty cannot be completely eliminated, what's important is not to fix the initial plan until the end, but to create a state where the gap between plan and reality can be continuously observed and updated as needed.
Continuously Converting the Unknown to the Known
Uncertainty is not something that can be addressed by a single identification exercise at the start of a project. As progress is made, new information is obtained, premises believed to be correct break down, and new dependencies and risks are discovered.
What I want to distinguish here is "known unknowns" and "unknown unknowns." Recognizing that something could become a problem but not yet knowing its content or impact is different from not recognizing in the first place that something could become a problem. RAID and Decisions are tools for organizing the former, while the latter cannot be managed as-is. Therefore, what's important is to discover unknowns as early as possible and convert them into known unknowns.
There are two methods.
One is to identify things periodically from the same perspective. Timing includes the end of sprints or iterations, when a milestone is reached, when a major specification change occurs, and when there are changes to external dependencies. The perspective is kept the same each time.
- What has been newly learned?
- Are there any Assumptions that were previously in place that have now broken down?
- Are there any newly arising Risks?
- Is there anything that has become Blocked?
- Is there any newly needed Decision?
- Is there anything impeding the realization of the next output?
- If this plan were to fail, what would be the cause?
The other is to actually try things on a small scale. Conducting PoCs, performance tests, integration tests, and verification in staging environments at an early stage surfaces problems that were not visible at the planning stage. Identification is the work of rearranging known unknowns, but unknown unknowns don't emerge without hands-on work.
Things that are found are fed back into the mechanisms already in use, rather than adding new management methods. What happened most often here was re-categorization of types. An Assumption breaks down and becomes a Risk; a Risk becomes a RAID Issue; something turns out to be unverifiable and becomes a Decision. It's not often that the type initially assigned remains correct until the end. Therefore, when a type is changed, I make sure to record why it was changed. The history of re-categorization itself becomes a record of "what was learned."
What Is Predictability
Throughout this text I've used the phrase "predictable state," but predictability does not mean that the project proceeds exactly as the initial plan.
Since projects have uncertainty, there will always be a gap between plan and reality. Sometimes the expected API doesn't arrive; sometimes performance requirements can't be met. Sometimes an unanticipated dependency is discovered, or the requirements themselves change midway.
What's important is being able to recognize that gap when a difference arises between plan and reality.
For example, even if the finalization of API specifications is delayed, if it's understood when the front-end implementation will start to be affected by the delay, how much buffer currently exists, after how many days of delay to switch to an alternative, and who will make that judgment, then the situation is manageable. Even without being able to perfectly predict the future, the project can proceed.
Conversely, even if all tasks appear to be progressing as planned, if dependencies and unverified premises are not grasped, the project cannot be said to be predictable. A board that appears normal and a board that is correct are different things.
Therefore, predictability in project management is better understood not as accurately predicting the future, but as being in a state where, when the future deviates from expectations, that change can be observed early, its impact understood, and necessary decisions made. And the observation mechanism itself falls within the scope of what is observed.
In Closing
Through this learning exercise, I came to understand well that the focus of project management is on creating a state where delivery can proceed without anxiety for stakeholders. I was also able to articulate quite a bit about the anxiety I myself had been carrying, and there's a part of me that feels a little relieved.
On the other hand, another thing I understood from actually doing it is that creating mechanisms is not the end of the work. Being prepared with means to see whether the mechanisms you've created are alive and functioning is the next challenge.