
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 take strong responsibility 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 is more strongly treated as the subject of management.
This time, I've compiled 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've concluded that project management is the activity of facing uncertainty and anxiety, and 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 that uncertainty creates in people."
Decomposing 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 action. So, we decompose uncertainty into perspectives like the following.
- Risk: There's a possibility that an undesirable event will occur in the future
- Assumption: It's unclear whether what we're treating as a premise is correct
- Decision: Among multiple options, it hasn't been decided which one to choose
For example, the uncertainty of "I don't know if we can release Feature A as planned" can be decomposed like this.
- Risk: "The external API might not be provided as planned"
- Assumption: "This design should deliver sufficient performance"
- Decision: "Should we prioritize performance, or prioritize the deadline"
Even with the same "not knowing," the next action to take differs depending on the type. The purpose of decomposing is not to completely eliminate uncertainty, but to reach a state where concrete action can be taken for each.
Reducing Anxiety Through Information
Separate from uncertainty, there is "anxiety" in projects.
Regardless of position—engineers, project owners, executives—people feel discomfort in states like "I don't know what will happen next," "I don't know how far we've progressed," and "I don't even know if there are problems." The anxiety that arises from this lack of visibility is what we're dealing with.
It's impossible to bring it to zero. However, anxiety can be reduced by sharing information about the current state and future outlook. Test results, milestones, risk lists, and decision items with their deadlines are examples of such information.
What's important here is that managing these things is not an end in itself.
There's no inherent value in setting 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 reason why, even though outcomes are said to be important, outputs are strongly emphasized in projects.
In that sense, outputs in project management can be thought of as having not only a role as deliverables, but also a role of providing a current position 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 not known," then decompose it to units that can be handled. Here we look at the actual procedure.
How to Decompose Uncertainty
Start by writing down "what is not known" in sentences. 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 action, further decomposition is needed.
Here, we think in the form of "what must be true for a September-end release to happen." For example, the following might be fulfillment conditions.
- Requirements are finalized by early August
- API specifications are finalized by early August
- Necessary engineering resources are secured
- Testing and performance requirement verification are completed during September
- A release go/no-go decision can be made during September
The first question to consider is: "What must be true for this output to be realized as planned?"
In PMI as well, Assumptions in a project are treated as correct for planning purposes, while being treated as not yet verified. If such assumptions turn out to be wrong, that becomes a project risk.
Don't make an ass out of you and me--using assumptions effectively
Therefore, after writing out the fulfillment conditions, check each one to see whether it's "a verified fact or just something you believe to be true." Even taking a single condition like "API specs will be finalized by the end of August," there are differences like the following.
- The contract explicitly states finalization by end of August
- The API team says "it'll probably be ready in time"
- It hasn't been confirmed at all
Each can be written as "will be finalized by end of August," but the strength of the basis differs greatly.
In practice, it's not even rare for an API that was contractually said to be available to arrive with specifications completely different from what was assumed. Therefore, "someone said so" as a fact and "it has been confirmed to actually be established" as a state need to be treated separately.
PMI also treats Assumption Analysis—examining the inaccuracy, instability, inconsistency, and incompleteness of assumptions—as one method for identifying risks. In other words, the purpose of listing fulfillment conditions and their basis is not to immediately eliminate uncertainty. It is to identify where uncertainty remains.
Understanding Risks
Once fulfillment conditions and assumptions become visible, the next step is to think about "what would happen if that assumption collapsed."
NASA's Risk Management Handbook expresses risk with the following structure.
- What is the current situation
- What kind of deviation may occur from there
- What is affected by it
- What kind of result does it ultimately lead to
Condition → Departure → Asset → Consequence
NASA Risk Management Handbook
For example, "there's a possibility the API specs won't be decided by August" alone is not yet specific enough as a risk. Decomposing this gives us the following.
- Currently, 12 unresolved items remain in the API specifications
- Therefore, there's a possibility the API specifications won't be finalized by August
- In that case, the start of frontend implementation will be affected
- Implementation start will be delayed, and there's a possibility of ultimately missing the deadline
By organizing things this way, we can handle what "feels vaguely dangerous" 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 are concerns" conveys nothing to anyone other than the person who wrote it. If the current situation isn't written, others cannot determine whether it's truly a risk or just a feeling.
Verifying Assumptions
How can we reduce uncertainty itself? One way is to transform assumptions into a verifiable form.
For example, suppose you're implementing based on the assumption that "a new search method should be able to respond within 100ms." At this point, the project is moving forward while depending on an unverified assumption that "performance should be achievable." Since the project can't move forward by just saying "we don't know if performance will be achieved," we define what must be observed to make a judgment.
So we define: "We will conduct a load test with 1 million records of production-equivalent data, and adopt the approach if the p95 is under 100ms." This allows the conversion into the following form.
- Uncertain assumption
- Verifiable hypothesis
- Observation method
- Judgment criteria
What's important is not to continue viewing uncertainty as "something unknown," but to design what must be observed to reach a state of knowing.
Convert What Cannot Be Verified into Decisions
Not all uncertainty can be verified. The question "Should we delay by two weeks to prioritize quality, or should we reduce features and release as planned?" cannot be verified. This is less of an uncertainty and more of a decision involving value judgment.
In this case, clarify the following.
- What needs to be decided
- What options are available
- What the judgment criteria are
- Who decides
- By when it needs to be decided
The UK government's guidance for large-scale projects also requires explicitly stating important Assumptions, Dependencies, and Decisions, and recording who, through what process, and by when unresolved matters will be resolved.
In other words, the purpose of decomposing uncertainty is ultimately to transform things into a state where concrete action can be taken. Assumptions are confirmed, hypotheses are verified, risks are monitored or mitigated, and unresolved matters are converted into decisions.
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, an acronym for Risk, Assumption, Issue, and Dependency. Adding Decision to this makes it easier to organize many uncertainties in a project.
- Risk: Something that hasn't happened yet but has a possibility of occurring
- Assumption: Something treated as correct in the plan but not yet verified
- Issue: A problem that has already occurred
- Dependency: Reliance on other work, organizations, events, etc.
- Decision: Among multiple options, it hasn't been decided which to choose
In the first half, I divided things into three categories—risk, assumption, and decision—but RAID is a form that independently separates "problems that have already occurred" and "dependencies on others" from those.
In practice, I manage these as GitHub Issues. The Issues here are not simply "tasks to be done." They are treated as "units of uncertainty" that need to be resolved, judged, or coordinated to move the project forward.
Note that since I attach a label called raid:issue to GitHub Issues, the word "Issue" becomes doubled. GitHub's container called an Issue and "a problem that has already occurred" in RAID are different things. Hereafter, the latter will be written as RAID Issue.
The operation itself is simple. I create Issues following RAID thinking with labels like raid:risk, raid:assumption, raid:issue, raid:dependency, and raid:decision. Then in GitHub Projects' board, I separate Issues with these labels into a RAID view, and the rest into a regular view.
For 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 several months, and what stumbled along the way. Only one GitHub Issues board and one GitHub Projects board were used.
Expressing Fulfillment Conditions
I first made 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 the fulfillment conditions one by one into sub-issues.
The parent is created as "What must be true for this output to be realized," and the children as those conditions. This way, GitHub Projects' Sub-issues progress becomes a display of "how many of the conditions have been cleared." The Issue completion rate directly becomes the progress on fulfillment conditions.
When I actually decomposed it, there were 7 child issues. The breakdown was 1 Risk, 2 Dependencies, 1 RAID Issue, 1 Assumption, and 2 Decisions.
After trying this, what I understood was that this is completely different from PR decomposition. The basic concept is 1 PR per issue, and when that's not possible, sub-issues were created. This couldn't be handled with the previous approach, so I changed the conventions themselves and decided 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 arise simply because there's little information. It grows stronger when stakeholders can no longer understand the following.
- How far things have progressed
- How things will proceed from here
- What isn't going as planned
- What hasn't been decided yet
- Who will make a judgment and when
That said, sharing large amounts of information isn't the answer either. What's needed is to create a state where necessary information about the three things—current position, future, and decisions—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, information like the following.
- CI execution results
- Test results
- Test coverage
- Completed outputs
- Incomplete outputs
- Currently occurring Issues
- Progress status
One thing to be careful about here is progress rate.
For example, even if there are 100 Issues and 80 are Closed, expressing this as "80% complete" doesn't necessarily mean the project is truly 80% complete.
If the remaining 20 items include:
- Production migration
- Performance testing
- Integration testing with external systems
- Security review
then important conditions for realizing the deliverable have not yet been confirmed.
Therefore, rather than a simple Issue completion rate, it's more important to see what has been established against the completion conditions for the deliverable. For example, the following expresses the current state far more accurately.
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 started, and performance testing has not been conducted.
In other words, "showing the present" is better understood not as reporting work volume, but as showing "what among the fulfillment conditions has already been confirmed, and what has not yet been confirmed."
The same applies to CI and test coverage.
CI being Green or test coverage being 80% is not an end in itself. 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 was maintaining a mechanism to record completion for each sprint with daily-running automation. Processing that takes Closed Issues during a period and attaches them to a sprint that has passed its deadline, closes that sprint if everything is done, and creates the next sprint. That's all it does.
One day, this automation started failing every day. The cause was a GitHub specification change, where passing only a date for the due date started returning a 422 error. A way of writing that had been working until then stopped working one day. As a result, the next sprint was not created. The 20 Issues closed that week remained without belonging to any sprint. It took about a week to finally notice... What was striking was that nothing appeared to be broken. CI was green, the board was operating normally, and Issues were being closed steadily.
I learned two things from this.
One is that the mechanism for outputting information is also a deliverable, and it has fulfillment conditions. "Running every day" is an unverified assumption. If a scheduled execution keeps failing and no one looks at it, it's the same as not being visualized.
The other is that "sharing information reduces anxiety" has conditions. The information being shared needs to match reality. Information that doesn't match doesn't reduce anxiety—it prevents anxiety from being felt when it should be. I think the latter is more dangerous.
Information That Shows the Future
Even if the current position is known, anxiety remains if what lies ahead isn't visible. Therefore, the next thing needed is information that shows "what is expected to happen from here."
The following types of content apply.
- Milestones
- Roadmaps
- Dependencies
- Target Dates
- Risk lists
- Unverified Assumptions
Here too, simply listing dates is not sufficient.
In the following example, you can tell what happens on each date, but you can't tell what is expected to be established.
8/1 API work
8/15 Frontend implementation
9/1 Testing
More important is to show what becomes possible afterward, like this.
8/1 API specifications finalized
→ Frontend implementation can begin
8/15 API implementation complete
→ Integration testing can begin
9/1 Integration testing complete
→ Release go/no-go can be decided
For example, if development is progressing rapidly right after a product launch, I think there's no need to forcibly set milestones. Instead, it's necessary to summarize what was done and what became possible with each sprint or iteration.
In GitHub Projects, project updates can be shared, so that feature is used effectively.
I placed one update per sprint, summarized in a few lines what became possible during that sprint, and also included links to the list of Issues and PRs from that period. The idea is that with just the summary, you can't verify "is that really all," so I made it possible to drill down to the source material.
Showing Dependencies
When creating visibility into the future, what's particularly important is dependencies. In projects, there are large numbers of relationships where "B can't start until A is finished." Without visibility into these dependencies, situations arise where "individual tasks are on track, but only the deadline suddenly slips."
In GitHub Issues, blocked by / blocking dependency relationships can be set between Issues. In other words, "what must finish before proceeding to the next step" can be expressed directly as relationships between Issues.
There's also a method of preparing a Blocked Status and placing Issues there, to use this feature or to express things being impeded by external factors that can't be made into Issues.
When I actually tried it, blockers fell into two types. One type could be expressed as Issues, and these are linked with blocked by. The other type could not be made into Issues: finalization of contract terms, cost judgments, release timing decisions, waiting on a specific person's work, and so on. The latter can't have content written even if made into an Issue, because they don't exist until someone decides.
So I added a separate field on the board to write in one line "what are we waiting for." I write the waiting condition itself, like "Waiting for finalization of paid plan costs and contract terms." 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 made into an Issue, only the field serves as the record.
What I noticed here was that blockers that can't be made into Issues are usually Decisions. "Waiting for finalization of costs and contract terms" is resolved once someone decides. In other words, this is not waiting—it's an unresolved matter. Looking back through this lens, several of what had been left sitting in Blocked were actually things that had been waiting for a decision.
Through these mechanisms, it becomes possible to see which incomplete Issue is blocking which future output. This is important for reducing anxiety. Rather than information that says "we are behind schedule," the following is a superior basis for judgment.
- The API specification finalization Issue is delayed by 3 days
- This Issue is Blocking frontend implementation
- As of now, there are 2 days of margin until the integration test start date
Visualizing Decisions
Even when the current state and future are visible, projects can come to a standstill.
The typical case is the state of "someone needs to decide before things can move forward." For example, problems like the following.
- Should we use the new API or the old API
- Should we continue performance improvement or cut features
- Should we delay the release or ship as planned
These are not tasks. Managing them with statuses like "in implementation" or "in progress" makes it harder to understand what's happening. Therefore, the decisions themselves are made the subject of management.
These can also be managed in GitHub Issues with labels applied. After that, creating a list of Issues with that label that are not yet Closed on the project allows you to see the currently unresolved matters remaining in the project.
Here I added just one view: a table that shows only Issues with the Decision label that are not yet Closed. The columns show the decision-maker and the deadline.
Operating a Project
A project is not something that ends by making a plan and executing it. It's necessary to proceed while revising assumptions and plans based on information obtained during execution, and making necessary judgments.
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 the plan and reality can be continuously observed and updated as needed.
Continuously Converting Unknown to Known
Uncertainty doesn't end with a single identification at the start of a project. As you proceed, new information is obtained, assumptions believed to be correct collapse, and new dependencies or risks are found.
What I want to distinguish here is "known unknowns" and "unknown unknowns." There's a difference between a state where you recognize something could be a problem but don't yet understand its content or impact, and a state where you don't even recognize that something could be a problem. RAID and Decision are tools for organizing the former, and the latter cannot be made a subject of management as-is. That's why it's important to discover unknowns as early as possible and convert them into known unknowns.
There are two methods.
One is to regularly identify things from the same perspective. The timing includes the end of sprints or iterations, when milestones are reached, when major specification changes occur, and when there are changes in external dependencies. The perspective is kept the same each time.
- What new things have been learned
- Are there any Assumptions that were previously held but have now collapsed
- Are there any newly occurring Risks
- Are there any newly Blocked items
- Are there any newly needed Decisions
- 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 moving things on a small scale. Conducting PoC, performance testing, integration testing, validation in a staging environment, and so on at an early stage surfaces problems that weren't visible at the planning stage. Identification work is about rearranging known unknowns, but unknown unknowns don't emerge without getting your hands moving.
What is found is fed back into the mechanisms already in use, rather than adding new management methods. What happened most often here was reassigning types. An Assumption collapses and becomes a Risk, a Risk becomes a RAID Issue, and when something turns out not to be verifiable, it becomes a Decision. It's rare for the type initially assigned to remain correct until the end. Therefore, when types are changed, I make sure to record why the change was made. The history of reassignments itself becomes a record of "what was learned."
What Is Predictability
I've been using the phrase "predictable state" throughout, but predictability does not mean that a project proceeds exactly as the initial plan.
Since projects have uncertainty, there will always be gaps between the plan and reality. There will be times when a planned API doesn't arrive, or when performance requirements can't be met. Unexpected dependencies may be discovered, or the requirements themselves may change midway.
What's important is being able to recognize the gap when one arises between the plan and reality.
For example, even if the API specification finalization is delayed, if you know when the delay will start affecting frontend implementation, how much margin currently exists, after how many days of delay you switch to an alternative plan, and who makes that judgment, then the situation is manageable. Even without perfectly predicting the future, the project can proceed.
Conversely, even if all tasks appear to be proceeding as planned, if dependencies and unverified assumptions are not understood, the project cannot be called predictable. The board appearing normal and the board being 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 quickly observed, its impact understood, and necessary decisions made. And the observing mechanisms themselves are included as subjects of observation.
Closing
Through this study, I came to understand well that project management focuses on creating a state where delivery can proceed without anxiety among stakeholders. I was also able to substantially articulate the anxieties I myself had been carrying, and I feel a bit relieved in that regard.
On the other hand, I also understood through doing it that building mechanisms is not the end of the work. The next challenge is to prepare means for seeing whether the mechanisms that were built are actually alive and functioning—including that as part of the whole.