Critiquing Data Designs
Learning Objectives
- You can recognise that the shape of data is a design decision with real consequences.
- You can name the common data-shape options and what each is good for.
- You can spot the failure modes that AI assistants fall into when proposing a data design.
- You can ask an AI for design alternatives and weigh them on the access pattern, not on first impressions.
This is the AI-collaboration chapter for the part. The earlier skills were all about code: reading it, verifying it, specifying it, spotting plausible-but-wrong versions, and comparing approaches. This one is about the layer underneath the code — the shape of the data, and critiquing data designs — judging the shape the data is held in, not just the code that processes it.
Data Shape Is a Design Decision
The same information can take many shapes. In the materials, the study log’s sessions have been represented in three different ways:
["math", 45, "2024-03-10"] # list (row){"subject": "math", "minutes": 45, "date": "2024-03-10"} # dictionarySession("math", 45, "2024-03-10") # objectSimilarly, a collection of sessions has been a list of rows, a list of dictionaries, a list of objects, and a property of a StudyLog object. Each shape makes some operations easy and others awkward. The list-of-rows made positional access cheap and named access impossible. The dictionary made named access easy and shape guarantees impossible. The object made shape guarantees and behaviour easy at the cost of a serialization step.
None of these is the right shape in general. The right shape depends on what you do with the data — and that means choosing one is a design decision, with the same importance as any other decision in a program.
Choosing badly is not an error; the code will run. It will just be harder to work with than it needed to be, in ways that show up later and cost more to fix.
Available Options and Their Uses
By now you have a toolkit of shapes. It helps to have them laid out with their strengths, because the critique skill is largely a matter of matching the shape to the job.
-
A single variable holds one value. Right when there is exactly one thing: a count, a total, a name.
-
A list holds a sequence of values, accessed by position or walked in order. Right when you have many of the same kind of thing and order matters, or you will process all of them.
-
A list of rows — a list of small lists — holds records by position. Right in rare instances such as representing a two-dimensional grid, where the position is inherent in the data.
-
A dictionary maps names to values. Right when you look things up by name, especially when the set of names varies or you do not control it — configuration, counts keyed by category, data arriving from outside.
-
A list of dictionaries holds a sequence of records with named fields. Right for a collection of records when the records’ shape is loose or still settling, and you do not need behaviour attached.
-
A dictionary of lists groups items under keys. Right as the result of a grouping, when you want all the items in each category together.
-
A class defines a fixed-shape record with behaviour. Right when the shape is stable and known, mistakes in that shape are worth catching early, and there is behaviour that belongs with the data.
The critique skill is mostly the discipline of asking “how will this data be accessed?” and picking the shape whose strength matches the answer — rather than picking the first shape that comes to mind, or the most elaborate one.
How AI Gets Data Design Wrong
Ask an AI assistant to design a data structure and it will give you one, confidently, usually without mentioning that other shapes were possible. The shape it picks is often reasonable, but it falls into recognisable traps often enough that you should look for them.
Over-nesting. Asked to hold study sessions, an assistant may reach for something like:
data = { "students": { "default": { "subjects": { "math": { "sessions": [ {"minutes": 45, "date": "2026-03-10"} ] } } } }}This can represent the data, but reaching a session’s minutes now means data["students"]["default"]["subjects"]["math"]["sessions"][0]["minutes"] — five levels deep, most of them serving no purpose the study log actually has. For a single user logging sessions, the flat list of records is simpler and serves every access the program needs.
Premature classes. Asked to hold study sessions, an assistant might also produce a class with an __init__, a couple of methods, and a serialization pair, where a plain dictionary would have done the whole job in one line. A class earns its keep when the shape is stable, reused, and worth protecting, or when behaviour belongs with the data. For a throwaway intermediate result, the class is overhead.
Schema drift. Asked to add a field to some records, an assistant working with dictionaries may add it to the records under discussion and leave the rest untouched, producing a mismatched collection. Every function downstream then has to cope with mixed shapes. When an AI proposes adding a field, the question to ask is “to all of them, consistently?” — and if the answer is “it depends”, that is a sign the shape wants to be a class.
Fighting the access pattern. An assistant may pick a shape that does not match how the data is used: a list when you keep searching it by name (a dictionary’s job), or a dictionary keyed by something you never look up by, when you really just walk all the records in order (a list’s job). When you read an AI’s proposed shape, trace how the program will actually reach into it, and check that the shape’s strength is the one the program needs.
Eliciting Alternatives
The comparing-approaches skill from the previous part applies directly here, with one addition: with data design, the alternatives are often not offered at all, so you have to ask for them explicitly. A useful prompt is some version of “what are two or three other ways I could structure this, and what is each one good and bad at?”
A good answer will lay out, say, a list of dictionaries against a class against a grouped dictionary, and — the part that matters — say what each makes easy and what each makes awkward. If the assistant just restates its first idea three times with cosmetic differences, that is itself useful information: it suggests the assistant has not engaged with the trade-off, and you should push harder or work it out yourself.
Then you judge, on the access pattern, the way this chapter has been describing. The judgment is yours. The assistant can lay out options and describe trade-offs faithfully, but only you know how the data will actually be used across the whole program, and that is what decides the shape.
Rewrite a data-shape alternatives prompt
0 / 10 points
Rewrite this weak prompt into a stronger prompt you would actually send to an AI assistant:
I am making a club attendance program. What data structure should I use? Give me Python code.Your rewritten prompt should give the assistant enough context to reason about data shape before writing code.
The club attendance program records member names, meeting dates, and whether each member attended. It must support these access patterns:
- list all attendance records in date order,
- find all records for one member,
- count attended meetings per member,
- and later attach small helper behavior to one attendance record.
Submit only the rewritten prompt. The rewritten prompt should ask for design alternatives and reasoning before code.
A Worked Critique
Suppose you ask an assistant how to store the study log so you can show totals per subject, and it proposes keeping the data pre-grouped by subject on disk:
{ "math": {"total": 130, "sessions": [{"minutes": 45, "date": "2024-03-10"}]}, "physics": {"total": 90, "sessions": [{"minutes": 90, "date": "2024-03-10"}]}}Trace it against the access patterns the program actually has. Showing per-subject totals: easy, they are right there. But the study log also walks all sessions in date order for streaks, finds the heaviest day across subjects, and lists recent sessions regardless of subject — and every one of those now has to dig through the per-subject grouping and stitch the sessions back together. The shape is optimised for one access pattern at the expense of several others the program relies on.
There is also a total stored alongside the sessions, which means two representations of the same fact — the stored total, and the sum of the session minutes — that can fall out of step the moment a session is added and the total is not updated. Storing a value you could compute is a standing invitation for the two to disagree.
The flat list of session records you already have avoids both problems. Walking all sessions is natural; grouping by subject is a summary you compute when you need it, with the one-pass dictionary accumulation, so the grouped total is always derived fresh and cannot drift. The assistant’s design is not bad — if the only thing the program ever did was show per-subject totals, pre-grouping might be defensible — but weighed against the program’s real mix of access patterns, the flat list is the better shape. That weighing, against how the data is actually used, is the skill.
Critique an over-nested attendance design
0 / 10 points
An assistant proposes this structure for a small club attendance program:
data = { "organization": { "clubs": { "default": { "members": { "Ari": { "meetings": { "2026-04-01": { "attendance": {"attended": True} } } } } } } }}The program is for one club. It needs to list all attendance records in date order, find all records for one member, and count attended meetings per member.
In 4-7 sentences, critique the proposed design. Explain what the design makes awkward, identify at least one unnecessary layer, and suggest a simpler shape that better matches the access patterns.
Where You Are in the Arc
Six of the nine AI-collaboration skills are now in place:
| Part | AI skill | What it gives you |
|---|---|---|
| 1 | Reading code you didn’t write | Knowing what a piece of code does |
| 2 | Verifying behavior and finding edge cases | Knowing whether what it does is right |
| 3 | Specifying what you want | Knowing what to ask for in the first place |
| 4 | Detecting plausible-but-wrong code | Knowing when “it runs” is not “it works” |
| 5 | Comparing approaches | Knowing how to choose between several right answers |
| 6 | Critiquing data designs | Knowing whether the data is in the right shape |
| 7 | Working with AI on libraries you’re learning | |
| 8 | Critiquing AI-suggested visualizations | |
| 9 | Iterating with AI on a project |
The next chapter puts this skill to immediate use. The study log’s second migration — to a Session class and a StudyLog class — is a sequence of data-design decisions, and each one is a chance to ask “is this shape right for how it is used?” rather than reaching for a class because the part happens to be about classes.
Check Your Understanding
- The chapter says the shape of data is “a decision.” What makes it a decision rather than an obvious fact about the problem?
- Name two of the four failure modes the chapter describes for AI-proposed data designs.
- What single question does the chapter recommend asking in order to choose a data shape?
- In the worked critique, two separate problems were found with the pre-grouped-by-subject design. What were they?
- Why does asking an AI for “two or three other ways to structure this” matter more for data design than it does for ordinary code?
AI Study Aid
Create a chapter diagram
We're looking into to what extent AI-generated diagrams could help with studying.
Use this study aid to generate an AI-generated visual summary of the material you just studied.
Each diagram style emphasizes the content in a different way, so you can choose the focus
that feels most useful.
Using the diagram generator is voluntary and does not affect your course progress. We encourage
you to try it out and see if it helps, but it's totally up to you! Your answers help us understand
how to make better study aids in the future.