3.02 Impact of Program Design
Design reliable programs that guard against bad input, and weigh their social, ethical, and intellectual property impacts.
1. Reference Guide
Key Topics
| Term | Definition | Example |
|---|---|---|
| System reliability | A program performs as expected, under stated conditions, without failure. | Thermostat gives correct status for every valid temperature |
| Edge case | An input at or beyond the limits of what is valid. | 0, -400, "", null, Double.NaN |
| Guard clause | A check at the top of a method that rejects invalid input before anything else runs. | if (temp < 50 \|\| temp > 90) throw ... |
| Silent failure | Bad input is accepted and produces a confident wrong answer. | -400 degrees reports HEATING |
| Unintended consequence | Harm beyond a program’s intended use, even when the code works as designed. | +2 degrees x 50,000 homes |
| Open source | Code published with a license that says how others may reuse it. | MIT, Apache-2.0 |
- A rejected call leaves the object unchanged: failing is safer than corrupting.
- No license means no permission: visible code is not free code.
The Five Big Ideas
| # | Big Idea | You will be able to |
|---|---|---|
| 1 | System Reliability | Explain why one passing test is not evidence of reliability |
| 2 | Guarding Against Bad Input | Write a guard clause that protects an object |
| 3 | Social, Economic, and Cultural Impact | Name beneficial and harmful effects of one program |
| 4 | Unintended Consequences | Explain how scale turns a small change into harm |
| 5 | Intellectual Property and Code Reuse | Decide if code may be reused from its license |
2. LxD Cycle Process
Empathize: Watching classmates write their first validated methods, the same pattern showed up: they tested one input, it returned the expected value, and they moved on. Asked “what happens if someone passes a negative number,” the common answer was “why would they?” The misconception underneath is that invalid input is the user’s problem, not the method’s. It produces no error, so it surfaces later where nobody is looking.
Define:
- POV: CSA students who can write a working method need to see that a method owns its own invalid input, because they test to confirm success instead of finding failure, which hides silent corruption.
- Learning Goal: Students will explain system reliability, add a guard clause that rejects invalid input, describe beneficial and harmful impacts of one program, and decide whether code may be reused from its license.
Ideate:
- HMW Question: How might we make a silent failure visible to someone whose code has never errored?
- HMW Question: How might we show that harm can come from scale rather than from a bug?
- Activity: A trace table with a deliberately wrong row, so students watch a method accept -400 degrees and report a status.
Thermostatwas chosen because an impossible value needs no domain knowledge to spot, and it scales into the impact ideas.
Prototype:
- A reference guide, one running example (ClimateSense), five short big ideas with runnable Java, four Popcorn Hacks, and a predict-the-output check.
- Students revise the broken method into a guarded one after seeing it fail.
Test:
- Peers complete the Popcorn Hacks without extra explanation.
- Observe whether peers test edge cases before declaring a method done.
- Use what did not land to revise the lesson after teaching.
3. College Board Requirements
AP CSA Unit 3, Topic 3.2 Impact of Program Design. Quoted from the course and exam description (College Board, 2025, p. 82):
- 3.2.A “Explain the social and ethical implications of computing systems.” (Learning Objective; suggested skill 5.A)
- 3.2.A.1 “System reliability refers to the program being able to perform its tasks as expected under stated conditions without failure. Programmers should make an effort to maximize system reliability by testing the program with a variety of conditions.”
- 3.2.A.2 “The creation of programs has impacts on society, the economy, and culture. These impacts can be both beneficial and harmful. Programs meant to fill a need or solve a problem can have unintended harmful effects beyond their intended use.”
- 3.2.A.3 “Legal issues and intellectual property concerns arise when creating programs. Programmers often reuse code written by others and published as open source and free to use. Incorporation of code that is not published as open source requires the programmer to obtain permission and often purchase the code before integrating it into their program.”
| Big Idea | Covers |
|---|---|
| 1 and 2 | 3.2.A.1 |
| 3 and 4 | 3.2.A.2 |
| 5 | 3.2.A.3 |
4. Lesson Plan
Learning Objective: Explain why a program must be tested beyond one input, protect an object with a guard clause, and weigh the impacts and legal limits of the code you write.
Success Criteria: You can name edge cases for a method, write a guard that rejects them, describe a benefit and a harm of one program, and decide if online code is reusable from its license.
| Time | Segment |
|---|---|
| 5 min | Tech Talk and the running example |
| 25 min | Five big ideas with Popcorn Hacks 1 to 3 |
| 10 min | Practice: predict the output, Popcorn Hack 4 |
| 5 min | Answer check and quick review |
Tech Talk (5 minutes)
A program that runs is not a program that works. One passing test says nothing about the input you did not imagine, and once code ships it affects real people in ways its author never intended.
ClimateSense is a hypothetical connected thermostat in tens of thousands of homes. Everything below centers on its Thermostat class, which holds a target temperature and reports a status:
%%{init: {'theme':'base','fontFamily':'JetBrains Mono, monospace','themeVariables':{'fontFamily':'JetBrains Mono, monospace','fontSize':'14px','primaryColor':'#1e293b','primaryTextColor':'#f8fafc','primaryBorderColor':'#60a5fa','lineColor':'#94a3b8','edgeLabelBackground':'#0f172a'},'flowchart':{'curve':'basis','padding':16,'nodeSpacing':40,'rankSpacing':50}}}%%
flowchart LR
T(["targetTemp"]):::start --> A{"≥ 78 ?"}:::ask
A -- yes --> C(["COOLING"]):::info
A -- no --> B{"≤ 65 ?"}:::ask
B -- yes --> H(["HEATING"]):::bad
B -- no --> I(["IDLE"]):::good
classDef start fill:#1e3a8a,stroke:#60a5fa,color:#fff,stroke-width:2px
classDef ask fill:#78350f,stroke:#fbbf24,color:#fff,stroke-width:2px
classDef good fill:#14532d,stroke:#4ade80,color:#fff,stroke-width:2px
classDef bad fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px
classDef info fill:#1e293b,stroke:#94a3b8,color:#f8fafc,stroke-width:2px
5. Code Examples
Big Idea 1: System Reliability
System reliability means a program performs as expected, under stated conditions, without failure, not just for the one input you tried. Here is ClimateSense’s unguarded first version. Predict all three outputs before reading on.
Code Runner Challenge
Predict all three outputs first, then press Run -- does anything look wrong?
View IPYNB Source
// CODE_RUNNER: Predict all three outputs first, then press Run -- does anything look wrong?
public class Thermostat {
private String roomName;
private double targetTemp;
public Thermostat(String roomName, double targetTemp) {
this.roomName = roomName;
this.targetTemp = targetTemp;
}
public void setTargetTemp(double temp) {
targetTemp = temp;
}
public double getTargetTemp() { return targetTemp; }
public String getStatus() {
if (targetTemp >= 78) return "COOLING";
if (targetTemp <= 65) return "HEATING";
return "IDLE";
}
public static void main(String[] args) {
Thermostat t = new Thermostat("Lab", 72);
System.out.println(t.getStatus());
t.setTargetTemp(80);
System.out.println(t.getStatus());
t.setTargetTemp(-400); // below absolute zero
System.out.println(t.getStatus());
}
}
Thermostat.main(null);
| Call | targetTemp after |
getStatus() |
Correct? |
|---|---|---|---|
new Thermostat("Lab", 72) |
72.0 | IDLE |
Yes |
setTargetTemp(80) |
80.0 | COOLING |
Yes |
setTargetTemp(-400) |
-400.0 | HEATING |
No, below absolute zero |
No crash, no warning, just a confident wrong answer. A silent failure is worse than a crash, because a crash tells you where to look.
Popcorn Hack 1
What does getStatus() return for exactly 78? For exactly 65?
Code Runner Challenge
Popcorn Hack 1 -- Press Run and read the status for exactly 78 and exactly 65.
View IPYNB Source
// CODE_RUNNER: Popcorn Hack 1 -- Press Run and read the status for exactly 78 and exactly 65.
public class Thermostat {
private String roomName;
private double targetTemp;
public Thermostat(String roomName, double targetTemp) {
this.roomName = roomName;
this.targetTemp = targetTemp;
}
public void setTargetTemp(double temp) {
targetTemp = temp;
}
public double getTargetTemp() { return targetTemp; }
public String getStatus() {
if (targetTemp >= 78) return "COOLING";
if (targetTemp <= 65) return "HEATING";
return "IDLE";
}
public static void main(String[] args) {
Thermostat t = new Thermostat("Lab", 72);
t.setTargetTemp(78);
System.out.println("78 -> " + t.getStatus());
t.setTargetTemp(65);
System.out.println("65 -> " + t.getStatus());
}
}
Thermostat.main(null);
Big Idea 2: Guarding Against Bad Input
A guard clause sits at the top of a method and rejects invalid input before anything else happens. The first version had none, so -400, 9999, and Double.NaN all succeeded silently.
%%{init: {'theme':'base','fontFamily':'JetBrains Mono, monospace','themeVariables':{'fontFamily':'JetBrains Mono, monospace','fontSize':'14px','primaryColor':'#1e293b','primaryTextColor':'#f8fafc','primaryBorderColor':'#60a5fa','lineColor':'#94a3b8','edgeLabelBackground':'#0f172a'},'flowchart':{'curve':'basis','padding':16,'nodeSpacing':40,'rankSpacing':50}}}%%
flowchart LR
S("setTargetTemp(temp)"):::start --> V{"NaN, or outside
50 - 90 ?"}:::ask
V -- yes --> X("throw IllegalArgumentException
object unchanged"):::bad
V -- no --> OK("targetTemp = temp
value stored"):::good
classDef start fill:#1e3a8a,stroke:#60a5fa,color:#fff,stroke-width:2px
classDef ask fill:#78350f,stroke:#fbbf24,color:#fff,stroke-width:2px
classDef good fill:#14532d,stroke:#4ade80,color:#fff,stroke-width:2px
classDef bad fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px
classDef info fill:#1e293b,stroke:#94a3b8,color:#f8fafc,stroke-width:2px
Code Runner Challenge
Press Run to see the guard reject -400 and leave the object unchanged.
View IPYNB Source
// CODE_RUNNER: Press Run to see the guard reject -400 and leave the object unchanged.
public class Thermostat {
private String roomName;
private double targetTemp;
public Thermostat(String roomName, double targetTemp) {
this.roomName = roomName;
this.targetTemp = targetTemp;
}
public void setTargetTemp(double temp) {
if (Double.isNaN(temp) || temp < 50 || temp > 90) {
throw new IllegalArgumentException("Target temp out of range: " + temp);
}
targetTemp = temp;
}
public double getTargetTemp() { return targetTemp; }
public String getStatus() {
if (targetTemp >= 78) return "COOLING";
if (targetTemp <= 65) return "HEATING";
return "IDLE";
}
public static void main(String[] args) {
Thermostat t = new Thermostat("Lab", 72);
try {
t.setTargetTemp(-400);
} catch (IllegalArgumentException e) {
System.out.println("rejected -> " + e.getMessage());
}
System.out.println(t.getTargetTemp()); // still 72.0 -- the exception ran before the assignment
}
}
Thermostat.main(null);
A rejected call leaves the object exactly as it was. NaN needs its own check because it fails every comparison: NaN < 50 and NaN > 90 are both false, so a range check alone lets it through.
Popcorn Hack 2
Delete the Double.isNaN(temp) clause and predict what setTargetTemp(Double.NaN) does. Explain in one sentence.
Code Runner Challenge
Popcorn Hack 2 -- Press Run, then delete the Double.isNaN(temp) clause and run again. What changes?
View IPYNB Source
// CODE_RUNNER: Popcorn Hack 2 -- Press Run, then delete the Double.isNaN(temp) clause and run again. What changes?
public class Thermostat {
private String roomName;
private double targetTemp;
public Thermostat(String roomName, double targetTemp) {
this.roomName = roomName;
this.targetTemp = targetTemp;
}
public void setTargetTemp(double temp) {
if (Double.isNaN(temp) || temp < 50 || temp > 90) {
throw new IllegalArgumentException("Target temp out of range: " + temp);
}
targetTemp = temp;
}
public double getTargetTemp() { return targetTemp; }
public String getStatus() {
if (targetTemp >= 78) return "COOLING";
if (targetTemp <= 65) return "HEATING";
return "IDLE";
}
public static void main(String[] args) {
Thermostat t = new Thermostat("Lab", 72);
try {
t.setTargetTemp(Double.NaN);
System.out.println("accepted -> " + t.getTargetTemp());
} catch (IllegalArgumentException e) {
System.out.println("rejected -> " + e.getMessage());
}
}
}
Thermostat.main(null);
Big Idea 3: Social, Economic, and Cultural Impact
One program can be beneficial and harmful at once, and the harm does not cancel the benefit. ClimateSense in fifty thousand homes:
%%{init: {'theme':'base','fontFamily':'JetBrains Mono, monospace','themeVariables':{'fontFamily':'JetBrains Mono, monospace','fontSize':'14px','primaryColor':'#1e293b','primaryTextColor':'#f8fafc','primaryBorderColor':'#60a5fa','lineColor':'#94a3b8','edgeLabelBackground':'#0f172a'},'flowchart':{'curve':'basis','padding':16,'nodeSpacing':40,'rankSpacing':50}}}%%
flowchart LR
C("ClimateSense
50,000 homes"):::start
C --> E("Energy use"):::info
C --> S("Auto scheduling"):::info
C --> R("Remote access"):::info
E --> E1("Lower bills,
less grid strain"):::good
S --> S1("Comfort without
manual effort"):::good
S --> S2("Penalizes
shift workers"):::bad
R --> R1("Adjust before
arriving"):::good
R --> R2("Needs smartphone
+ home internet"):::bad
classDef start fill:#1e3a8a,stroke:#60a5fa,color:#fff,stroke-width:2px
classDef ask fill:#78350f,stroke:#fbbf24,color:#fff,stroke-width:2px
classDef good fill:#14532d,stroke:#4ade80,color:#fff,stroke-width:2px
classDef bad fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px
classDef info fill:#1e293b,stroke:#94a3b8,color:#f8fafc,stroke-width:2px
None of the harms are bugs. They are consequences of reasonable design choices. Ask who is excluded, not just who is served.
Big Idea 4: Unintended Consequences
An unintended consequence is harm beyond a program’s intended use, even when the code works exactly as designed. Suppose ClimateSense raises every target 2 degrees during a heat wave to ease grid load:
%%{init: {'theme':'base','fontFamily':'JetBrains Mono, monospace','themeVariables':{'fontFamily':'JetBrains Mono, monospace','fontSize':'14px','primaryColor':'#1e293b','primaryTextColor':'#f8fafc','primaryBorderColor':'#60a5fa','lineColor':'#94a3b8','edgeLabelBackground':'#0f172a'},'flowchart':{'curve':'basis','padding':16,'nodeSpacing':40,'rankSpacing':50}}}%%
flowchart LR
A("+2 degrees
in one house"):::start --> B("Barely noticeable"):::good
A --> C("x 50,000 houses at once
demand shock on the grid"):::bad
A --> H("Medically vulnerable resident
real health risk"):::bad
classDef start fill:#1e3a8a,stroke:#60a5fa,color:#fff,stroke-width:2px
classDef ask fill:#78350f,stroke:#fbbf24,color:#fff,stroke-width:2px
classDef good fill:#14532d,stroke:#4ade80,color:#fff,stroke-width:2px
classDef bad fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px
classDef info fill:#1e293b,stroke:#94a3b8,color:#f8fafc,stroke-width:2px
Nobody wrote a harmful feature. The harm comes from scale, not intent.
Big Idea 5: Intellectual Property and Code Reuse
Reusing code is normal. The rules are about which code, under what terms.
%%{init: {'theme':'base','fontFamily':'JetBrains Mono, monospace','themeVariables':{'fontFamily':'JetBrains Mono, monospace','fontSize':'14px','primaryColor':'#1e293b','primaryTextColor':'#f8fafc','primaryBorderColor':'#60a5fa','lineColor':'#94a3b8','edgeLabelBackground':'#0f172a'},'flowchart':{'curve':'basis','padding':16,'nodeSpacing':40,'rankSpacing':50}}}%%
flowchart TD
Q("Found code online"):::start --> L{"License stated?"}:::ask
L -- no --> N("Treat as NOT free to use
write your own"):::bad
L -- yes --> O{"Open source?"}:::ask
O -- yes --> Y("Use it,
follow the license"):::good
O -- no --> P("Only with permission"):::bad
classDef start fill:#1e3a8a,stroke:#60a5fa,color:#fff,stroke-width:2px
classDef ask fill:#78350f,stroke:#fbbf24,color:#fff,stroke-width:2px
classDef good fill:#14532d,stroke:#4ade80,color:#fff,stroke-width:2px
classDef bad fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:2px
classDef info fill:#1e293b,stroke:#94a3b8,color:#f8fafc,stroke-width:2px
Readable is not reusable. A public repo is visible to everyone, which says nothing about permission.
Popcorn Hack 3
A classmate says a four-line snippet is too short for licensing to apply. Respond.
Code Runner Challenge
Popcorn Hack 3 -- A classmate says a four-line snippet is too short for licensing. Run it, then change license to "MIT" and "proprietary" and compare.
View IPYNB Source
// CODE_RUNNER: Popcorn Hack 3 -- A classmate says a four-line snippet is too short for licensing. Run it, then change license to "MIT" and "proprietary" and compare.
public class LicenseCheck {
static String mayReuse(String license) {
if (license.equals("none")) return "NO -- no license means no permission. Write your own.";
if (license.equals("MIT") || license.equals("Apache-2.0")) return "YES -- follow the license (keep the notice).";
if (license.equals("proprietary")) return "ONLY with the owner's permission.";
return "Unknown license -- read it before reusing.";
}
public static void main(String[] args) {
String snippet = "int add(int a, int b) { return a + b; }"; // short, but still someone's work
String license = "none"; // try "MIT", "proprietary"
System.out.println("Snippet: " + snippet);
System.out.println("License: " + license);
System.out.println("May I reuse it? " + mayReuse(license));
}
}
LicenseCheck.main(null);
6. Hacks & Practice Tasks
Predict the Output
Using the guarded setTargetTemp, pick your answer (A to D) first, then run the cell to check it.
Code Runner Challenge
Pick your answer (A-D) below first, then press Run to check it.
View IPYNB Source
// CODE_RUNNER: Pick your answer (A-D) below first, then press Run to check it.
public class Thermostat {
private String roomName;
private double targetTemp;
public Thermostat(String roomName, double targetTemp) {
this.roomName = roomName;
this.targetTemp = targetTemp;
}
public void setTargetTemp(double temp) {
if (Double.isNaN(temp) || temp < 50 || temp > 90) {
throw new IllegalArgumentException("Target temp out of range: " + temp);
}
targetTemp = temp;
}
public double getTargetTemp() { return targetTemp; }
public String getStatus() {
if (targetTemp >= 78) return "COOLING";
if (targetTemp <= 65) return "HEATING";
return "IDLE";
}
public static void main(String[] args) {
Thermostat t = new Thermostat("Lab", 72);
try {
t.setTargetTemp(95);
} catch (IllegalArgumentException e) {
System.out.println("rejected");
}
System.out.println(t.getTargetTemp());
System.out.println(t.getStatus());
}
}
Thermostat.main(null);
A. 95.0, then COOLING
B. rejected, then 72.0, then IDLE
C. rejected, then 95.0, then COOLING
D. rejected, then 72.0, then COOLING
Popcorn Hack 4
Finish setRoomName so it rejects null, empty, and whitespace-only names, validating before assigning. The first attempt should be accepted and the next three rejected.
Code Runner Challenge
Popcorn Hack 4 -- Finish setRoomName so it rejects null, empty, and whitespace-only names, then press Run. Expect 1 accepted, 3 rejected.
View IPYNB Source
// CODE_RUNNER: Popcorn Hack 4 -- Finish setRoomName so it rejects null, empty, and whitespace-only names, then press Run. Expect 1 accepted, 3 rejected.
public class Room {
private String roomName;
public Room(String roomName) { this.roomName = roomName; }
public void setRoomName(String name) {
// TODO: reject null, empty, and whitespace-only names.
roomName = name;
}
public String getRoomName() { return roomName; }
public static void main(String[] args) {
Room r = new Room("Lab");
String[] attempts = { "Nursery", null, "", " " };
for (String a : attempts) {
try {
r.setRoomName(a);
System.out.println("accepted -> [" + r.getRoomName() + "]");
} catch (IllegalArgumentException e) {
System.out.println("rejected -> " + e.getMessage());
}
}
}
}
Room.main(null);
Answer Check
Predict the Output: B. 95 is outside 50-90, so the guard throws before the assignment; the object keeps 72.0 and getStatus() returns IDLE. (A and C assume the value was stored anyway; D contradicts its own state.)
Popcorn Hack 4. Reject null (a later method call on it would throw NullPointerException far from the real cause) and empty or whitespace-only names (an unidentifiable room is unusable). The rule: a mutator rejects anything that leaves the object unable to function.
Quick Review
- Reliability: works under all stated conditions, not just the one input you tried.
- Test edges: zero, negative, empty,
null,NaN, boundaries. - Guard clause: runs before assignment, so invalid input is never stored.
- Silent acceptance is more dangerous than a crash.
- Impact: one program can help and harm, and harm beyond intended use comes from scale, not intent.
- Reuse: visible code is not free code. No license means no permission.
7. References
College Board. (2025). AP Computer Science A course and exam description [Effective fall 2025], Unit 3, Topic 3.2, p. 82.
Learn more about Topic 3.2 (College Board):
- Topic 3.2 Impact of Program Design in the AP CSA Course and Exam Description: opens the PDF directly on the Topic 3.2 page (printed page 82).
- AP Computer Science A course page: course overview and Unit 3 resources.
- AP CSA Course and Exam Description (full PDF): all units and topics.
Further reading:
- Oracle, “Class Double”:
isNaNandNaNcomparison behavior. - Oracle, “Class IllegalArgumentException”.
- Open Source Initiative, “The Open Source Definition”.
- GitHub Docs, “Licensing a repository”.
Submit Assignment
Need to update a submission later? Open the submissions dashboard.