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).
Extract framework-coupled boundary logic into a pure, testable function
Move boundary-condition parsing out of a framework-coupled handler into a pure function so it can be unit tested.
Bad example
| 1 | // route handler, imports the full app/model graph |
| 2 | export default asyncRoute(async (req, res) => { |
| 3 | const limit = Math.min(req.query.limit ?? 10, maxLimit); |
| 4 | const offset = Number(req.query.offset ?? 0); |
| 5 | // ... uses limit/offset |
| 6 | }); |
Explanation (EN)
The parsing logic can only be exercised by hitting the route through the full app, which pulls in the entire dependency graph. In practice this means the boundary cases (NaN, empty string, negative, duplicate query keys) never get a unit test and ship unverified.
Objašnjenje (HR)
Logika parsiranja može se testirati samo kroz cijelu aplikaciju preko rute, što povlači cijeli graf ovisnosti. U praksi to znači da rubni slučajevi (NaN, prazan string, negativan broj, dupli query ključevi) nikad ne dobiju unit test i idu u produkciju neprovjereni.
Good example
| 1 | // helpers/pagination.ts — no framework/model imports |
| 2 | export function parsePagination(query: Record<string, unknown>, maxLimit = 100) { |
| 3 | const limit = Math.min(Math.max(parseInt(String(query.limit ?? ''), 10) || 10, 1), maxLimit); |
| 4 | const offset = Math.max(parseInt(String(query.offset ?? ''), 10) || 0, 0); |
| 5 | return { limit, offset }; |
| 6 | } |
| 7 |
|
| 8 | // pagination.test.ts |
| 9 | it.each([['abc', 10], ['', 10], ['-5', 10]])('falls back to default for %s', (input, expected) => { |
| 10 | expect(parsePagination({ limit: input }).limit).toBe(expected); |
| 11 | }); |
| 12 |
|
| 13 | // route handler |
| 14 | const { limit, offset } = parsePagination(req.query); |
Explanation (EN)
The pure function has no dependency on the route/framework layer, so every boundary case can be exercised directly and cheaply in a unit test, without spinning up the app.
Objašnjenje (HR)
Čista funkcija nema ovisnost o sloju rute/frameworka, pa se svaki rubni slučaj može testirati izravno i jeftino u unit testu, bez pokretanja cijele aplikacije.