Help improve SovranCode?

Google Analytics can measure anonymous usage after you choose Allow. Essential account and progress features work either way.

SovranCode
Learn
Learn on SovranCodeCourses5 free learning paths→ExercisesPractice with live challenges→GuidesDirect answers for developers→E-booksFocused field guides→
Build
Build on SovranCodeProjectsPortfolio-ready builds→TemplatesSovranCode team marketplace→Developer toolsFast browser utilities→
Connect
Connect on SovranCodeForumQuestions and discussions→JournalPractical development notes→AboutWhy SovranCode exists→PricingFree, Plus, and Student Plus→
Services
SearchCreate account
Explore SovranCodeLearn, practice, and build.
LearnCourses5 free learning paths→ExercisesPractice with live challenges→GuidesDirect answers for developers→E-booksFocused field guides→
BuildProjectsPortfolio-ready builds→TemplatesSovranCode team marketplace→Developer toolsFast browser utilities→
ConnectForumQuestions and discussions→JournalPractical development notes→AboutWhy SovranCode exists→PricingFree, Plus, and Student Plus→
Search
All articlesTHE SOVRANCODE JOURNAL / LEARNING
Learning 10 min read

Design a practice loop that actually teaches coding

THE SHORT VERSION

Build a practice session around one cart-total bug: predict its output, inspect the failure, compare a solution, and try a second problem later.

SovranCode Learning LabAugust 4, 2026
Updated September 14, 2026
ONE IDEA, FIVE MOVES02 — PRACTICE
01Readone idea
02Predictbefore Run
03Editone thing
04Explainthe mismatch
05Returnwithout notes
THE OUTPUT ISN'T THE LESSON“I expected 27. I got 15. I forgot quantity.”That sentence tells you what to practice next.
A short loop is complete when you can explain the result, not when the test turns green.
Jump to a section 8 sections
Start with the mistake the learner is likely to makeGive the session a beginning and an endWork the cart problem all the way throughWrite feedback that names the failed assumptionIf you write lessons, design the check firstTomorrow, change the shape of the problemWhen you get stuck, inspect one iterationKeep a record small enough to reread

Here's a familiar scene: you finish a JavaScript lesson on reduce, understand every line, and then your own cart total says 15 when the receipt should say 27. That gap is the lesson. This article builds a complete practice session around the bug—what to ask before running code, which test makes the mistake visible, what feedback should say, and how to check the idea again without the answer open. The solution is included. The goal is to leave with a method you can use on the next function, not another paragraph telling you to ‘practice more.’

01 / 08

Start with the mistake the learner is likely to make

The first version of our cart function adds item.price for every line. It looks plausible because the method, callback, and initial value are all in the right places. Give it one notebook and it passes. Give it two notebooks on one line and it fails. The learner has to notice that a line item carries both price and quantity. That is a much clearer target than “learn arrays.”

THE FIRST FAILURE

One basket, two totals

Input
2 notebooks × 12; 1 pen × 3
Expected
27
Starter
15
Missing
The quantity of each line item

Before showing any code, ask for a prediction: two notebooks at 12 each, one pen at 3. The expected total is 27. Then ask what a function that simply adds 12 and 3 would return. The learner now has two numbers—27 and 15—and a reason to inspect the difference. A failed check is informative when its input exposes exactly one assumption.

The underlying learning move is retrieval: try to bring the rule to mind before rereading it. A study by Karpicke and Roediger found an advantage for repeated retrieval over restudy in a vocabulary task. It did not test JavaScript functions. Our use of prediction in a coding lesson is a practical application of that idea, not a claim that one paper validates every detail of this exercise.

02 / 08

Give the session a beginning and an end

This can fit into twenty minutes because the task is narrow. Give five minutes to reading the reducer and predicting the two outputs. Spend ten minutes changing the expression and running the cases. Use the final minutes to write a one-sentence explanation and a question for a later session. If it takes longer, that is fine; the structure exists so you know what success looks like, not so a timer can grade you.

SESSION CARD

Run the cart-total loop

Keep the answer visible after the attempt; no locked solution is needed.

  1. 01Write 27 on paper before pressing Run.
  2. 02Predict what the starter function returns and name the missing property.
  3. 03Edit only the reducer expression, then run a multi-quantity case.
  4. 04Run an empty-cart case and explain why it returns 0.
  5. 05Close the answer; leave yourself one question for tomorrow.

A course often puts reading, editing, and testing in separate places. That adds friction. If you are learning from SovranCode's JavaScript course, keep a small scratch file or browser console beside the lesson. Copy the minimum code needed to test the idea. Do not rebuild the full shopping cart UI just to learn how one reducer handles quantity.

03 / 08

Work the cart problem all the way through

Read the left-hand code first. The input is two notebooks at 12 each and one pen at 3. Write down the correct total, then trace the reducer by hand: sum starts at 0, adds 12, then adds 3. The function returns 15. Only after you can explain that trace should you compare it with the solution. We show the answer immediately because the explanation is part of the lesson; a hidden solution would not make the practice more honest.

TRY IT, THEN COMPARE

Repair the cart total

Predict the result for two notebooks and one pen. Change the reducer so quantity matters, then check what it returns for an empty cart.

STARTING POINT
function total(items) {
  return items.reduce(
    (sum, item) => sum + item.price,
    0
  );
}
ONE SOLUTION
function total(items) {
  return items.reduce(
    (sum, item) => sum + item.price * item.quantity,
    0
  );
}

total([
  { price: 12, quantity: 2 },
  { price: 3, quantity: 1 }
]); // 27
total([]); // 0

Why it works. The callback adds each line's price multiplied by its quantity. The initial accumulator of 0 means an empty array has a defined total instead of throwing or returning an undefined value. A next exercise could decide how to reject a negative quantity; that is a separate business rule.

Do not stop at the displayed // 27 comment. Run assertions so the explanation has a consequence. The first case catches the missing multiplication; the second checks the initial value; the third makes sure zero quantity contributes nothing. These are three different questions, not three copies of the happy path.

WORKED EXAMPLEThree checks with three jobsJavaScript
const basket = [
  { price: 12, quantity: 2 },
  { price: 3, quantity: 1 }
];

console.assert(total(basket) === 27, "quantity matters");
console.assert(total([]) === 0, "empty cart starts at zero");
console.assert(
  total([{ price: 12, quantity: 0 }]) === 0,
  "zero quantity adds nothing"
);

console.assert is enough for this small lesson. In a real codebase, put equivalent cases in its test runner. For money, use integer cents or a suitable decimal representation; this example uses whole numbers to isolate the reducer decision.

If you remove the initial 0 from reduce, the empty-cart case throws instead of returning a total. If you add quantity only to the first line item, the mixed basket fails. If you let negative quantities through, the arithmetic still runs but the business rule may be wrong. That last question belongs to a separate validation exercise. A practice task is strongest when it is explicit about what it is and is not teaching.

04 / 08

Write feedback that names the failed assumption

A learner who sees “Wrong answer” has to guess whether the syntax, input, loop, or expected result is wrong. For this task, the feedback can be exact: “For two notebooks at 12 and one pen at 3, expected 27; your function returned 15.” That sentence tells them the test input and the gap. It does not paste the solution into the error message.

Then give a useful hint in two steps. First: “Which property on a basket item says how many were bought?” If that is still too broad: “Trace the expression added to sum for the notebook line.” A hint should reduce the search area. The worked answer should remain available and explain why the change works; people who are stuck need a way forward, not a gate that protects an answer from them. That is how we want SovranCode exercises to treat questions, solutions, and explanations.

After success, change the data. Try three pens at 3 each. A learner who hardcoded 27 for the first basket will get 27 again; the new case should be 9. Now the check is about a general rule. Passing one familiar example is encouraging. Passing a changed input and being able to predict the result is stronger evidence that the code follows the intended relationship.

There is a limit to how much feedback belongs in one exercise. A negative price, floating-point currency, inventory limits, tax, and discounts are all real shopping-cart concerns. They are not the same lesson as multiplying price by quantity. Put a short note beside the answer about those boundaries, then build separate tasks for the ones learners need next. Otherwise one failed check can have five possible causes and the practice loop loses its focus.

05 / 08

If you write lessons, design the check first

The same cart example can guide someone building a course. Start with the behavior you want to observe: a learner can calculate line totals from unit price and quantity. Write the smallest input that distinguishes that rule from the common wrong one. One notebook at 12 will not do it; the broken function also returns 12. Two notebooks on one line reveal the mistake immediately. Only then write the prompt and starter code.

Keep the question specific: “This function returns 15 for a basket worth 27. Change it to account for quantity. What should it return for an empty basket?” A good reference solution shows the changed expression and explains the initial zero. The hint points at quantity, while the feedback reports the exact basket and observed total. Those pieces serve different moments in the learner's work; none should be replaced with an unexplained pass/fail badge.

Finally, test the exercise itself. Can the obvious wrong implementation pass every visible check? Does the solution handle an empty list? Does the explanation say why the code works for a new basket, not merely repeat the line of code? Let another person attempt it without your narration. If they solve a different problem than you intended, the prompt needs repair before the learner does.

06 / 08

Tomorrow, change the shape of the problem

If you rerun the cart code with the answer still beside it, you are mostly checking recognition. Tomorrow, use a different data shape and a different loop. A workshop sells seats; each booking stores seats and pricePerSeat. Two seats at 10 and one seat at 15 should produce 35. The prompt below is deliberately familiar without being a copy-paste task. Try the left side before reading the solution on the right.

TRY IT, THEN COMPARE

Transfer the rule to workshop bookings

The starter code ignores the number of seats. Repair it with a `for...of` loop. What should an empty bookings array return?

STARTING POINT
function revenue(bookings) {
  let total = 0;
  for (const booking of bookings) {
    total += booking.pricePerSeat;
  }
  return total;
}
ONE SOLUTION
function revenue(bookings) {
  let total = 0;
  for (const booking of bookings) {
    total += booking.seats * booking.pricePerSeat;
  }
  return total;
}

revenue([
  { seats: 2, pricePerSeat: 10 },
  { seats: 1, pricePerSeat: 15 }
]); // 35
revenue([]); // 0

Why it works. The loop syntax changed, but the business relationship did not: each row contributes count times unit price. Initializing `total` to 0 gives the empty list a sensible result. If you can explain that without mentioning `reduce`, you have learned more than one method call.

There is no universal return interval. The next day is a convenient first check; a later week is another. What matters is whether the rule survives without the worked answer on screen. Keep a small note such as “I remembered multiplication but forgot the empty case.” That tells you what to repair. “I am bad at JavaScript” gives you nothing to test.

07 / 08

When you get stuck, inspect one iteration

The full basket has only two lines. Put a console.log({ sum, item }) at the start of the reducer callback and run it once. On the notebook line you will see sum: 0 and an item with price: 12, quantity: 2. The next sum becomes 12. That is the exact step to question. You do not need a debugger tour of the whole application to find it.

WORKED EXAMPLEInspect the first wrong stepJavaScript
function total(items) {
  return items.reduce((sum, item) => {
    console.log({ sum, item });
    return sum + item.price;
  }, 0);
}

total([{ price: 12, quantity: 2 }]);
// Logs: { sum: 0, item: { price: 12, quantity: 2 } }
// Returns: 12. Expected: 24.

For a focused debugging pass, use one line item. Once the bug is clear, remove the log and rerun the full set of checks.

If you still need help, ask with that tiny case: “For one item at 12 with quantity 2, I expect 24 and get 12. I traced the callback; it adds price to sum. What should I check next?” Another learner, a mentor, or an assistant can answer that without reconstructing your whole project. The SovranCode community is more useful when a question includes the input, expectation, actual result, and the step you already inspected.

08 / 08

Keep a record small enough to reread

A useful study log can fit in four lines. You are not documenting the whole session; you are leaving a clue for your future self. Write the prediction, the observed result, the rule you repaired, and one question for the next attempt. It should take less time to read than the tutorial you would otherwise reopen.

WORKED EXAMPLEA practice note you can actually useText
Predicted: 27 for two notebooks and one pen.
Observed: starter returned 15.
Changed: line cost = price × quantity; empty total starts at 0.
Next: can I explain the same rule with a for...of loop?

A note such as “finished arrays” records activity. This one records a decision and a test you can repeat.

The pattern transfers beyond arithmetic. After the Semantic HTML article, you could predict whether a form label is connected to its input, inspect the rendered DOM, repair the for/id pair, and revisit the idea on a different form. A tiny deliberate edit with a visible result is often more instructive than copying an entire page.

Courses give you an order in which to meet ideas. Practice gives you evidence that you can use them. For this exercise, the evidence is specific: you can predict the total, explain why the first implementation returned 15, write a general fix, and handle the empty case. When those answers survive a new input and a later attempt, move to the next concept.

IN THIS ARTICLE
Start with the mistake the learner is likely to makeGive the session a beginning and an endWork the cart problem all the way throughWrite feedback that names the failed assumptionIf you write lessons, design the check firstTomorrow, change the shape of the problemWhen you get stuck, inspect one iterationKeep a record small enough to reread
1,997 words8 sections
KEEP READING

More from SovranCode

ARTICLESemantic HTML that scales beyond the first pageARTICLEThemeForest Changed How We Buy Website Templates. Here’s What Comes Next.
READ NEXTThemeForest Changed How We Buy Website Templates. Here’s What Comes Next.
THE SOVRANCODE PLATFORM

Learn enough to build something real.

Start learning
100Learning modules
39exercises
6projects
2templates
4E-books
4guides
SovranCode

A free-first programming platform for people who learn best by understanding, practicing, and building.

● Core learning content is free
FollowYouTubePinterestX
LearnHTML courseCSS courseJSJavaScript coursePython courseC courseSQL courseDeveloper guidesAll exercises
BuildProjectsTemplate marketBuyer libraryTemplate licensesDeveloper toolsE-books
CommunityForumJournalContact
CompanyPricing previewAboutServicesPrivacyEnglish edition. Additional languages will be published only after full editorial review.
© 2026 SovranCode · Built for curious minds.Next.js · Node.js · PostgreSQL