Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Handle invalid input consistently across methods that share the same check
When several methods validate the same kind of input, they must agree on what happens for invalid input — don't have one path throw while another silently returns empty.
Bad example
| 1 | private buildKey(id: number): string { |
| 2 | if (!isValidId(id)) { |
| 3 | throw new Error(`Invalid id: ${id}`); // throws |
| 4 | } |
| 5 | return `item:${id}`; |
| 6 | } |
| 7 |
|
| 8 | async getById(id: number): Promise<Item[]> { |
| 9 | if (!isValidId(id)) { |
| 10 | return []; // silently returns empty for the SAME invalid input |
| 11 | } |
| 12 | const key = this.buildKey(id); |
| 13 | return this.load(key); |
| 14 | } |
Explanation (EN)
The same invalid id produces two different behaviors depending on which method is entered first — `getById` returns `[]`, but if `buildKey` is reached it throws. Callers can't predict the contract.
Objašnjenje (HR)
Isti nevalidan id dovodi do dva razlicita ponasanja ovisno o tome koja se metoda prva izvrsi — `getById` vraca `[]`, ali ako se dode do `buildKey` baca iznimku. Pozivatelji ne mogu predvidjeti ugovor metode.
Good example
| 1 | // Pick ONE contract for invalid input and apply it everywhere. |
| 2 | // Here: tolerate-and-skip (return empty), no throwing. |
| 3 | private buildKey(id: number): string { |
| 4 | return `item:${id}`; |
| 5 | } |
| 6 |
|
| 7 | async getById(id: number): Promise<Item[]> { |
| 8 | if (!isValidId(id)) { |
| 9 | return []; |
| 10 | } |
| 11 | return this.load(this.buildKey(id)); |
| 12 | } |
Explanation (EN)
Validation lives in one place and resolves invalid input the same way (return empty) across all methods. The key-builder no longer second-guesses input the caller already screened.
Objašnjenje (HR)
Validacija je na jednom mjestu i nevalidan unos rjesava se jednako (vraca prazno) u svim metodama. Graditelj kljuca vise ne provjerava unos koji je pozivatelj vec filtrirao.
Notes (EN)
If you prefer the throwing contract, then the lookup methods should throw too — the point is consistency, not which strategy you pick. Document the chosen contract on the interface.
Bilješke (HR)
Ako vise volite ugovor koji baca iznimku, onda i metode za dohvacanje trebaju bacati — poanta je u dosljednosti, a ne u tome koju strategiju odaberete. Dokumentirajte odabrani ugovor na sucelju.