عرض عملي: التخطيط قبل الكود على مشكلة جديدة
في هذا الدرس 11 موضوعات
هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.
Lesson Overview
You have learned the four parts of the routine one at a time: understanding a problem, decomposing it, writing pseudocode, tracing by hand, and listing edge cases. In this lesson you do them together on a problem you have not seen before, from the first read to the final check.
Follow along on paper, and try each step yourself before reading how it is done. The map analogy applies one last time: plan the whole route, check the risky roads, and only then start the engine.
Why this matters: this is the routine for the lab and the assessment, and for a ticket at work. The plan is graded as much as the code, because a clear plan is evidence of clear thinking.
The previous lesson, "Thinking in edge cases", gave you the checklist.
Learning Objectives
By the end of this lesson you will be able to:
- Apply the full routine (restate, plan, edge cases, trace, code, check) to an unseen problem.
- Write a plan that matches the code, line by line.
- Use the edge-case list to find a bug before a user does.
- Decide, record, and test a decision about unusual input.
- Check that every listed edge case is handled by the finished code.
Written Explanation
The routine
Use these steps, in order, on every unseen problem.
- Read and restate. Say the problem in your own words and list inputs, outputs, and constraints. Ask your questions and record assumptions.
- Plan. Decompose it and write pseudocode (or a flowchart).
- List edge cases with the expected result for each, using the checklist.
- Trace. Run one example through the plan with a variable table.
- Code. Only now write the Java, line by line from the plan.
- Check. Run every line of the edge-case list. Make sure the plan and the code still match.
If a later step reveals a flaw, go back and fix the plan, then the code. The demo below shows this.
Examples
The three examples in this lesson are three stages of one demo.
Example 1: read, restate, plan, list the edge cases (simple)
The problem: "Count how many words in a sentence are longer than 4 letters."
Step 1: restate. Given a sentence, count the words that have more than four letters. Inputs, outputs, and constraints:
Problem (my words): Count the words of a text that have more than 4 letters.
Input: String text
Output: int count
Constraints: What separates words? What is a "letter"? Empty text?
Questions/decisions: Words are separated by one or more spaces.
Length 5 or more counts (more than 4).
Punctuation is not a letter (decision pending, see edge cases).
Empty text or only spaces -> 0.
Example by hand: "plan before you write code" -> before (6), write (5) -> 2Step 2: plan. Decomposition:
1. Cut the text into words.
2. Start a counter at 0.
3. For each word, if it has more than 4 letters, add 1.
4. Return the counter.Pseudocode:
SET words = the words of text
SET count = 0
FOR EACH word IN words
IF length of word > 4
SET count = count + 1
RETURN countStep 3: edge cases. Using the checklist:
| Input | Expected | Why |
|---|---|---|
plan before you write code | 2 | Happy path |
| empty text | 0 | Empty |
| only spaces | 0 | Empty after trimming |
hello brave world | 3 | Extra spaces at the ends and between words |
hello | 1 | One word |
four fives | 1 | Exactly 4 letters (not counted) and exactly 5 (counted): the boundary |
Hi, there! | 1 | Punctuation |
Wait four! Great, stuff | 2 | Punctuation on words at the boundary |
The last two rows are the interesting ones. The last expects 2: Great and stuff have five letters each, while four! has four letters but five characters.
Example 2: trace, code, and find the bug (practical)
Step 4: trace. Trace the plan on the hand example plan before you write code:
| step | word | length | > 4? | count |
|---|---|---|---|---|
| start | - | - | - | 0 |
| 1 | plan | 4 | false | 0 |
| 2 | before | 6 | true | 1 |
| 3 | you | 3 | false | 1 |
| 4 | write | 5 | true | 2 |
| 5 | code | 4 | false | 2 |
The plan gives 2, as expected, and a word of length exactly 4 is not counted.
Step 5: code the first idea. Translating the plan directly gives:
static int countLongWordsV1(String text) {
String[] words = text.split(" ");
int count = 0;
for (String w : words) {
if (w.length() > 4) count++;
}
return count;
}Step 6: run the list. Running version 1 over the inputs gave this:
| Input | Expected | Version 1 |
|---|---|---|
plan before you write code | 2 | 2 |
hello brave world | 3 | 3 |
Wait four! Great, stuff | 2 | 3 |
Two surprises. First, the extra spaces did not cause a wrong answer. With split(" "), extra spaces produce empty pieces, but an empty piece has length 0, which is never above 4, so the count is unaffected. Before you "fix" something, check what it really does. (If the problem had been "count the words", the empty pieces would have broken it: " hello brave world " gives 8 pieces with split(" ") but 3 real words.)
Second, the last row is wrong: version 1 returned 3 instead of 2. The word four! has four letters but five characters, so counting length counts the punctuation. The edge-case list found this before any user did; a happy-path test would have passed.
Example 3: fix the plan, then the code, then check (realistic)
Go back to the plan, because the plan said "length of word", and length is not what we mean. We need a decision and a plan change.
Decision (recorded): a word's size is the number of letters in it; digits, punctuation, and other symbols do not count.
Updated pseudocode:
SET words = the words of trimmed text, split on runs of spaces
SET count = 0
FOR EACH word IN words
IF the number of letters in word > 4
SET count = count + 1
RETURN countThat adds a small step, "count the letters of a word", which we make its own method. To find out whether a character is a letter we use Character.isLetter, a library method that this course has not covered yet, so treat it as a preview: it takes one char and answers true or false. For splitting, we also use trim() and split("\\s+"). The pattern \\s+ is a regular expression meaning "one or more whitespace characters", another preview topic: for now, read it as "split on any run of spaces". Trimming first matters because a text that starts with spaces would otherwise give an empty first piece.
static int lettersIn(String w) {
int n = 0;
for (int i = 0; i < w.length(); i++) {
if (Character.isLetter(w.charAt(i))) n++;
}
return n;
}
static int countLongWords(String text) {
String[] words = text.trim().split("\\s+");
int count = 0;
for (String w : words) {
if (lettersIn(w) > 4) count++;
}
return count;
}Run the whole list again. Real results:
| Input | Expected | Result |
|---|---|---|
Wait four! Great, stuff | 2 | 2 |
| empty text | 0 | 0 |
| only spaces | 0 | 0 |
Hi, there! | 1 | 1 |
I also ran the other rows of the list on this version and they match their expected column (for example hello gives 1 and four fives gives 1). The plan and code now match line for line: SET words is the trim and split line, the loop is the loop, number of letters in word is lettersIn, and the counter is count.
One more detail the list made us look at: for empty text, "".trim().split("\\s+") gives an array holding one empty string, not an empty array, so the loop runs once with a zero-letter word and the count stays 0. (For a problem that counts words, empty text would wrongly give 1 and need an if.)
Backend Insight
A ticket arrives ("count how many items in an order are expensive"). You restate it and ask the questions (what is expensive? is the limit included?), write a short plan, agree on edge cases such as an empty order, and only then code and run the cases. Reviewers read the plan and edge cases first, because they show quickly whether you understood the task.
Notice how the bug was found: not by clever debugging, but by a list written before the code.
Common Mistakes
Mistake 1: Coding from the first idea
- Incorrect: typing
split(" ")and a loop as soon as the problem is read. - Correct: restating, planning, listing edge cases, and tracing first.
The demo's first version was a reasonable first idea. It still hid a bug that only the list could find.
Mistake 2: "Fixing" a problem you have not confirmed
Spaces looked tricky, but here they were not the failing case. Check what the code does before changing it.
Mistake 3: Fixing only the code
When the list reveals a flaw, update the plan too. If the plan still says "length of word" while the code counts letters, they no longer match, and the next reader is misled.
After any change, rerun the whole list: a fix can break a row that passed before.
Exercises
Try each exercise yourself before opening the solutions. Do the full routine where an exercise asks for it.
Level A: Foundation
A1. List the six steps of the routine in order.
أظهر الحل A1
A1. Read and restate; plan (decompose, pseudocode or flowchart); list edge cases; trace an example; code; check the whole list and that the plan matches the code.
A2. Restate "count the words in a text" with input, output, and constraints.
أظهر الحل A2
A2. Problem: given a text, say how many words it has. Input: a String. Output: an int. Constraints: what separates words (one or more spaces?), is punctuation part of a word, and what is the answer for empty text (0)?
A3. List at least four edge cases for "count the words in a text", with expected results.
أظهر الحل A3
A3. Empty text gives 0; only spaces gives 0; one word gives 1; "one two" gives 2; "one two" (extra spaces) gives 2; " one " gives 1. (A plain split on empty text gives one piece, so empty text needs a special check.)
Level B: Application
B1. Run the routine for "is an int array a palindrome (reads the same forwards and backwards)?". Give the restatement, pseudocode, and an edge-case list of at least five rows, then write and run the Java method.
أظهر الحل B1
B1.
Problem (my words): Does the array read the same from both ends?
Input: int[] a
Output: boolean
Constraints: Empty array? (decision: yes, a palindrome)FOR i FROM 0 UP TO (length / 2) - 1
IF a[i] differs from a[length - 1 - i]
RETURN false
RETURN trueEdge cases: {} true; {7} true; {4, 4} true; {1, 2, 1} true (middle element is not compared); {1, 2, 3, 1} false. Java:
static boolean isPalin(int[] a) {
for (int i = 0; i < a.length / 2; i++) {
if (a[i] != a[a.length - 1 - i]) return false;
}
return true;
}Running the five cases in the order above printed true true true false true for {}, {7}, {1,2,1}, {1,2,3,1}, {4,4}, matching the expectations.
B2. Trace the final countLongWords on " a bigger test ": give the pieces after trim() and split("\\s+"), then the count.
أظهر الحل B2
B2. After trim() the text is "a bigger test"; split("\\s+") gives a, bigger, test.
a has 1 letter (count stays 0), bigger has 6 (count 1), test has 4 (count stays 1). The result is 1, which the program also printed.
B3. A plan says "IF the word has more than 4 letters, add 1". The code says if (lettersIn(w) >= 4) count++;. Which edge-case row would reveal the difference, and what would the code return for it?
أظهر الحل B3
B3. The row four fives (exactly 4 letters and exactly 5 letters). The plan says 4 letters is not counted, but >= 4 counts it, so the code returns 2 instead of the expected 1. The boundary row exposes it.
Level C: Challenge
C1. Run the full routine for "return the length of the longest run of equal neighbouring values in an int array" (for {1, 1, 2, 2, 2, 3} the answer is 3). Decide what happens for an empty array. Include a trace, an edge-case list of at least five rows, the Java method, and the results of running your list.
أظهر الحل C1
C1. Restatement: input int[], output the length of the longest block of equal neighbours; decision: an empty array gives 0.
IF array is empty RETURN 0
SET best = 1, run = 1
FOR i FROM 1 TO length - 1
IF a[i] equals a[i - 1]
SET run = run + 1
ELSE
SET run = 1
IF run > best
SET best = run
RETURN bestTrace on {1, 1, 2, 2, 2, 3}: run goes 1, 2, 1, 2, 3, 1 and best ends at 3. Edge cases: {} 0, {5} 1, {1, 1, 2, 2, 2, 3} 3, {2, 2, 2} 3 (the whole array), {1, 2, 3} 1 (no repeats). Java:
static int longestRun(int[] a) {
if (a.length == 0) return 0;
int best = 1, run = 1;
for (int i = 1; i < a.length; i++) {
if (a[i] == a[i - 1]) run++; else run = 1;
if (run > best) best = run;
}
return best;
}Running the five cases in that order printed 0 1 3 3 1, matching. The run that ends at the last element is counted because best is updated inside the loop on every pass.
Mini Challenge
Solve this unseen problem with the full routine and hand in the plan with the code: "Given a text, count how many words start with a capital letter."
- Restate it, with inputs, outputs, constraints, and your decisions (is a word that starts with a digit counted? what about punctuation at the front?).
- Write the pseudocode.
- Write an edge-case list of at least eight rows with expected results.
- Trace one example with a variable table.
- Write the Java and run every row. If a row fails, say whether the plan or the code was wrong, and fix both.
Check your work: plan, list, and trace came before the code; every row was run; plan and code match. (Hint: Character.isUpperCase, a preview method, tests one character.)
Summary & Next Lesson
Key takeaways
- The routine is: read and restate, plan, list edge cases, trace, code, check.
- The edge-case list is what finds bugs the happy path hides. Write it before the code.
- Check what the code actually does before "fixing" a suspicion.
- When a flaw appears, update the plan first and the code second. Rerun the whole list after any change.
- The plan and the code must match, and the plan is graded as much as the code.
Next lesson
This was the last lesson of the module. The module's lab, "Plan before code", has you apply the routine to three unseen problems and submit the plan with the code. The next module, BEG-017, opens with "What an algorithm is".
Self-check
- In what order do the six steps of the routine come?
- In the demo, which step found the real bug?
- Why did the extra spaces not break the long-word count?
- What should you do when the edge-case list shows a flaw in your plan?
- Why run the whole list again after a fix?
أظهر الإجابات
- Restate, plan, edge cases, trace, code, check.
- Running the edge-case list (the row with punctuation), which was written before the code.
- Extra spaces create empty pieces, which have length 0 and are never longer than 4, so they did not change the count.
- Fix the plan first, then the code, so that they still match.
- A fix can break a row that passed before.
References
- Oracle, Java SE 21 API:
String. Supportstrim()(removes leading and trailing characters up to the space character) andsplit(a positive-width match at the start of the text gives an empty leading piece, which is why we trim first). - Oracle, Java SE 21 API:
Character. SupportsisLetter(char), which answers whether a character is a letter.isUpperCasein the Mini Challenge hint was not checked against the page. - The Java methods in this lesson were compiled and run with JDK 21; the quoted results are from those runs. The explanation of
\\s+as "one or more whitespace characters" is standard regular-expression meaning that I did not verify against a primary source here; it is flagged in the text as a preview topic.
التطبيق
طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.
تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.