Skip to content

Criterion D: Development

12 marksPlanning budget: 1120 counted wordsIB recommended: 1000 words

Criterion D shows how you built the product. Start by justifying the structure of the product, then demonstrate the techniques that best show your thinking and the complexity of your solution. For each technique, show the code, explain it, justify how you programmed it and justify how you tested it. The IB guide asks you to justify the structure of the product, demonstrate the techniques used to implement the algorithms from Criterion C, evaluate the choices you made, and justify the effectiveness of a testing strategy that covers correctness, reliability and efficiency.

What you need to produce

  • A short justification of the product's structure, at the beginning, before the first technique (recommended)
  • At least five techniques (recommended), each in four parts: (1) a screenshot of the code, (2) an explanation of the code, (3) a justification of how you programmed it, briefly compared with another option, and (4) a brief justification of how you tested it
  • Your full, commented source code in the appendix, which every code screenshot refers to

Word budget

About 1,120 counted words, the largest share of the 2,000: a short opening on the structure, then about 175 words per technique if you show six (a little more each if you show five), including each technique's heading, which counts. The 10–12 band asks you to evaluate choices and justify testing, which takes reasoning in prose, so D gets most of the words saved by bulleted success criteria and short-cell tables. Code, screenshots and figure captions are not counted. See how words are counted and allocated.

Code screenshots. Show code as screenshots from your editor, with line numbers and the file name, and reference the full source in your appendix. You may add arrows, highlights, numbered markers and short comments. Used sensibly this is fine; if a screenshot is clearly being used to hold paragraphs of explanation, expect your teacher or the examiner to count those words School convention. The video is planned separately: see Video.

Subsections

SubsectionWords (plan)Suggested rangeMain evidence
Two real examples––the IB timetable exemplar and a past student's visual example
How to write Criterion D––guidance, exemplar lessons and a checklist
D0 Structure of the product7050–80one short opening paragraph
D1 Technique 1: No double bookings175150–185code + GUI + test output in one figure
D2 Technique 2: The weekly limit175150–185code screenshot
D3 Technique 3: The noise rule175150–185code + GUI screenshot
D4 Technique 4: The waiting list175150–185code screenshot
D5 Technique 5: Releasing no-shows175150–185code + log output
D6 Technique 6: The usage report175150–185code + report output

Below: two real examples, then one guidance section with seven parts (purpose, what to include, suggested length, worked example, supporting evidence, lessons from the IB exemplars and a completion checklist), then PracticePal's whole Criterion D as one worked example. Labels show where each piece of guidance comes from:

IB requirement From the official IB Computer Science guide (IA_details.pdf)IA Guide Recommendation from the IA Documentation Guide (your teacher's analysis of IB exemplars)Teaching tip Extra suggestion added by this website
Official level descriptors for Criterion D (best-fit marking)
MarksLevel descriptor (IB Computer Science guide)
0The response does not reach a standard described by the descriptors below.
1–3very limited functionality
no appropriate techniques to implement the algorithms
states the choices made to implement the algorithms
states the testing strategy used
4–6limited functionality
at least one appropriate technique
outlines the choices made
states the effectiveness of the testing strategy
7–9partial functionality
some appropriate techniques
explains the choices made
describes the effectiveness of the testing strategy
10–12fully functional product
appropriate techniques to implement the algorithms
evaluates the choices made
justifies the effectiveness of the testing strategy

Two real examples

The PracticePal features below are invented. These two are real: an official IB exemplar, and a past student whose visual presentation of code is worth copying.

IB exemplar 6: IB timetable 10/12 in Criterion D

An official IB example marked under the current IA. It presents five techniques (file reading, multithreading, singletons, an SQL database and timetable creation) in the same four parts every time.

How technique 1 maps to the four parts

  1. Code: a screenshot of getAllSubjects() from the editor.
  2. Explanation: the first paragraph walks through the code: a File object, an ArrayList, a for-each loop over the lines, each split on “-” and parsed into a Subject.
  3. Justification: “The reason why I used this approach…”: a text file is easy for the school to edit (SC7) and reading it is wrapped in exception handling. It then evaluates the limitations: one catch for every exception, the file is re-read on every call instead of being cached, and its existence is never checked.
  4. Testing: a short paragraph on how testing the subjects file with normal, abnormal and extreme data also tests this method.

Do better than this example (from the examiner's comments)

  • “Code has been included without comments.” Comment the code in your screenshots.
  • Testing was only “somewhat described”: the testing paragraphs say the plan would test the feature but name no test, data or result. Name them.
  • The configuration file “has not been integrated and must be maintained outside the solution”.

Open the full IA (PDF) Examiner's comments (PDF)

A past student: a visual way to show code

Written for the previous IA, where Development was Criterion C, so it is not marked against the current criteria. It is here for the way it presents code: the code, the GUI and the output in one picture.

What it shows well

  1. Code and GUI together: a screenshot of the form with red boxes and dotted arrows from a button to the exact lines of code it runs.
  2. Explanation: short callouts next to the code (“Validates if all fields are empty”) plus a sentence or two of prose.
  3. Test cases on screen: “Error #1” and “Error #2”, and 28 to 31 February 2018, each marked with a tick or a cross next to the message it produces.
From the old syllabus: two parts are missing. These techniques have no specific justification (why this approach, compared with another) and no specific comment on testing (which tests, with what data, and why they show it works). Both are required now. Add them as the IB timetable example and PracticePal do.
What the missing parts could look like · for the validation technique on pages 14–17149 counted words

Instead of this technique, I could have put the validation rules in the database itself, for example as constraints in a larger database such as MySQL. I chose to validate in the GUI because it is more user-friendly: the user gets instant feedback in a clear message before anything is saved, rather than a database error afterwards. The + and − buttons go further for the quantity, removing non-numeric input completely. Limitation: data added to the database directly is not validated.

Tests T4–T7 cover this technique. Normal: a complete product (Butter, quantity 2, 14 March 2018) is added. Abnormal: each required field left empty, and a quantity of 0, are rejected with a message and nothing is saved. Extreme: 28 February is accepted, 29–31 February rejected, and − at quantity 0 does nothing. 29 February 2020, a leap year, was wrongly rejected until I added the year to the check.

Suggested by this website, not written by the student. The tests and results are invented to show the kind of thing to write: name the tests, the type of data, the results and anything the tests found.
Watch the callouts. Short labels are fine, but some callouts here are full sentences of explanation. Words used to hold explanation inside a screenshot may be counted School convention.

Open the full example (PDF)

1 Purpose

Justify the structure of your product, then present your techniques one after another, each in the same four parts: the code, what it does, why you programmed it this way, and how you know it works.

2 What to include

  1. IB requirementJustify the structure of the product and why the structure is appropriate.
  2. IA GuidePut this justification at the beginning, before the first technique, unless one of the techniques you demonstrate is the structure of the product itself (for example, how the program is divided into modules or classes); then justify it in that technique.
  3. IB requirementDemonstrate the techniques used to develop the product, based on the algorithms in Criterion C. Techniques may include loops, data structures, existing libraries and the integration of software tools.
  4. IA GuideDemonstrate at least five techniques, chosen to show the most complex parts of your solution.
  5. IB FAQApply techniques from the syllabus. The IA is the same for SL and HL, so SL-level techniques are the minimum expectation; choose techniques that match your success criteria and support both the functionality and the efficiency of the solution.
  6. IB FAQComplexity lies in the problem, not in the techniques: you do not need code far beyond the course, and should avoid developing techniques beyond it. Object-oriented programming is not required (a Python and SQL database solution without classes is fine).
  7. IA GuideMake sure each technique is well tested in your test plan (Criterion C) and shown in your video, so that the testing justification you give here is valid.
  8. IB requirementHighlight key elements of code that are important for the efficient functioning of the algorithms. Code must include relevant comments, be consistent and readable, and be referenced to the full source code in the appendix (without the appendix you cannot get full marks for techniques).
  9. IA Guide1 · Code. A screenshot of the code for the technique, with the file name and line numbers, referenced to the full source in your appendix.
  10. IA Guide2 · Explanation. Walk through what the code does, pointing to line numbers or numbered markers rather than retyping the code.
  11. IA Guide3 · Justification. Why you programmed it this way, briefly compared with another option, and what the choice costs or cannot do. To reach 10–12 the IB asks you to evaluate the choices (7–9 explains them; 4–6 outlines them).
  12. IA Guide4 · Testing. Briefly justify how you made sure it works: which tests from your plan, with normal, extreme and abnormal data, and what they showed. Across all your techniques, cover correctness, reliability and efficiency (an IB requirement).
  13. IA GuideIf you used AI (ChatGPT or similar), acknowledge it in a code comment and in your documentation.
  14. Teaching tipSuggestion: give each of the four parts its own paragraph, so the examiner can find them. Paragraphs are enough: headings for each part would count towards the 2,000 words.
  15. Teaching tipSuggestion: combine the code screenshot with screenshots of the GUI and the output in one figure, with numbered markers you refer to in the text. Students have used this to save words and make a technique easier to follow.

3 Suggested length

About 1,120 counted words: 50–80 for the structure, then about 150–185 per technique if you show six, or a little more each if you show five. Headings count, so keep them short; code, screenshots and figure captions do not. Spend the extra words on evaluating each choice: what it costs, what it cannot do, and what testing showed. Refer to success criteria by code (SC4), never by their text.

4 Worked example

The worked example is PracticePal's whole Criterion D, as one document: go to the worked example. Two real examples are above.

5 Supporting evidence (to be added to your appendix)

  • Appendix A: the full, commented source code; each figure gives the file, lines and page.
  • Appendix B: the full results of the tests you mention, with output and before-and-after screenshots.
  • Keep the key result in the figure itself: the IB does not use the appendix as evidence for marks.

6 Lessons from the IB exemplars

From the IA Documentation Guide's analysis of real, examiner-graded IB Computer Science IAs.

  • Example 6 (IB timetable, 10/12 in D) presents five techniques in this pattern: a code screenshot, what the code does, why this approach with its advantages and limitations, and how the testing strategy covers it.For your IA: Use the same four parts for every technique you choose.
  • Code without comments was named in the examiner's overall comment on 5 of the 8 IB exemplars, including Example 6.For your IA: Comment the code you show and the code in your appendix; comments should say why, not repeat the code.
  • In Examples 2 and 5 the implementation choices were only “outlined”; in Example 4 their evaluation was “not pervasively addressed”.For your IA: Justify every technique against an alternative, not just the first one.
  • Example 8 (5/12 in D): the documentation “does not highlight key elements of code”.For your IA: Choose the code that carries the logic, and mark the lines that matter.
  • The effectiveness of the testing strategy was “generically stated” in Examples 4, 7 and 8, and too little testing with extreme and abnormal data was criticised in Examples 2, 6 and 7.For your IA: Each testing paragraph names specific tests, data and results.
  • Examples 2 and 6 were judged “not fully integrated” because questions or a configuration file had to be edited outside the product.For your IA: Let users maintain their data through the product.

7 Completion checklist

Ticks are saved in this browser only, so you can use the list while you draft.

Worked example: PracticePal's Criterion D

The whole of PracticePal's Criterion D as one document: the structure first, then six techniques, each with its code, explanation, justification and testing. The small labels beside each part are added by this website: they are not part of the document and are not counted.

Worked example (illustrative): Criterion D in full · PracticePal, a fictional project1048 counted words (suggested 1000–1120)

Structure of the product

PracticePal is a Flask web app divided into modules by responsibility, as in the Criterion C structure chart: views.py only handles pages; rules.py, waitlist.py and reports.py hold the logic; scheduler.py runs timed jobs; db.py alone contains SQL. This lets every rule be unit-tested without a browser, and a database change affects one file. A single app.py would be quicker to write but hard to test.

Technique 1: No double bookings (SC4)

Figure D1: rules.py, lines 32–51 (Appendix A, p. 4)
rules.pylines 32–51
32def make_booking(con, student, room, start, loud):
33 end = start + SLOT # every slot is 30 minutes
34 reason = check_rules(con, student, room, start, end, loud)
35 if reason: # weekly limit or noise rule
36 return None, reason
37 try:
38 # BEGIN IMMEDIATE takes the write lock BEFORE the final check,1
39 # so two requests for one slot are handled one after the other.
40 # (Idea from a ChatGPT explanation of 'database is locked';
41 # code written by me.)
42 con.execute('BEGIN IMMEDIATE')
43 if db.count_overlaps(con, room, start, end) > 0: # Q1, rechecked inside the lock2
44 con.rollback()
45 return None, 'Slot just taken'
46 booking_id = db.insert_booking(con, student, room, start, end, loud)
47 con.commit()
48 return booking_id, None
49 except sqlite3.IntegrityError: # UNIQUE(room_code, start_time): second safeguard3
50 con.rollback()
51 return None, 'Slot just taken'

    make_booking() runs when a student taps Book. BEGIN IMMEDIATE takes the write lock (1); only then does count_overlaps() check for an overlap, using the Criterion C rule (2). A free slot is saved; otherwise the student sees “Slot just taken” (4).

    Checking and then inserting let two simultaneous requests both pass. Locking before the final check makes them one step, with a UNIQUE constraint as a second safeguard (3). A Python lock is simpler but fails with several processes. I tried one first: it passed with a single server worker but let duplicates through with two, which confirmed the choice. The cost, saving bookings one at a time, is acceptable when each takes under 0.2 seconds.

    T5 (extreme) accepts 12:30 next to 12:00. T6 (abnormal) books one slot twice at once, 200 times: 6 duplicates before the lock, none after (5). T14 (efficiency): 30 simultaneous bookings each took under 0.2 seconds. Together they cover correctness, reliability under load and efficiency.

    Technique 2: The weekly limit (SC5)

    Figure D2: db.py, lines 40–48 (Appendix A, p. 8)
    db.pylines 40–48
    40def count_week_bookings(con, student, start):
    41 """Bookings the student already has in the ISO week (Mon-Sun) of start."""
    42 year, week, _ = start.isocalendar() # ISO week, not US week (fix after T7)1
    43 row = con.execute(
    44 "SELECT COUNT(*) FROM booking WHERE student_id = ? "
    45 "AND iso_year = ? AND iso_week = ? "2
    46 "AND state IN ('confirmed', 'checked_in')", # no-shows and cancellations do not count3
    47 (student, year, week)).fetchone()
    48 return row[0]

      count_week_bookings() counts the student's bookings in the ISO week of the slot. isocalendar() gives the year and week, Monday to Sunday (1); one query counts the matching rows (2), ignoring cancellations and no-shows (3).

      Storing each booking's ISO year and week makes this one indexed query. Querying a Monday-to-Monday date range needs no extra columns, but repeats date arithmetic wherever weeks are used. Not counting no-shows was Ms Okafor's decision. The cost is two extra columns that must stay in step with the start time, so only insert_booking() sets them and nothing edits them later.

      T7 (extreme) books a third, then a fourth slot in one week, including a Sunday. It first failed: US week numbers start on Sunday, so Sunday bookings counted towards the next week. ISO weeks fixed it, and a unit test now checks the last days of December, when the ISO year can differ from the calendar year.

      Technique 3: The noise rule (SC6)

      Figure D3: rules.py, lines 71–84 (Appendix A, p. 5)
      rules.pylines 71–84
      71def load_neighbours(con):
      72 """Room graph as a dictionary: room code -> set of rooms sharing a wall."""
      73 graph = {code: set() for code in db.room_codes(con)}
      74 for a, b in db.neighbour_pairs(con): # NEIGHBOUR table, one row per wall1
      75 graph[a].add(b) # undirected: add both directions
      76 graph[b].add(a)
      77 return graph
      78
      79def noise_clash(con, graph, room, start, end):
      80 """Return the first neighbour with an overlapping loud booking, or None."""
      81 for n in sorted(graph[room]): # only this room's neighbours2
      82 if db.count_loud_overlaps(con, n, start, end) > 0: # Q3
      83 return n
      84 return None

        load_neighbours() turns the NEIGHBOUR table into a dictionary mapping each room to the set of rooms sharing a wall, adding each wall both ways (1). For a loud booking, noise_clash() checks only that room's neighbours (2) and the message names the clash (3).

        Walls are data, not if-statements: if P2 becomes a drum room, the head of music edits a table, not the code. A set gives fast membership tests without duplicates. Refusing any loud overlap in the building is simpler but blocks distant rooms. Corridor noise is not modelled. The weakness is that the table must be right: a missing wall silently allows a clash, so the admin screen lists each room's neighbours for Ms Okafor to check.

        T8: a loud booking next to a loud one is refused (abnormal); a quiet one is accepted (normal). Unit tests add extreme cases: a room with no neighbours, and bookings that only touch. A loop also checks that every wall in the table works both ways.

        Technique 4: The waiting list (SC7)

        Figure D4: waitlist.py, lines 18–25 (Appendix A, p. 7)
        waitlist.pylines 18–25
        18def offer_next(con, room, slot):
        19 """Offer a freed slot to the student at the FRONT of its waiting list (FIFO)."""
        20 entry = db.first_waiting(con, room, slot) # ORDER BY joined_at LIMIT 11
        21 if entry is None:
        22 return None # nobody waiting: slot is just free
        23 db.set_entry_state(con, entry.id, 'offered', offered_at=now())2
        24 mail_offer(entry.student_id, room, slot, expires=now() + OFFER_TIME) # 15 minutes3
        25 return entry.student_id

          When a booking is freed, offer_next() reads the waiting list in joined_at order and takes the oldest entry (1), so the table acts as a first-in, first-out queue. The entry becomes “offered” (2) and the student is emailed a 15-minute deadline (3).

          A queue matches the rule agreed with Ms Okafor: first to join, first offered. An in-memory collections.deque would be lost on every server restart; the database keeps the queue and shows the head of music who is waiting, for one query per offer. A priority queue was considered, but nothing in the requirements ranks students, and a rule students can predict matters more here than flexibility.

          T9 (normal): three students join and the first is offered the freed slot. Extreme cases accept at 14:59 and expire at 15:00, passing the offer on. Joining twice (abnormal) is refused. A fake clock avoided real waiting, and T9 was repeated after a server restart to show the queue survives.

          Technique 5: Releasing no-shows (SC8)

          Figure D5: scheduler.py, lines 12–20 (Appendix A, p. 9)
          scheduler.pylines 12–20
          12def release_no_shows(con):
          13 """Run every 5 minutes by APScheduler (set up in app.py)."""
          14 cutoff = now() - timedelta(minutes=GRACE) # GRACE = 101
          15 late = db.unchecked_bookings(con, before=cutoff) # Q6: confirmed, no check-in
          16 for b in late:
          17 db.set_booking_state(con, b.id, 'no_show') # kept for the usage report2
          18 waitlist.offer_next(con, b.room_code, b.start_time) # technique 43
          19 con.commit()
          20 log.info('released %d no-shows', len(late))

            APScheduler runs release_no_shows() every five minutes. It finds confirmed bookings that started more than ten minutes ago (1) without a check-in, marks each as a no-show rather than deleting it (2), and offers the slot to the waiting list (3).

            A fixed-interval job keeps no state, so it survives restarts. A timer per booking would be exact, but every timer would be lost when the server restarts each night. The cost is precision: a booking may be released up to five minutes late. In hindsight five minutes was too generous for 30-minute lunchtime slots; a one-minute interval would cost little and is evaluated under SC8.

            T10 (extreme): a booking without a check-in must be kept at +9 minutes and released after +10. It was released at +12 (4), revealing the delay. Running the job twice (abnormal) never records a no-show twice. The log showed each run takes under 50 ms, so a shorter interval is feasible.

            Technique 6: The usage report (SC10)

            Figure D6: reports.py, lines 9–19 (Appendix A, p. 11)
            reports.pylines 9–19
            9def usage_report(con, year, week, path):
            10 """Write one CSV row per room for an ISO week (SC10)."""
            11 rows = db.week_usage(con, year, week) # GROUP BY room: bookings, minutes, no-shows1
            12 with open(path, 'w', newline='') as f:
            13 out = csv.writer(f) # quotes any field containing a comma
            14 out.writerow(['room', 'bookings', 'used_%', 'no_shows'])
            15 for r in rows:
            16 avail = db.available_minutes(con, r.room, year, week) # 3,000 minus blocked time
            17 used = 100 * r.minutes / avail if avail else 0 # room blocked all week2
            18 out.writerow([r.room, r.bookings, round(used, 1), r.no_shows])
            19 return path

              usage_report() writes one CSV row per room for an ISO week. One grouped query returns each room's bookings, minutes and no-shows (1); the percentage used is minutes booked divided by minutes available, 3,000 less any blocked time (2).

              Grouping in SQL lets the database count, so Python handles one row per room. The csv module, rather than joined strings, stops a comma in a room name breaking the file. CSV opens in Excel, which Ms Okafor uses; a PDF looks better but cannot be filtered. The grouped query relies on SQLite's date functions, so another database would need it rewritten; for one school that is an acceptable risk.

              T12 uses a busy week (normal) and an empty week (extreme), checked against hand counts. A room blocked all week caused a division by zero; the guard now reports 0% (3). Totals were checked against the bookings table so that no booking is counted twice.

              Illustrative only: the people, data and results are invented to show the level of detail expected. Your documentation must describe your own problem, your own evidence and your own decisions.

              Criterion D worked examples: word total

              SubsectionPlanning allocationWorked example (counted words)
              D0 Structure of the product7069
              D1 Technique 1: No double bookings175166
              D2 Technique 2: The weekly limit175158
              D3 Technique 3: The noise rule175171
              D4 Technique 4: The waiting list175164
              D5 Technique 5: Releasing no-shows175161
              D6 Technique 6: The usage report175159
              Total11201048

              The fictional PracticePal documentation uses 1048 of the 1120 counted words planned for Criterion D. Across all five criteria it stays within 2,000; see the budget table.