Files
AgentCompany/builtin-skills/software-engineer/clean-code/references/err-avoid-null.md
T
ZacharyZhang-NY e74dafcd36 Silence render-disposed spam, unbreak bundled skills, drop board wake
Three independently ugly bugs that all fed the same log flood:

* Electron's `WebFrameMain.send` writes every "Render frame was disposed"
  to stderr via `console.error`. When the worker fans a second
  agent-event past a reloading renderer, we produced thousands of
  identical lines and stalled the main loop on stderr I/O. Added a
  `mainFrame.detached` guard so the send is short-circuited before
  Electron's own catch block fires, and installed a targeted filter in
  `suppress-warnings.ts` (now actually imported from the entry point)
  so the specific `console.error("Error sending from webFrameMain:"…)`
  noise never reaches the terminal. Any other payload still surfaces.

* `dispatchAgentMessage` accepted the human-reader sentinel as a wake
  target when an agent replied to `__board__` — `wakeAgentIfPossible`
  then called `db.getAgent("__board__")`, threw, and the dispatcher
  kept repeating on every send. Strip `HUMAN_SENDER_ID` at
  `resolveMessageWakeTargets`, and keep a defense-in-depth guard in the
  heartbeat so a stray caller (future automation fan-out) cannot
  reintroduce the crash.

* Pi's skills loader rejects any SKILL.md whose frontmatter `name`
  diverges from its parent directory. The four bundled `my-writing-style`
  copies declared `name: writing-style-skill`, so every install emitted
  a warning and dropped the skill. They also lived as orphan gitlinks
  (mode 160000 without .gitmodules), and the global `*.md` gitignore
  hid every other SKILL.md from version control. Fixed the frontmatter
  to match the dir, converted the dangling submodules to plain trees,
  and allowlisted `builtin-skills/**/*.md` so a fresh clone carries the
  catalogue instead of silently losing it.
2026-04-20 08:13:48 -04:00

79 lines
2.2 KiB
Markdown

---
title: Avoid Returning and Passing Null
impact: HIGH
impactDescription: eliminates NullPointerException risk
tags: err, null, optional, null-object
---
## Avoid Returning and Passing Null
Returning null creates work for callers and invites errors. One missing null check leads to NullPointerException. Throw exceptions, return empty collections, or use the Special Case / Null Object pattern.
**Incorrect (returning null):**
```java
public List<Employee> getEmployees() {
if (thereAreNoEmployees) {
return null; // Caller must check for null
}
return employees;
}
// Every caller must do this
List<Employee> employees = getEmployees();
if (employees != null) { // Easy to forget
for (Employee e : employees) {
pay(e);
}
}
// Passing null
public double calculatePay(Employee employee, Money bonus) {
// What if bonus is null?
}
calculatePay(employee, null); // What does null mean?
```
**Correct (avoid null entirely):**
```java
// Return empty collection instead of null
public List<Employee> getEmployees() {
if (thereAreNoEmployees) {
return Collections.emptyList();
}
return employees;
}
// Clean caller code
for (Employee e : getEmployees()) {
pay(e);
}
// Use Optional for truly optional values
public Optional<Employee> findById(Long id) {
return Optional.ofNullable(employeeMap.get(id));
}
// Use Special Case object
public interface BillingPlan {
Money getRate();
}
public class NullBillingPlan implements BillingPlan {
public Money getRate() {
return Money.ZERO;
}
}
// Explicit parameters instead of null
public double calculatePay(Employee employee, Money bonus) { /* ... */ }
public double calculatePayWithoutBonus(Employee employee) { /* ... */ }
```
**When null/nullable is acceptable:**
- Language-level nullable types with compiler enforcement (Kotlin `?`, TypeScript `strictNullChecks`, Rust `Option<T>`) make null safe because the compiler forces handling. The problem is untracked nullability, not the concept itself.
- Interop with APIs or frameworks that require null (e.g., JDBC, some serialization libraries).
Reference: [Clean Code, Chapter 7: Error Handling](https://www.oreilly.com/library/view/clean-code-a/9780136083238/)