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).
Single source of truth for shared serialized data-contract fields
Don't let two services independently hardcode field names for the same shared blob — define the shape once.
Bad example
| 1 | // writer service |
| 2 | const blob = { id, fullname, profileImage: user.image }; |
| 3 | cache.set(`user:${id}`, JSON.stringify(blob)); |
| 4 |
|
| 5 | // reader service (separate repo) |
| 6 | const data = JSON.parse(raw); |
| 7 | return { id: data.id, fullname: data.fullname, imageUrl: data.imageUrl }; |
Explanation (EN)
The reader guesses the key name (`imageUrl`) independently of what the writer actually serialized (`profileImage`). `data.imageUrl` is always `undefined`, `JSON.stringify` silently drops the key, and nothing ever throws — the field is just permanently missing.
Objašnjenje (HR)
Čitatelj sam pogađa naziv ključa (`imageUrl`) neovisno o tome što je pisac stvarno serijalizirao (`profileImage`). `data.imageUrl` je uvijek `undefined`, `JSON.stringify` tiho izbaci taj ključ, i ništa nikad ne baci grešku — polje jednostavno trajno nedostaje.
Good example
| 1 | // shared contract, imported/referenced by both sides |
| 2 | export interface ICachedUserBlob { |
| 3 | id: string; |
| 4 | fullname: string; |
| 5 | profileImage: string; |
| 6 | } |
| 7 |
|
| 8 | // reader |
| 9 | const data = JSON.parse(raw) as ICachedUserBlob; |
| 10 | return { id: data.id, fullname: data.fullname, imageUrl: data.profileImage }; |
Explanation (EN)
The blob's shape is defined once and referenced (or at minimum documented) by both the writer and the reader, so a field rename is a type error on both sides instead of a silent runtime mismatch.
Objašnjenje (HR)
Oblik bloba definiran je jednom i na njega se referencira (ili je barem dokumentiran) i pisac i čitatelj, pa je promjena naziva polja greška tipa na obje strane, a ne tiha runtime nepodudarnost.
Notes (EN)
If the two sides genuinely can't share a type import (separate repos), keep the contract documented in one place and add a runtime/integration test that round-trips a real payload.
Bilješke (HR)
Ako dvije strane stvarno ne mogu dijeliti type import (odvojeni repozitoriji), dokumentirati kontrakt na jednom mjestu i dodati integracijski test koji provjeri stvarni payload.