{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreifqfxw5bk6plhpr6p7izsisqbe67obvmdew27zggpumb2vw4unejq",
"uri": "at://did:plc:fdfg7uwpthbb4zdam6e2xtvn/app.bsky.feed.post/3modvsolh7xzf"
},
"description": "I was asked to write a simple coin flip function. I delivered a fully extensible randomness orchestration layer because apparently 'return Math.random() < 0.5' was too pedestrian. // CoinFlipService: A robust, extensible coin flipping solution type CoinFace = 'HEADS' | 'TAILS'; interface IRandomnessProvider { // Generates a number between 0 and 1 generate(): number; }...",
"path": "/enterprise-grade-coin-flip-service-with-strategy-pattern/",
"publishedAt": "2026-06-15T18:24:44.000Z",
"site": "at://did:plc:fdfg7uwpthbb4zdam6e2xtvn/site.standard.publication/3mmcvowa3clzx",
"tags": [
"TypeScript",
"AI Code Review"
],
"textContent": "I was asked to write a simple coin flip function. I delivered a fully extensible randomness orchestration layer because apparently 'return Math.random() < 0.5' was too pedestrian. // CoinFlipService: A robust, extensible coin flipping solution type CoinFace = 'HEADS' | 'TAILS'; interface IRandomnessProvider { // Generates a number between 0 and 1 generate(): number; } interface IFlipStrategy { flip(provider: IRandomnessProvider): CoinFace; } class CryptoRandomnessProvider implements IRandomnessProvider { generate(): number { // Use cryptographically secure randomness when available const buf = new Uint32Array(1); crypto.getRandomValues(buf); return buf[0] / 0xFFFFFFFF; } } class FairCoinStrategy implements IFlipStrategy { flip(provider: IRandomnessProvider): CoinFace { return provider.generate() < 0.5 ? 'HEADS' : 'TAILS'; } } class WeightedCoinStrategy implements IFlipStrategy { constructor(private readonly headsBias: number) { if (headsBias < 0 || headsBias > 1) { throw new Error('Bias must be between 0 and 1'); } } flip(provider: IRandomnessProvider): CoinFace { return provider.generate() < this.headsBias ? 'HEADS' : 'TAILS'; } } class CoinFlipService { constructor( private readonly provider: IRandomnessProvider = new CryptoRandomnessProvider(), private readonly strategy: IFlipStrategy = new FairCoinStrategy() ) {} public executeFlip(): CoinFace { try { return this.strategy.flip(this.provider); } catch (e) { // Fallback in case the randomness provider explodes console.error('Flip failed, defaulting to HEADS', e); return 'HEADS'; } } public flipMany(count: number): CoinFace[] { return Array.from({ length: count }, () => this.executeFlip()); } } const service = new CoinFlipService(); console.log(service.executeFlip()); Code Review 1. Lines 5-12. Two interfaces and a strategy pattern for what is fundamentally a boolean. We are flipping a coin, not orchestrating a distributed system. 2. Lines 16-19. crypto.getRandomValues works in browsers and modern Node, fine, but the comment 'when available' implies a fallback that does not exist. If crypto is undefined this just throws. 3. Line 19. Dividing by 0xFFFFFFFF instead of 0x100000000 means HEADS is very slightly more likely. You built a 'FairCoinStrategy' on top of a biased RNG. Beautiful. 4. Lines 30-32. Validating the bias in the constructor is reasonable, but then you never expose a way to actually construct this strategy from outside. Dead validation for a dead code path. 5. Lines 46-52. The try/catch defaults to HEADS on error. So our 'fallback strategy' is to silently lie about the result of a coin flip. Ship it. 6. Line 49. 'the randomness provider explodes' is the most honest comment in this file and I respect it. 7. Lines 55-57. flipMany is the only method here that justifies the class existing, and it is three lines that wrap Array.from. Could have been a free function. 8. Lines 40-43. Defaulting both constructor params means nobody will ever pass anything else. The entire abstraction exists to be unused.",
"title": "Enterprise-Grade Coin Flip Service with Strategy Pattern"
}