Structure: Prologue + Episodes 1–8 + Epilogue
How to use this guide:
-
The night before each session: Read the corresponding episode (15–20 minutes)
-
After each session for review: Re-read the concept notes and "Try This Week"
-
Can also be read independently, without attending the workshop
1. The Mapmaker
"Giving someone a map is easy. Teaching them to draw one is hard. But only the latter shows them how to truly find their way."
1.1. The Story
When Seunghyun started his career, he believed that being fast was the same as being good.
Whenever a requirement came in, he was the first to open his laptop. He took the speed at which structure formed in his mind as evidence of his ability. And that belief was not entirely wrong — he built things quickly, most of them worked, and his team recognized him for it.
But somewhere past his third year, something strange began to happen.
He found himself rebuilding things he had already built. Code he had worked hard on was discarded after a "this isn’t what I asked for." Features he considered finished ended with "we don’t actually need that anymore" two months later. Technically, he had built exactly what was requested — and yet, somehow, it kept turning out to be wrong.
Then one day, a single sentence from Minjun became the starting point of this story.
"Can you beef up the team collaboration features? Notifications and task assignment. We need a demo next month."
The old Seunghyun would have been thinking WebSocket within fifteen seconds. And he was — but this time, something made him stop.
What do I actually know right now?
This workshop is the story of what Seunghyun learned, starting from that question, across eight sessions.
It is not a story about technology. It is not about any particular framework or language.
It is a story about how to see problems.
1.2. What This Series Covers
People who build software move between two spaces.
Problem Space — What is the problem? Who is suffering? Why does this matter?
Solution Space — How do we solve it? What do we build? What technology do we use?
The issue is that most engineers do not spend enough time in the Problem Space. The moment they hear a requirement, their brain automatically crosses into the Solution Space. The more experience they have, the faster and more natural that transition becomes.
And most rework starts right there.
This workshop teaches two things.
First, tools for exploring the Problem Space deeply — a language for dissecting requirements, methods for handling ambiguity, techniques for grasping the structure of a problem.
Second, and more importantly — when you understand a problem deeply, the solution actually becomes simpler.
What must be achieved becomes clear. What can wait until later becomes visible. What does not need to be built at all becomes identifiable. As a result — you build less, build faster, and deliver to users sooner.
Spending more time in the Problem Space may seem slow. But in practice, that exploration prevents rework in the Solution Space.
1.3. How to Use This Guide
Each episode is meant to be read the night before the corresponding session, or used as a review afterwards.
As you read, put yourself in Seunghyun’s position. There will be moments when Jiyeon’s choices feel like something from your own past. There will be moments when Hyuntae’s discoveries feel entirely new.
The concept notes translate what happens in the story into theoretical language. If you read them again after completing the workshop exercises, they will read differently than the first time.
That is the intention of this structure.
1.4. Characters
Seunghyun (32, fullstack engineer, 5 years of experience) The point-of-view character. He wants to do good work, but keeps feeling like something is going slightly off. He is the most technically skilled person on the team, but lately he has been sensing — faintly — that skill alone is not enough.
Jiyeon (28, fullstack engineer, 3 years of experience) Confident in her ability to build things fast. When a requirement comes in, her hands move first. Nothing is wrong with that. She just doesn’t know yet what she doesn’t know.
Hyuntae (26, fullstack engineer, 1 year of experience) The team’s most junior member. He doesn’t know much — and precisely because of that, he asks about things everyone else takes for granted. His questions often land on what matters most.
Minjun (31, BizDev) The person who brings in client deals. He doesn’t know much about technology, but his instincts about the field are sharp. The requirements he brings are always ambiguous. That’s not his fault.
1.5. Series Contents
| Session | Episode Title | Core Question |
|---|---|---|
Prologue |
The Mapmaker |
Why should I read this? |
Session 1 |
Seunghyun’s Thirty Seconds |
Am I actually understanding the problem, or just recognizing a pattern? |
Session 2 |
The Three Things Hidden in Minjun’s Words |
What does it mean for a requirement to be "clear"? |
Session 3 |
Whoever Asks Designs |
What BizDev wants and what users need are different things |
Session 4 |
Before Drawing the Map |
How do you know when you’ve understood a problem well enough? |
Session 5 |
Walking Through the Fog |
How do you handle ambiguity that cannot be resolved? |
Session 6 |
I’ve Seen This Problem Before |
You may not be seeing this problem for the first time |
Session 7 |
Where to Focus Your Energy |
Should you put the same effort into every part of a design? |
Session 8 |
Seunghyun’s Map |
A solution that looks plausible is different from one that actually works |
Epilogue |
The Person Who Learned to Draw Maps |
After the workshop ends |
First episode: Seunghyun’s Thirty Seconds '''
2. Seunghyun’s Thirty Seconds
"The more experience you have, the faster the answer comes. The trouble is, the answer comes before the question."
2.1. The Story
Monday, 3 p.m.
Minjun returned from a client meeting and walked back into the office. Before he even set his laptop bag down, a Slack message came through.
Minjun: Hey Seunghyun, I’m back. Talked to the client — they want us to beef up the team collaboration features. Notifications and task assignment. Need to show them a demo next month.
Seunghyun read the message. And stopped.
Right. Notifications. Task assignment.
Something in his mind began to run on its own. Notifications meant WebSocket or SSE. Or maybe Firebase. Task assignment meant an assignee column, or a separate assignment table. If real-time updates were needed, a pub/sub architecture would fit. Next month was one month away. One month meant…
Fewer than fifteen seconds had passed, and Seunghyun already had a rough structure sketched in his head.
From the next desk, Jiyeon swiveled her chair and said:
"Did you see that? The notification feature. I’ve been wanting to try Kafka — maybe this is the moment."
Seunghyun started to answer, then stopped.
Hold on.
Something felt off. It had been less than thirty seconds since the message arrived. And already, he and Jiyeon were both talking about technology — without asking Minjun a single question.
What do I actually know right now?
Seunghyun read the Slack message again.
"Team collaboration features." "Notifications and task assignment." "Demo next month."
Three sentences. That was everything.
I don’t know the client’s team size. I don’t know why they’re asking to improve notifications. I don’t know what the current notification setup looks like. I don’t know how task assignment is currently handled. I don’t know what needs to be shown in the demo.
And yet he had been thinking about WebSocket within fifteen seconds.
Seunghyun got up from his desk and walked over to Minjun.
"Minjun — how does that team actually work right now? When you say they want stronger notifications, what specific situation is that coming from?"
Minjun opened his laptop and answered.
"Oh, right — so, the team lead assigns tasks and the team members never find out. They have to separately message on Slack to tell them, which is a huge hassle."
Ah.
Seunghyun thought to himself.
This isn’t a problem with notification technology. The problem is that the task assignment workflow never connects to the system in the first place.
Whether WebSocket was needed was still unknown. Maybe a single email notification would be enough. Maybe what came first wasn’t notifications at all, but the task assignment screen itself.
In those thirty seconds, Seunghyun had learned something.
What he had felt as "understanding the problem" had actually been recognizing a pattern.
2.2. Concept Notes
2.2.1. Why We Reach for an Answer in Thirty Seconds
What happened to Seunghyun is not unusual. The more experience an engineer has, the faster and more naturally it occurs.
In psychology, this is called the Einstellung Effect[1] — a previously successful solution sits ready in the mind, and when a similar signal arrives, it fires automatically. It is a mechanism the brain creates for efficiency.
The problem is that this mechanism blocks us from seeing new problems clearly. Even when a better solution is right in front of us, the familiar answer arrives first, and we stop looking. And ironically, the more experience you have, the more strongly this effect operates.
Less experience → fewer patterns → slower but exploratory
More experience → richer patterns → faster but automatic
↑
this is the trap
2.2.2. Presumptive Architecture — The Default in Your Head
Software architecture researcher George Fairbanks describes this with the concept of Presumptive Architecture[2].
Every developer carries an unconscious default: "for this kind of situation, use this architecture."
-
Real-time notifications →
pub/sub -
Batch processing → queue
-
Search → Elasticsearch
-
High volume →
Kafka
These defaults are not wrong. For the right situation, they’re a perfect fit. But whether they fit the problem at hand — that is still unknown.
The real danger of Presumptive Architecture comes when it is used without distinguishing assumption (assumption) from analysis (analysis). Like when Jiyeon said "I’ve been wanting to try Kafka" — when a technology choice comes before problem analysis.
2.2.3. Problem Space and Solution Space
Polya describes problem-solving as moving through two spaces.[3]
| Problem Space | Solution Space |
|---|---|
"What is the problem?" |
"How do we solve it?" |
"Who is suffering?" |
"What do we build?" |
"Why is this a problem?" |
"What technology do we use?" |
"Is this really the problem?" |
"How do we design the structure?" |
Tools: questions, observation, interviews |
Tools: design, code, diagrams |
Both spaces must be visited. This is not an argument against entering the Solution Space. The key is that the transition must be conscious.
Seunghyun’s automatic WebSocket thought was an unconscious, automatic transition. His walk over to Minjun was a conscious reversal of that move.
2.2.4. The Paradox of Experience
There is a reason engineers at three to four years of experience are especially prone to this trap.
Someone with one year of experience asks a lot of questions because they don’t know much. Someone with ten years has accumulated enough experience to question their own patterns. But someone at three to four years has learned enough patterns that answers come before questions — and those answers seem quite plausible.
This is the paradox of experience.
The goal of this workshop is not to discard experience. It is to treat experience as assumption. The intuition that says "this looks like a pub/sub problem" is valid. The practice is building the muscle to pause in the Problem Space before that intuition solidifies into "this is a pub/sub problem."
|
Experience is an asset. The moment you treat patterns that emerge from experience as assumptions rather than analysis, you start using that asset more effectively. |
Seunghyun’s thirty seconds was the beginning of that practice.
2.3. Try This Week
Try these two things consciously this week.
First. When you receive a requirement or a work assignment, ask yourself: "Am I understanding the problem, or am I recognizing a pattern?"
Second. Set aside the solution that just came to mind, and generate at least five Problem Space questions. "What do I still not know?"
If that feels awkward and uncomfortable, you’re doing it right.
Next episode: The Three Things Hidden in Minjun’s Words — How to dissect requirements into Functions, Attributes, and Constraints
3. The Three Things Hidden in Minjun’s Words
"The requirement isn’t unclear. There are just three different kinds of things mixed together."
3.1. The Story
Thursday morning.
Seunghyun, Jiyeon, and Minjun gathered in a small meeting room. On one side of the whiteboard was the sentence from last time:
"Team collaboration features. Notifications and task assignment. Demo next month."
Jiyeon opened her laptop and said:
"Seunghyun, I thought it through last night. I think SSE will work for the notifications, and adding an assignee field to tasks covers the basics. I’d guess we can have an MVP in about two weeks."
Minjun nodded. "Oh, that’s quick."
Seunghyun started to say something but stopped. What Jiyeon said was not wrong — technically it was entirely feasible. But something felt missing.
We’re sending notifications — which notifications? At what point? Who needs to receive them? We’re assigning tasks — how are tasks currently assigned? What’s frustrating about it? Demo — what exactly does the client want to see?
Seunghyun spoke up.
"Minjun — hold on. Just one question. You said the client can’t keep track of task assignments, right? Is the specific situation that a team lead assigns a task and the member doesn’t know about it, or that the assignment isn’t being made in the first place?"
Minjun thought for a moment.
"Ah — the assignment itself is happening. Inside the system. But when a task gets assigned, nothing goes out to the team member. The team lead has to send a separate Slack message saying 'can you take this?'"
Ah. Seunghyun began to write.
"So the notification is only needed when a task is assigned — or does it also need to go out when the status changes?"
"Hmm… when assigned, and when a deadline is approaching, I guess."
"What’s the team lead’s environment like? Desktop, or do they use mobile too?"
"Oh, these are manufacturing folks — they’re out on the floor a lot. Mobile would be good to have."
Jiyeon quietly closed her laptop.
"…SSE doesn’t work when you’re backgrounded on mobile."
Silence.
Seunghyun walked to the whiteboard. He began writing what Minjun had said, divided into three columns.
Functions │ Attributes │ Constraints
──────────────────┼─────────────────────────┼──────────────────
Notify on │ Works in mobile │ Demo next month
task assignment │ background │
│ │ Keep existing
Deadline reminder │ Delivered within │ assignment UI (?)
│ 1 minute │
[?] │ [?] │ [?]
"Minjun, see all those question marks? Those are the things we don’t know yet. If we start building without answering them, we’re going to have to tear everything apart later."
Minjun stared at the whiteboard for a while.
"But… some of these are things I need to go back and ask the client about."
"Exactly. On the Attributes side — how fast the notifications need to arrive, whether there should be a re-send if someone hasn’t read it. Even if you asked me, I couldn’t answer those. We need to go directly to the client’s users."
Jiyeon said:
"So the two-week MVP…"
Seunghyun smiled.
"Is two weeks after we know what we’re building."
3.2. Concept Notes
3.2.1. The Three Layers of a Requirement
The three columns Seunghyun drew on the whiteboard come from the FAC framework[4] that Weinberg presents in Exploring Requirements.
Every requirement looks like a single sentence on the surface — but in practice, it contains three distinct kinds of information mixed together.
Functions — What does it do?
The actions the system performs. These are the most visible, and the first to surface in conversation.
"Send a notification." "Assign a task." "Show a list."
Both BizDev and users naturally speak in Function language. So engineers tend to hear only Functions and stop there.
Attributes — How must it do it?
The quality criteria for a Function. "How quickly." "How reliably." "In what environment." "In what form."
Attributes rarely surface first in conversation. The person speaking either takes them for granted and omits them, or hasn’t thought them through clearly yet. But Attributes determine Architecture.
The way Jiyeon’s SSE choice fell apart — that was because she didn’t know about the mobile background constraint, which was an Attribute.
Constraints — What cannot be touched?
The conditions a solution must respect. Technical (existing systems, infrastructure), business (budget, timeline), legal (regulations, contracts).
Constraints are the hardest to uncover. They are so obvious to the people involved that they don’t say them. And they’re discovered latest — usually after the design is complete.
The later a constraint is discovered, the more exponentially expensive the rework becomes.
3.2.2. Ambiguity Comes from Three Places
The reason filling in FAC is hard is that ambiguity comes from three different sources.
First, the language itself is ambiguous. The phrase "fast notification" contains no measurement standard. This can be resolved with a question: "How fast do you mean?"
Second, different people interpret it differently. The same word "notification" might make a BizDev picture a desktop popup, a developer think of a server push, and a user expect a text message. This can only be resolved by drawing the picture together.
Third, there are unstated assumptions. Things like "without touching the existing screen" — things that go unsaid because they seem too obvious. These require direct questions to uncover. But how to uncover them — that is the subject of Session 3.
3.2.3. "The Document Is Nothing; the Documenting Is Everything"
The act itself of Seunghyun drawing three columns on the whiteboard was important.
Weinberg says: the purpose of creating a requirements document is not to finish the document. It is that the whole team ends up with the same picture through the process of making it.
|
Drawing the three FAC columns on the whiteboard and filling in the question marks together is itself the act of aligning the team’s understanding. Not the finished document — the process is the point. |
While watching Seunghyun mark the question marks, Minjun made a discovery too. "Some of these are things I need to go back and ask the client about." The whiteboard had generated conversation.
3.3. Try This Week
The next time you receive a requirement, mentally unfold these three columns.
Functions: What actions does this sentence describe?
Attributes: Were quality criteria mentioned? If not, what criteria might influence the architecture?
Constraints: Are there "obvious" things I’m already assuming? Are there unstated conditions the other person may have?
In particular: it is normal for the "?" column to outnumber the "confirmed" column. Knowing what you don’t know is the beginning.
3.3.1. How FAC Creates Simplification
FAC checking has one more important effect.
In the process of filling in the "?" columns — "this is not something we need to build" starts to become visible.
When Attributes become clear, features that don’t need to meet that standard naturally drop out of scope. If "response time under one second" is confirmed as an Attribute, there’s no reason to use WebSocket for secondary features that don’t need real-time updates.
When Constraints become clear, things that need to operate outside those conditions are no longer in scope for now. If a budget ceiling is confirmed as a Constraint, infrastructure beyond that range exits the conversation.
Filling in the "?" columns is simultaneously work to find what needs to be built and work to find what doesn’t. The deeper you explore the Problem Space — the narrower and clearer the Solution Space becomes. And that clarity makes faster delivery possible.
Next episode: Whoever Asks Designs — How to fill the FAC blanks using Context-Free Questions and the Black Box Test '''
4. Whoever Asks Designs
"Direct questions narrow the answers. Good questions open what hasn’t been seen yet."
4.1. The Story
Friday morning.
Seunghyun, Jiyeon, and Minjun gathered in the meeting room again. This time, Minjun said he would connect them by video call with the client’s point of contact — the team lead, Director Kim.
The video connected. Jiyeon spoke first.
"Hello, Director Kim. We’d like to ask about the notification feature. We were thinking it would be good to automate the manual Slack messages you’ve been sending. Would email notifications work for you, or would you prefer app push notifications?"
Director Kim paused.
"Hmm… email or app push… I’m not sure. Whatever’s more convenient, I suppose."
Jiyeon looked at Minjun. Minjun shrugged.
Seunghyun quietly stepped in.
"Director Kim, may I ask something different? Could you walk me through what happens when you assign tasks right now? I’d like to hear the full flow."
Director Kim relaxed slightly.
"Oh, sure. So when we’re out on the floor, we log the assignment in the system, and then we message the team member on Slack — 'can you take this one?' But sometimes they miss it. When people are out on the floor, they don’t check Slack much."
On the floor. Seunghyun wrote it down.
"Are your team members out on the floor a lot too?"
"Yes, we’re factory line supervisors. Everyone’s out there with a tablet or just their phone."
Tablet or phone. He wrote that down too.
"What happens when someone misses a task?"
"Line stoppage. If it doesn’t get handled on time, production halts. Then it comes back on us."
The room went quiet.
Jiyeon was quickly revising something in her notes.
Seunghyun continued.
"Director Kim — may I ask this: is there anything I’ve missed? Any situation I might not have thought of?"
Director Kim thought for a moment, then said:
"Well… we also have a night shift. When urgent assignments come in at night, the message needs to go out even faster. That’s when it becomes the biggest problem."
Seunghyun stopped writing. Urgent assignments on the night shift. This was entirely unexpected.
After the call ended, Jiyeon closed her laptop and said:
"My first question was email or push notification — I can see now how narrow that question was."
Seunghyun walked to the whiteboard and began writing.
Trigger: On task assignment / On urgent assignment (including nights)
Input: Team lead's assignment action (within the system)
Output: Immediate delivery to team member's device (tablet/phone)
Edge: Team member is offline
Urgent assignment during night shift while asleep
"Does it look different now?"
Jiyeon nodded.
"If I hadn’t known about the line stoppage… I would have thought a one-minute delay in notification would be fine."
Seunghyun added:
"And email is off the table now. No one’s going to be checking email while trying to prevent a line stoppage."
4.2. Concept Notes
4.2.1. Why Direct Questions Narrow Things Down
Jiyeon’s first question — "Would email work for you, or would you prefer app push?" — was not a bad question. It was just already assuming a solution.
What that question presupposes:
-
Notifications are needed (true, but not yet confirmed)
-
Email and app push are the options (are there others?)
-
The person understands the difference between the two (she didn’t)
Weinberg calls questions like this Context-Specific Questions. They start from a specific context — in this case, notification technology — and keep the conversation within that context.
By contrast, Seunghyun’s "Could you walk me through what happens when you assign tasks?" assumes no solution at all. It explores the problem space itself. This is a Context-Free Question[5].
4.2.2. Meta-Questions — The Most Underrated Kind
Seunghyun’s last question — "Is there anything I’ve missed?" — was what surfaced the night shift urgent assignment scenario.
That information could not have come from any other question. There was no reason to ask "do you operate a night shift?" beforehand.
Meta-Questions are powerful for this reason: conversation naturally flows within the territory of what the questioner already knows. A Meta-Question gives the other person permission to cross that boundary.
Ordinary question: I ask from within what I know → they answer Meta-Question: I signal there's territory I don't know → they tell me
"Is there anything I’ve missed?" is the safest and most powerful question available in any situation.
4.2.3. Black Box — Reaching Agreement Before Implementation
What Seunghyun wrote on the whiteboard after the call was the core elements of a Black Box Template.
Agreeing on the Black Box first produces two things.
One: the boundary gets agreed on before debating the implementation. "What goes in and what must come out" gets settled before "how do we build it." Once that is agreed, the implementation method becomes the engineers' call.
Two: edge cases surface naturally. The question "under what conditions does this function not work?" arises naturally from the Black Box boundary. What happens when a team member is offline in an environment where line stoppages occur — discovering edge cases like this during implementation is expensive.
4.2.4. Ask About the Workaround
There is one Process Question that Weinberg particularly emphasizes — keep it in mind.
"What workaround are you using right now?"[6]
People are already doing in action what they cannot express in words. The separate Slack message was the workaround. Knowing exactly what that workaround is reveals the real problem. If there is no workaround — the problem isn’t urgent enough to prioritize.
4.3. Try This Week
The next time you have a requirements conversation, stay conscious of three things.
First. Before you ask a question, check: is it already assuming a solution? "Would you prefer A or B?" presupposes that the answer is one of A or B.
Second. When a conversation stalls, try: "How are you handling this right now?" The workaround will surface.
Third. Before you close the conversation, say at least once: "Is there anything I’ve missed?" The most important thing may come out right there.
Next episode: Before Drawing the Map — How to distinguish symptoms, problems, and root causes, and draw a domain map of the problem space '''
5. Before Drawing the Map
"Navigate without a map, and you’ll arrive somewhere you were never meant to go."
5.1. The Story
Monday afternoon.
Seunghyun, Jiyeon, and the team’s newest member Hyuntae gathered at the whiteboard. It was the first design session since the call with Director Kim.
Jiyeon started drawing on the whiteboard.
"Here’s what I’m thinking — add a status column to the task table, fire an FCM push to the token when an assignment event occurs. For night shift, we add a priority flag."
Hyuntae nodded. "Sounds clean."
Seunghyun studied Jiyeon’s diagram for a while. Something felt off. Not wrong, exactly, but.
Are we solving the right problem?
Seunghyun spoke up.
"Jiyeon — hold on. Let’s get clear on what we’re trying to fix."
"Team members missing tasks. Because there’s no notification."
"Missing tasks because there’s no notification — that’s right. But is that the symptom or the problem?"
Jiyeon put down her pen.
Seunghyun erased the whiteboard and drew three lines.
Symptom: Team members miss tasks Problem: No notification sent after assignment Root Cause: The assignment workflow happens outside the system
"If we build the notification, we solve the 'problem' layer. But the root cause stays. The team lead enters it in the system, then sends a separate Slack message — that double-action is still there."
Hyuntae asked. "So do we need to fix the root cause too?"
"Not necessarily. For a demo next month, the notification might be enough. But it has to be a conscious decision. 'We are fixing the problem layer right now. The root cause comes later' — that has to be a decision, not an accident."
Jiyeon thought for a moment.
"So we might get a similar request again later."
"We will. And we need to be ready for that. Or we need to talk to Minjun about whether to address the root cause now."
Seunghyun erased the whiteboard again and started drawing something different.
"Okay, before that — let’s draw out who does what in this system. Before we write a line of code."
Team Lead ─── Assigns Task ──→ Task
│
│ Status Change
▼
Team Member ←── Notification ── Assigned
│ │
│ Acknowledges │
▼ ▼
Acknowledged In Progress / Done / Overdue
Hyuntae studied it, then said:
"Seunghyun, do we actually need an 'Acknowledged' state? Can’t we just send the notification?"
Jiyeon jumped in.
"But Director Kim said he wants to know if team members saw it. Don’t you remember?"
Hyuntae tilted his head. "Did he? I thought it was just a notification."
Seunghyun watched quietly.
We had the same conversation — and three people understood it differently.
"Someone here is treating 'Assigned' and 'Acknowledged' as the same thing. They’re different. 'Assigned' means the team lead has assigned it. 'Acknowledged' means the team member has seen it. If they’re the same, there’s no need for an acknowledgement feature. If they’re different, there is."
Hyuntae said quietly:
"That changes the DB design."
"Right."
The room went quiet. Jiyeon’s original diagram had already become obsolete.
5.2. Concept Notes
5.2.1. Symptom, Problem, and Root Cause
A doctor who hears a patient say "I have a headache" doesn’t immediately prescribe pain medication. They first ask why it hurts — because the headache may be a symptom.
The same distinction of layers exists in software development.
A Symptom is an observable outcome. "Team members miss tasks." It is where the pain is felt — but fixing the symptom is not the same as fixing the problem.
A Problem is the direct cause of the symptom. "No notification is sent after assignment." Fixing this makes the symptom disappear. But a deeper cause may remain.
A Root Cause is the deeper structure that generates the problem. "The assignment workflow happens outside the system." Fixing this can make multiple symptoms disappear at once.
Which layer to address is a conscious choice that depends on context. For a demo next month, fixing the problem layer is realistic. For a long-term product roadmap, the root cause might be within reach. The issue is — many teams fix the symptom layer without realizing it.
|
"Which layer are we fixing?" is not a technical decision — it is a scope decision. If the team doesn’t explicitly share this choice, they can easily end up believing they’re each solving a different layer. |
5.2.2. The Same Phenomenon Frames Differently, Becomes a Different Problem
The phenomenon of "team members miss tasks" becomes an entirely different problem depending on how you frame it.
Framed as a notification problem — build notifications. Framed as a communication problem — redesign the process. Framed as a visibility problem — build a dashboard. Framed as an accountability problem — build an acknowledgement feature.
A good engineer recognizes that multiple frames are possible, and chooses together with the team which frame to work from.
5.2.3. Domain Model — Drawing the World Before Writing Code
Fairbanks distinguishes three models surrounding software.[7]
The Domain Model is the real-world concepts. People, actions, states, rules, objects. This is not code — it is an understanding of reality.
The Design Model is the structure of the software being built. ERDs, APIs, system diagrams. This is the entry point to the Solution Space.
The Code Model is the actual implementation.
Most engineers skip the Domain Model and go straight to the Design Model. Just as Hyuntae treated "Assigned" and "Acknowledged" as the same thing — when the Domain Model is not aligned within the team, the same meeting produces different designs.
How do you know when the Domain Model has stabilized? When the team is speaking the same vocabulary. When "task" means the same thing to everyone. When "Assigned" and "Acknowledged" point to the same concept in every mind on the team. Until that point, even the most detailed ERD has a shaky foundation.
5.3. Try This Week
Before your next design meeting, ask the team this question.
"Are we fixing a symptom, or are we fixing the problem?"
And before you start designing, invest five minutes to align on domain vocabulary.
"What are the three most important concepts in this system? What states can each of them be in?"
These two questions can prevent hours of rework later.
5.3.1. Layer Selection Determines Scope
The decision of "which layer to fix" naturally determines the scope of what needs to be built.
If you decide to fix the symptom layer — everything related to the root cause layer is not yours to build right now. That comes later.
If you decide to fix the problem layer — that decision defines this sprint’s scope. Other root causes generating other symptoms do not need to be addressed now.
Deeply understanding the Problem Space does not mean you build more. It means you can distinguish what needs to be built now from what doesn’t. And the clearer "what needs to be built now" becomes, the faster you can complete it and deliver it to users first.
Layer selection is not merely a decision about "what to fix." It is also a decision about "what to deliver now."
Next episode: Walking Through the Fog — The choice Cunningham made in front of irresolvable ambiguity '''
6. Walking Through the Fog
"Those who wait for every fog to lift never depart. Some fogs only clear as you walk through them."
6.1. The Story
Wednesday morning.
The team was stuck.
The technical review meeting had been going on for two hours. On the board were three versions of the notification architecture diagram — Jiyeon’s version, Hyuntae’s version, and a combined version.
The sticking point was the same in all three.
"Can we reliably deliver notifications to mobile in the background?"
Jiyeon said:
"`FCM` supports background push. Android handles it natively, and for iOS you just need to configure APNs."
Hyuntae pushed back.
"But this is a factory environment. If the Wi-Fi drops or the power-saving mode is aggressive, it might not get through. I’ve seen that happen."
"That’s not a typical case."
"Is a factory floor a typical environment?"
Seunghyun looked at both of them. They were both saying something true. And neither had certainty.
This is not a problem that talking will solve.
They had read the FCM documentation. They had read Stack Overflow. But there was no source that clearly answered "will push notifications arrive overnight on a factory floor tablet in aggressive power-saving mode?" Some threads said yes, others said no.
Seunghyun erased the board.
"Hold on. Let’s think about what we’re actually doing here."
Both looked at him.
"We’ve been talking for two hours trying to answer this question — but it’s not a question that gets answered by talking. The documentation won’t answer it either. We have to try it."
Hyuntae asked.
"So what do we do?"
"Let’s do the simplest thing. Build a test app. Throwaway. Just the FCM setup and a push-sending function. That’s it. Then test it on a real tablet — power-saving mode on, Wi-Fi throttled. As close to a real factory environment as we can get."
"That’s… probably half a day of work."
"Right. Half a day. Faster and more definitive than two more hours of talking."
Jiyeon asked quietly.
"And if it fails? If the push doesn’t arrive?"
Seunghyun answered.
"That’s also an answer. Then we know FCM alone won’t cut it, and we find another way. Failure isn’t the problem. Continuing to build while staying in the dark — that’s the problem."
Hyuntae stood up.
"I’ll do it. I think I can get it done by this afternoon."
That evening at six.
Hyuntae sent a message on Slack.
Hyuntae: Results are in.
Wi-Fi normal, no power-saving → Received as expected
Weak Wi-Fi, light power-saving → Delayed but received
Heavy power-saving (max battery saver) → Not received
Wi-Fi disconnected + power-saving → Completely unreceived
Conclusion:
FCMalone cannot guarantee night shift urgent cases.
But for regular assignment notifications, it looks okay.
Seunghyun replied:
Seunghyun: Perfect. Now we know.
Night shift urgents need separate handling. Regular uses FCM.
Half a day ended a two-hour argument.
Jiyeon responded:
Jiyeon: But wasn’t this throwaway code?
Hyuntae: Yes. But without it, I think we’d still be in that meeting.
6.2. Concept Notes
6.2.1. Two Kinds of Not Knowing
What the team faced in this story was a situation where two kinds of not knowing were mixed together.
Whether FCM supports background notifications — that can be confirmed by reading documentation. This is Resolvable Ambiguity.
But whether notifications actually arrive on a specific factory-floor device in power-saving mode — that requires trying it. Documentation covers the general case, not this specific environment. This is Essential Ambiguity.
For two hours, the team was treating Essential Ambiguity as if it were Resolvable. They kept asking a question that had no answer through discussion. What Seunghyun did was separate the two.
6.2.2. What "Simplest Thing" Actually Means
Ward Cunningham’s question — "What is the simplest thing that could possibly work?" — is often misunderstood.[8]
It does not mean "build only the minimum."
The precise meaning is:
"What is the smallest action that will make this ambiguity visible?"
The test app Hyuntae built was not production code. He knew it would be thrown away going in. Just FCM configuration, just the push function. The purpose was learning, and half a day was enough.
This is a Spike Solution[9]. An XP practice for exploring specific technical or design ambiguity through throwaway exploratory code. The output is not code — it is learning.
Jiyeon’s question — "But wasn’t this throwaway code?" — had already been answered by Hyuntae. Without it, the two-hour argument would have continued.
6.2.3. Technical Debt — A Misunderstood Concept
When Ward Cunningham first talked about Technical Debt, many people missed what he actually meant.
It was not a metaphor for bad code.
Cunningham’s intent was this:
A more sophisticated design is needed than what we currently understand — but we can’t know that sophistication yet. So we intentionally build something simple, learn through using it, and refactor based on what we’ve learned. The gap between the current design and the ideal design is the "debt."
The key is that it is intentional. Building something while uninformed is incurring debt. Building something carelessly without awareness — that is not debt, that is just bad design.
If the team decided to handle the night shift urgent alert with FCM for now and add separate handling later — they are consciously taking on debt. "We know this is not the perfect solution. We will fix it later." That declaration is what makes debt manageable.
6.2.4. Knowing Through Doing
Philosopher Donald Schön studied expert practitioners and found something they all had in common.[10]
They did not form a perfect plan before acting. They thought while acting, and through the results of their actions, they came to understand problems more deeply. He called this Reflection-in-Action.
Seunghyun stopping the two-hour meeting and starting the test — that was it. Not more discussion, but the smallest action for the fastest learning.
This is not a sign of immaturity. It is a mature epistemology in the face of a complex problem.
6.3. Try This Week
The next time your team is going in circles with the same question, try this.
First. Stop and ask: "Is this a problem we can solve by talking, or something we can only know by doing?"
Second. If it’s Essential Ambiguity, ask: "What is the simplest action that would confirm this? How long would it take?"
Third. If that action is faster than another hour of discussion, just do it.
You are not building something to throw away. You are building something to learn from.
Next episode: I’ve Seen This Problem Before — How to find problems someone has already solved using analogical reasoning '''
7. I’ve Seen This Problem Before
"There are no truly new problems. There are only problems in new packaging."
7.1. The Story
Thursday lunch.
The team was seated at a table in the cafeteria. How to handle night shift urgent notifications was still unresolved. The Spike had confirmed that FCM alone was not enough. So what now?
Jiyeon was stirring her soup and said:
"Night shift urgents… in the end, it’s a message that someone absolutely has to receive. Because if they miss it, the line stops."
Hyuntae said:
"Isn’t that kind of like PagerDuty? On-call notifications."
Seunghyun put down his spoon.
"Right. Wait — let’s think about how PagerDuty solves this."
Jiyeon pulled out her phone.
"PagerDuty… sends an alert, and if there’s no acknowledgement within a certain time, it escalates to the next person. And eventually it even makes a phone call."
Seunghyun nodded.
"That’s the core of it. If there’s no acknowledgement, retry. And with each retry, switch the channel. This is structurally the same as TCP retransmission."
Hyuntae’s eyes went wide.
"`TCP`… like if a packet doesn’t arrive, resend it? That’s the same as notifications?"
"Same structure. The channel is different — but no delivery confirmation means retry; increase the retry interval; if all else fails, switch to a different channel. That logic."
Jiyeon summed it up.
"So for us — send app push, no acknowledgement in five minutes, send again, for night shift urgents also send SMS."
"That’s the right direction. But if there are twelve team members, it’s different from PagerDuty where the escalation target is one person. If our assigned member doesn’t receive it, what do we do? Do we reverse-notify the team lead?"
Hyuntae thought for a moment.
"That’s a Visibility problem. The team lead doesn’t know whether the member received it."
Seunghyun smiled for the first time.
"That’s right, Hyuntae. That’s the second structure in this problem."
Walking out of the cafeteria, Jiyeon said:
"Seunghyun, we’re still building a notification feature, right? Not implementing TCP retransmission."
Seunghyun answered as they walked.
"Obviously. We’re not using TCP itself — we’re using the principle. The logic of 'no confirmation, retry.' The implementation is entirely our own."
That afternoon.
Seunghyun posted links to Kakao Work and Naver Works on Slack.
Seunghyun: Services in a similar position to us. Not the feature list —
Let's look at the Trade-offs they chose.
What did Kakao Work give up to get what it got?
What kind of user is Naver Works optimized for?
Take an hour each, use them, and write 2-3 sentences.
An hour later, Jiyeon posted her findings.
Jiyeon: Kakao Work went all-in on Kakao ecosystem integration.
Notification customization is almost nonexistent.
Easy if you have a Kakao account, awkward without one.
→ Might not fit enterprise-only environments like our client.
>
Naver Works has strong groupware features.
Designed for companies with formal approval hierarchies.
But you get so many notifications you start ignoring them (personal experience).
→ Doesn't solve notification fatigue.
Seunghyun replied:
Seunghyun: Good. So you can see where we can differentiate.
"Only the notifications field workers actually need — delivered reliably."
That's our design direction.
7.2. Concept Notes
7.2.1. Polya’s Question
George Polya wrote the book How to Solve It [11] while studying methods of mathematical problem-solving. One of the most powerful questions he offered was:
"Do you know a related problem?"
This question, which started in mathematics, applies equally to software design.
You do not need to solve every problem from scratch. If the structure of this problem resembles a known problem from elsewhere, you can borrow the logic of that solution. This is analogical reasoning.
That is what Seunghyun did. He connected the notification problem to the logical structure of TCP retransmission. He connected it to PagerDuty’s escalation pattern. The domains were entirely different, but the structure of retry when delivery is not confirmed was the same.
7.2.2. The Three Steps of Analogical Reasoning
Analogical reasoning proceeds in three steps.
First, extract the structure. What remains when you strip away the domain-specific details? Remove "team member," "notification," and "factory" from the problem — and what remains is: "in an environment where receiver state is uncertain, reliably deliver messages of varying urgency and confirm receipt."
Second, search for related problems. Is this structure present in a different domain? TCP retransmission, PagerDuty escalation, hospital triage, air traffic control priority communication.
Third, import the principle back. The principle of the related solution — not the solution itself. Not implementing TCP, but the logic of "retry with a different channel if no confirmation."
7.2.3. Reduction — What Kind of Problem Is This?
Sometimes it is faster to reduce the problem to a problem-type vocabulary rather than searching for a specific analogy.
The moment you say "this is a Visibility problem," the team can reference known solution patterns for Visibility problems — state sharing, real-time synchronization, acknowledgement requests. The trade-offs each pattern carries are already known.
When Hyuntae said "that’s a Visibility problem," it was not a simple observation. That single statement had already opened a range of possible solution directions.
7.2.4. Reading Trade-offs, Not Feature Lists
When researching similar services, simply listing their features is not particularly useful. Knowing that a feature exists tells you nothing about why that design was chosen.
From Cunningham’s perspective, a product that is already live is the result of numerous Spikes and Essential Ambiguity explorations. The evidence of that exploration is embedded in the Trade-offs they selected.
Jiyeon’s observation that Naver Works notifications are so numerous you start ignoring them — that is Trade-off reading. They prioritized completeness over notification frequency. And the result was notification fatigue. We can make a different choice.
7.2.5. How Experience Accumulates
One of the abilities that distinguishes engineers at five or six years from those at three or four is analogical reasoning.
Accumulating experience is not simply having done more things. It is beginning to see already-solved structures in new problems. When you receive a new problem and "I’ve seen this structure somewhere" surfaces automatically — that is how experience becomes a knowledge asset.
This ability can be trained. Start by asking, each time you encounter a problem:
|
Analogical reasoning is "structure recognition," not "memory recall." You don’t need to know |
"What kind of problem is this? Have I seen this structure somewhere?"
7.3. Try This Week
The next time you receive a new requirement, invest five minutes before you start designing.
First. Extract the core structure of the problem in one sentence. Strip out as much domain-specific language as you can.
Second. Ask: "I’ve seen this structure somewhere — where?" Look across other services, other technologies, other domains.
Third. From the related case you find, take the principle — not the solution. "What logic did they use to solve this?"
Those five minutes can reduce the scatter of design directions down the road.
Next episode: Where to Focus Your Energy — How to allocate design effort using a risk-driven approach '''
8. Where to Focus Your Energy
"If you invest equally in everything, you have nothing left for what matters most."
8.1. The Story
Monday morning.
It was design review time. Jiyeon put her architecture diagrams from the previous week on the screen.
Component diagrams, sequence diagrams, ERD, a draft API spec. You could tell at a glance how much effort had gone into it.
Hyuntae said:
"Wow, very detailed."
Jiyeon asked carefully.
"What do you think, Seunghyun?"
Seunghyun looked at the screen for a long time. Something felt off — not wrong, but.
"Jiyeon, how long did this take to put together?"
"…Two days."
"Notification delivery guarantee — the fallback when FCM fails — where is that in here?"
Jiyeon pointed around the diagram.
"Here… ah, that’s not in there yet."
"What about when a night shift urgent goes undelivered and the team lead needs to be notified?"
"That’s not there either…"
"The acknowledgement timeout handling?"
Jiyeon went quiet.
Seunghyun said gently.
"This is well drawn. But the things we need to worry about most are missing. And the component structure — that’s low risk right now. How we partition things can be changed later. But notification delivery guarantees — those are expensive to change after the fact."
Hyuntae jumped in.
"I was wondering about that too. What happens if a push doesn’t go through?"
Seunghyun wrote on the whiteboard in a small list.
Engineering Risk List: 1. Notification not delivered (network/power-saving) → Reliability risk 2. Night shift urgent acknowledgement failure → Reliability risk 3. Handling when no acknowledgement arrives → Reliability risk 4. Performance when team grows from 15 to 150 members → Performance risk 5. Code change scope when adding notification channels → Modifiability risk
"Out of these five, can you see which ones need design energy right now?"
Jiyeon read through them slowly.
"1, 2, 3 are important for the demo too. If the line stops during the demo, it’s over."
"Right."
"4… the demo has 15 people, so isn’t that fine for now?"
"Right. Low risk currently. But when it reaches 150 members, we’ll need to revisit it. No need to do it now."
"5?"
Seunghyun thought for a moment.
"This is in the middle. We’re considering adding SMS as a channel — so some degree of channel abstraction now makes sense. But it doesn’t need to be perfect — just enough that adding SMS later isn’t painful."
Jiyeon was writing notes.
"So out of the two days I spent drawing all that, what we actually need right now is…"
"How to handle 1, 2, 3. And the level of channel abstraction for 5. That’s it. Everything else — later."
Hyuntae asked:
"What about the other diagrams?"
Seunghyun smiled.
"Discard them. For now. Draw them again when they’re needed."
Jiyeon said quietly:
"Two days…"
"Those two days weren’t wasted. You now have the whole structure in your head. But from now on — whenever you draw, ask: what risk does this lower?"
That afternoon.
Jiyeon focused on just three things.
First, retry logic when FCM delivery fails — how many retries, and at what intervals.
Second, the trigger condition for SMS fallback when a night shift urgent flag is present.
Third, an interface abstracting the notification channel — making app push and SMS share the same interface.
At six in the evening, she sent a message on Slack.
Jiyeon: Finished three things today.
Got two days' worth done in one day.
8.2. Concept Notes
8.2.1. Functionality and Quality Attributes Accumulate Differently
Software has two kinds of attributes.
Functionality is "what the system does." Send a notification. Assign a task. You can layer these on with each sprint, and they’re relatively easy to add later.
Quality Attributes are "how well the system does it." Reliability, performance, security, modifiability. These are secured through architectural decisions. Adding them later may require touching the entire system.
Jiyeon’s two-day diagrams showed the functional structure in detail — but did not address the most critical quality attribute: notification delivery reliability. Component structure can be changed later. But failure-handling for notification delivery is expensive if it was never considered from the start.
8.2.2. Risk-Driven Model — Design in Proportion to Risk
George Fairbanks answered the question that software architects are most often asked.[12]
"How much software architecture should you do?"
His answer: in proportion to risk. Design deeply where risk is high; minimize or defer design where risk is low.
This is not laziness. It is focusing on what matters most within limited time.
What Seunghyun did was exactly that. He listed five Engineering Risks and distinguished what was important right now (1, 2, 3), what could wait (4), and what was in the middle (5). As a result, Jiyeon finished two days of work in one day.
8.2.3. Engineering Risk and PM Risk Use Different Tools
There is an important distinction.
Engineering Risk is the possibility of technical failure in system analysis, design, or implementation. Notifications aren’t delivered. Data consistency breaks. A security vulnerability exists. This is resolved through engineering methods — Spikes, prototypes, load tests, architecture reviews.
Project Management Risk is a problem of timeline, team, or prioritization. We won’t finish in a month. The team doesn’t know this technology. This is resolved through PM methods — schedule adjustment, training, scope reduction.
The key: the type of risk and the type of technique must match. Drawing a Gantt chart to address a performance risk is ineffective. Drawing an architecture diagram to address a team scheduling problem is equally ineffective.
8.2.4. The Decision to "Not Do This Now"
The most practical insight from Fairbanks’s Risk-Driven Model is this.
Low-risk things don’t need to be designed right now. And that is not "never do it" — it is "revisit when the risk grows."
Deeply designing the scalability of a system that currently has 15 users is waste. When signals appear that it might reach 150, that is the appropriate time to invest.
The reason this judgment is hard is that engineers have an instinct to design perfectly. The Risk-Driven Model gives that instinct a criterion: "What risk does this design reduce?"
8.3. Try This Week
Before your next design session, ask this question first.
"Where in this system is the failure most likely?"
Once you have an answer — focus your design energy there. Leave everything else simple for now, and revisit when the risk grows.
When someone brings a long diagram to a design meeting, ask:
"What risk does this diagram reduce?"
If there is an answer, it’s good design. If there isn’t — it may be time to reconsider whether it’s needed right now.
Next episode: Seunghyun’s Map — Verifying the solution against the original problem, and integrating everything learned across eight sessions '''
9. Seunghyun’s Map
"A map is not the territory. But a good map tells you simultaneously where you need to go — and where you don’t."
9.1. The Story
The night before the demo.
Seunghyun stood alone in front of the whiteboard.
He looked back over the past month. It had started with a single sentence from Minjun — the TeamOrder notification feature. He remembered thinking about WebSocket within fifteen seconds of first hearing it.
What had been built now was three things.
FCM app push and acknowledgement. Night shift urgent SMS channel. Notification channel interface.
That was everything.
Compared to everything that had come to mind at the beginning, it was far less. No real-time dashboard. No notification history page. No Kafka. The Kafka that Jiyeon had wanted to try was nowhere to be found.
Is this right?
Seunghyun began writing on the whiteboard.
What we understood from Minjun's words at the start: "Team members miss tasks and the line stops" "Team lead assigns tasks then has to separately message on Slack" "Field usage — tablet/phone. Night shift exists" What we built: FCM + acknowledgement → Eliminate "separate messages," reduce "misses" SMS fallback → Cover night shift urgent cases Channel abstraction → Minimize changes when adding channels later What we did NOT build and why: Notification history → Team lead wanted "did they see it now," not a past log Real-time dashboard → Outside demo scope, low risk Kafka → Excessive infrastructure for a 15-person team, zero risk now Auto reports → Not in requirements. Not a Function in FAC
After writing, Seunghyun stared at it for a long time.
I can see why each of the things we didn’t build was okay not to build.
Not building notification history was not laziness. It was because — from the Context-Free Questions in Session 3, what the team lead wanted was "did the team member see it" — current receipt status, not a real-time history of the past.
Not having Kafka was not a technology choice. It was because — the risk check in Session 7 had confirmed there was no risk for a 15-person team right now.
Not having auto reports was because — when FAC was filled in during Session 2, it was never in the Functions list.
Because we understood the problem, we could see what didn’t need to be built.
And because there was so much that didn’t need to be built — we could focus on the three things that genuinely mattered. They could be completed within a month.
Seunghyun put down the marker.
Tomorrow at the demo, he would show the team lead these three things. Only three. But Seunghyun knew those three things mapped precisely to what the team lead had said — "I want to stop the line stoppages."
The day after the demo.
A Slack message came from Minjun.
Minjun: Oh wow. Team lead said they want to deploy this right away.
"It has exactly what we need and nothing more," they said.
Jiyeon replied:
Jiyeon: Really?? I was worried there weren’t enough features.
Seunghyun replied:
Seunghyun: "Exactly what we need" is a compliment.
It means we knew what was needed.
Hyuntae posted last:
Hyuntae: But when do we get to use Kafka?
9.2. Concept Notes
9.2.1. When You Understand the Problem, the Solution Becomes Simpler
This is the single proposition that runs through the entire workshop.
|
When you fully explore the Problem Space, the Solution Space does not become wider — it becomes narrower. You don’t see more things to build. You see the things you don’t need to build. |
At first, this may seem counterintuitive. Deeply understanding a problem takes more time, and it seems like it would delay entry into the Solution Space.
But in practice, the opposite is true.
When you fully explore the Problem Space, three things become clear.
First, what must essentially be achieved becomes visible. What the team lead wanted was "confirmation that team members received their tasks." When that is clear — everything that is not that becomes non-essential.
Second, what can wait becomes visible. Things with low risk, things users don’t need right this moment. Not building these things now is not laziness — it is judgment.
Third, what does not need to be built at all becomes identifiable. Things that were never in FAC’s Functions list. Concepts that don’t appear in the Domain Model. Things that weren’t failure causes in the Pre-mortem. When these become clear, scope naturally contracts.
When these three things are visible — what needs to be built becomes simple. And simple things can be built and delivered to users first.
The reason TeamOrder’s three features could reach a demo in one month was not that the rest was lazily skipped. It was that understanding the problem deeply revealed that the rest didn’t need to be built.
9.2.2. Problem-Solution Fit
While building a solution — or after — there is something that must be confirmed.
Are the problem I defined and the solution I built actually connected?
This is Problem-Solution Fit.
The way to check is simple. What would the user have done without this solution? If the workaround is still there — you missed the core. If the problem can still occur even with this solution — something essential is missing.
What Seunghyun did when he wrote "what we built" and "what we understood from the original problem" side by side and compared them — that was exactly this check.
9.2.3. Pre-mortem — Finding Weaknesses Without Optimism Bias
Pre-mortem is a technique proposed by Gary Klein.[13] It asks: "Assume we failed six months from now — what would the reason be?"
Where an ordinary review looks for "why this will succeed," a Pre-mortem looks for "why this will fail." Without the optimism bias, weaknesses surface more naturally.
The failure reasons that come out of a Pre-mortem are — mostly things that should have been discovered in the Problem Space. A Constraint that wasn’t known (Session 2). An Essential Ambiguity that was never Spiked (Session 5). A risk that was underestimated (Session 7). So a Pre-mortem serves as a final check — and as a way to confirm whether the tools from this workshop actually worked.
9.3. What to Take from This Session
The workshop is ending.
You take the tools with you. FAC, Context-Free Questions, Black Box, layer analysis, Domain Model, Resolvable vs Essential, Spike, analogical reasoning, Risk-Driven design.
But you don’t need to pull out all of these tools every time.
There is one habit that all these tools point toward.
When you receive a requirement — before crossing into the Solution Space, pause just once and ask:
"What do I know right now? And what do I still not know?"
That question opens the Problem Space. That exploration simplifies the solution. That simplicity enables faster delivery to users.
Epilogue: The Person Who Learned to Draw Maps — TeamOrder six months later, and what this workshop left behind '''
10. The Person Who Learned to Draw Maps
"A teacher shows you the path. A mentor teaches you how to find one."
10.1. The Story
TeamOrder’s notification feature moved beyond the demo and made it into production.
Three months in, the expected happened. Two team leads asked to reduce their notification settings — too many were coming through. The "notification fatigue" failure scenario that had appeared in the Pre-mortem had become real. Because the team had anticipated it, they added priority filtering in one week.
Six months in, users had grown to 150. It was time to pull out the scalability design that had been set aside in Session 7 as "low risk for now." Because the team had expected this too, they scheduled a review without alarm.
One day Jiyeon posted on Slack:
Jiyeon: I noticed lately — I react differently to requirements than I used to.
I used to immediately think about DB design.
Now "what problem is this?" comes first.
Hyuntae replied:
Hyuntae: Same here. But doesn’t that make you slower?
What do you think, Seunghyun?
Seunghyun replied:
Seunghyun: It feels slower at first. But the rework has decreased, hasn’t it?
Not doing rework is ultimately faster.
Minjun jumped in later:
Minjun: Hey, now when I bring requirements,
I find myself thinking about "why this is needed" first.
Feels like I picked something up without realizing it.
10.2. Closing — To the Reader
This workshop did not teach technology.
FAC, Context-Free Questions, Black Box, Domain Model, Spike, analogical reasoning, Risk-Driven — these are all tools. Tools eventually become less useful. Better tools come along.
But what lies behind the tools remains.
The willingness to understand problems first. The patience to explore ambiguity rather than be unsettled by it. The ability to identify what not to build. And — the belief that moving in the right direction is ultimately faster than moving quickly.
This does not emerge automatically from three or four years of experience. It requires deliberate practice. This workshop was the beginning of that practice.
10.3. What Was Learned in This Workshop
A final review of the tools and concepts covered across eight sessions.
Problem Space Exploration
| Session | Tool | Core Question |
|---|---|---|
1 |
Einstellung Effect, Presumptive Architecture awareness |
Am I understanding the problem, or recognizing a pattern? |
2 |
FAC (Functions / Attributes / Constraints) |
Have I uncovered all three layers of the requirement? |
3 |
Context-Free Questions, Black Box Test |
Did I explore without presupposing a solution? |
4 |
Symptom-Problem-Root Cause layers, Domain Model |
Did I consciously choose which layer to solve? |
Handling Ambiguity
| Session | Tool | Core Question |
|---|---|---|
5 |
Resolvable vs Essential diagnosis, Spike |
Is this ambiguity resolvable through asking, or only knowable through doing? |
Solution Space Exploration
| Session | Tool | Core Question |
|---|---|---|
6 |
Analogical reasoning, problem-type reduction, Trade-off research |
Have I seen this structure somewhere before? |
7 |
Engineering Risk identification, Quality Attributes, Risk-Driven design |
Where should I focus my design energy? |
8 |
Problem-Solution Fit, Pre-mortem |
Is the problem I defined actually connected to the solution I built? |
10.4. So What Changes?
Before this workshop:
Requirement received
↓ (15 seconds)
Enter Solution Space
↓
Design + Build
↓
"This isn't what I asked for"
↓
Rework
After this workshop:
Requirement received
↓
"What do I know right now?"
↓
Problem Space exploration (FAC, Context-Free Q, Domain Model...)
↓
Identify core + what can wait + what doesn't need to be built
↓
Build with focus
↓
Early delivery → Feedback → Validated expansion
Reducing rework is not the goal. Reducing rework is a byproduct. The goal — is getting users what they need, sooner.
If Seunghyun’s learning could be written in a single line:
"Spending more time on the problem is how you build the solution faster."
If that line comes to mind the next time you receive a requirement — this workshop succeeded.