Using AI Tools · Guide 13 of 35

Using AI for Programming

Specify a small programming task, inspect the proposed implementation and test it against independent examples.

IntermediateAbout 10 min readPractical exercise

Before you start: Basic JavaScript · Prompt engineering. Reading time is an estimate; allow extra time for practice.

What you’ll learn

  • Write an independent behaviour contract before requesting generated code.
  • Give a coding assistant focused context and review its proposed changes.
  • Run a local counterexample and verify a corrected implementation against boundary cases.
  • Distinguish generated suggestions, executed checks and a production-ready change.
On this page

Decide what the program must do

You are adding a duration label to a small practice timer. The label should display total minutes and two-digit seconds: 61 seconds becomes “1:01”, and 3,600 seconds becomes “60:00”. An assistant can propose the function, but you need to decide those rules first. Otherwise it may introduce an hours format, round fractional input or accept numeric strings without asking.

Our contract accepts only JavaScript numbers that are non-negative safe integers, representing whole seconds. “Safe integer” means an integer within the range that JavaScript's number representation can distinguish reliably from adjacent integers. Invalid inputs return null. Minutes do not wrap after 59, and the function performs no network, file or user-interface work.

Write expected examples before inspecting a proposal: 0 → “0:00”, 59 → “0:59”, 60 → “1:00”, and 61 → “1:01”. Also decide how to treat -1, 1.5, “61” and missing input. This creates a standard independent of whatever code the assistant produces. A test that merely repeats the generated implementation's assumptions can approve the wrong behaviour.

Supply the smallest useful programming context

Tell the assistant the language, runtime, function signature and relevant project conventions. For this exercise, plain JavaScript in a modern browser console or Node.js is enough. In an existing repository, also identify the actual dependency versions and nearby tests. A suggestion that uses a real API from the wrong library version can still fail in your project.

Share code you are authorised to share, and remove access tokens, connection strings, customer records and unrelated logs. Editor assistants can include surrounding code or open files as context, so review the product's context and data controls as well as what you manually paste. Never place a secret in a prompt and rely on an instruction not to reveal it.

Ask for a focused proposal and an explanation of assumptions. An inline completion, a chat answer and an agent that can edit files or run commands have different capabilities. Inspect the current tool permissions. For a small formatter, no package installation, external service or production access is needed.

Example prompt: a bounded programming request
Implement formatDuration(seconds) in plain JavaScript.
Accept non-negative safe-integer numbers only; return null otherwise.
Return total minutes plus a colon plus exactly two seconds digits.
Examples: 0 -> "0:00", 61 -> "1:01", 3600 -> "60:00".
Reject strings, fractions, negative numbers, NaN and Infinity.
Do not coerce input, add dependencies or change other code.
Explain the implementation and suggest boundary tests separately.
State which tests you actually ran; do not claim execution if none ran.

Use this in a chat or coding assistant with the intended scope. It is a request for code and evidence, not evidence that files were edited or checks executed.

Challenge a plausible first proposal

Suppose the assistant proposes the candidate below. It divides by sixty to get minutes and uses the remainder for seconds. That seems plausible, but it prints “1:1” for 61 seconds. One counterexample is enough to show that it violates our formatting contract. It also has no input validation, so fixing the display alone would leave other requirements unmet.

Run the complete block in a browser console or save it as duration-candidate.js and run node duration-candidate.js. It needs no dependencies or network. The assertion deliberately confirms the observed defect so the demonstration completes successfully while exposing the incorrect result. It is not a test declaring the candidate suitable for use.

JavaScript: reproduce a generated formatting defect
function candidate(seconds) {
  return Math.floor(seconds / 60) + ':' + (seconds % 60);
}
const observed = candidate(61);
if (observed !== '1:1') throw new Error('Unexpected demonstration result');
if (observed === '1:01') throw new Error('The expected defect disappeared');
console.log('Observed:', observed, '| Required: 1:01');

Expected output: Observed: 1:1 | Required: 1:01. The failure is demonstrated against a predetermined requirement; the assertions check that the demonstration really exhibits it.

Review each operation in the correction

The corrected function first uses Number.isSafeInteger and checks the sign. This rejects strings without converting them and excludes fractions, NaN, Infinity and unsafe integers. Then it computes whole minutes and the remaining seconds. Converting the remainder to a string and using padStart(2, “0”) supplies the leading zero without changing a two-digit value.

Run this complete block separately in a browser console or save it as duration-checks.js and run node duration-checks.js. It includes its own function and checks, so it does not depend on the earlier snippet. Each expected string comes from the written contract. The invalid-input loop verifies the chosen rejection policy rather than merely checking that the program does not crash.

JavaScript: a duration formatter with independent checks
function formatDuration(seconds) {
  if (!Number.isSafeInteger(seconds) || seconds < 0) return null;
  const minutes = Math.floor(seconds / 60);
  const remainder = String(seconds % 60).padStart(2, '0');
  return minutes + ':' + remainder;
}
const examples = [
  [0, '0:00'], [9, '0:09'], [59, '0:59'], [60, '1:00'],
  [61, '1:01'], [3599, '59:59'], [3600, '60:00']
];
for (const [input, expected] of examples) {
  if (formatDuration(input) !== expected) {
    throw new Error('Wrong duration for ' + input);
  }
}
const invalid = [-1, 1.5, '61', '', null, undefined, NaN,
  Infinity, Number.MAX_SAFE_INTEGER + 1];
for (const input of invalid) {
  if (formatDuration(input) !== null) {
    throw new Error('Accepted invalid input: ' + String(input));
  }
}
console.log('7 formatting cases and 9 rejection cases passed');

Expected output: 7 formatting cases and 9 rejection cases passed. These are local behaviour checks, not API calls. The function formats a duration; it does not measure elapsed time or schedule a timer.

Test the change where it will be used

Passing this block establishes behaviour for the tested inputs. Integration still needs a decision about null. A UI might show “Duration unavailable” for invalid data instead of rendering the word null or silently showing zero. Verify that the caller actually supplies seconds rather than milliseconds: 60,000 milliseconds is one minute, but our function correctly interprets the number 60,000 as seconds because that is its contract.

Inspect the complete diff if an assistant edits your project. Look for unrelated formatting, new packages, changed configuration or removed tests. Run the relevant project checks and read their output. A claimed successful run without an observed command result is not the same evidence as a completed test execution. Type checking and linting answer useful but different questions from behaviour tests.

Check the proposed use of language features in primary documentation when uncertain. The sources below explain padStart and Number.isSafeInteger. For external packages, verify the exact installed version and genuine package source before installing anything. A package name suggested by a model may be mistaken or refer to something unrelated.

Use explanations to improve your own model of the code

Ask the assistant to explain why 59 and 60 are useful adjacent tests, or why accepting “61” would be a separate policy. Then predict the output for 119 and 120 before running it. Being able to explain the result is more valuable than collecting a larger block of generated code you cannot maintain.

When a test fails, compare the requirement, expected result and observed result before requesting another rewrite. A wrong assertion can be the problem too. Give the assistant the smallest failing case and the actual error, then ask for a focused change. Preserve the failing case as a regression check if it represents supported behaviour.

Generated tests need review just like generated code. Ask what boundary is still untested, but choose important cases independently. A second response approving the first one is not an independent oracle. The purpose of assistance is to accelerate a process you can inspect, explain and reproduce.

Keep the conclusion proportional to the evidence

This formatter is deliberately small. It does not address localisation, spoken time labels, an hours display or the accuracy of a real timer. Adding those requirements changes the contract and needs corresponding checks. The exercise also does not establish the security of an application merely because a pure function passes sixteen cases.

For consequential code, use the project's review and release process, appropriate security checks and realistic integration tests. Keep changes small enough to understand and reverse. A useful final assistant report states what changed, which commands ran, their results and any remaining limitations, so another developer can assess the work without trusting the conversation's confidence.

Put it into practice

Try it yourself

Run both JavaScript blocks. Predict and add checks for 119 and 120 seconds, then write the caller behaviour for null. Explain why a value in milliseconds must be converted deliberately before calling the formatter.

Show hint

Expect 119 → “1:59” and 120 → “2:00”. Keep the null policy distinct from a valid zero duration. Demonstrate one caller case for null and one for 0. Do not weaken input validation just to accept a convenient input. These checks verify a duration-formatting contract, not the accuracy of a timer or a complete UI.

Optional practice

Check your understanding

5 questions to revisit the ideas. No score is saved, and you can retry. This is separate from Skill Quiz; it does not award XP or unlock guides.

1. Why choose the expected result for 3,600 seconds before asking for code?
2. What does the first runnable block demonstrate?
3. Why does the corrected function return null for the string “61”?
4. The caller supplies 60,000 milliseconds to a function expecting seconds. Where is the remaining problem?
5. An assistant says all project tests passed but provides no execution result. What should you do?

Related programming documentation

Sources & further reading

Primary references for the concepts in this guide. Examples and exercises are illustrative; verify provider-specific behaviour against the version you use.