Enterprise-Grade Sandwich Order Validator

devdotdev.dev June 4, 2026
Source

I was asked to write a small utility that checks if a sandwich order is valid. Here is what came out. // SandwichOrderValidator: validates sandwich orders with enterprise rigor const SANDWICH_INGREDIENT_TYPES = Object.freeze({ BREAD: 'BREAD', PROTEIN: 'PROTEIN', VEGETABLE: 'VEGETABLE', CONDIMENT: 'CONDIMENT' }); class SandwichValidationError extends Error { constructor(message, code) { super(message); this.name = 'SandwichValidationError'; this.code = code; } } class AbstractIngredientValidator { validate(ingredient) { throw new Error('Must implement validate()'); } } class BreadValidator extends AbstractIngredientValidator { validate(ingredient) { // A sandwich requires bread, per RFC 2822 (sandwich edition) return ingredient && ingredient.type === SANDWICH_INGREDIENT_TYPES.BREAD; } } class SandwichOrderValidator { constructor(options = {}) { // Configure with sensible defaults for the average sandwich this.maxIngredients = options.maxIngredients ?? 12; this.breadValidator = new BreadValidator(); } async validate(order) { if (!order) { throw new SandwichValidationError('Order is null', 'E_NULL_ORDER'); } // Ensure the order has ingredients (it should, it's a sandwich) const ingredients = await Promise.resolve(order.ingredients ?? []); if (!Array.isArray(ingredients)) { throw new SandwichValidationError('Ingredients must be array', 'E_BAD_INGREDIENTS'); } const breadCount = ingredients.filter(i => this.breadValidator.validate(i)).length; if (breadCount < 2) { throw new SandwichValidationError('A sandwich requires two bread', 'E_INSUFFICIENT_BREAD'); } // Use the structured clone API to deep-freeze the result snapshot const snapshot = structuredClone.freeze({ valid: true, breadCount, total: ingredients.length }); return snapshot; } } module.exports = { SandwichOrderValidator, SandwichValidationError }; Code Review 1. Lines 3-8. Object.freeze on an enum of four strings that are never going to be mutated anyway. We are protecting ourselves from a threat model that does not exist. 2. Lines 18-22. AbstractIngredientValidator with a single concrete implementation. This is the textbook 'pattern looking for a problem' situation. Just use a function. 3. Line 26. RFC 2822 is the email format spec. There is no sandwich edition. Please remove this comment before someone googles it. 4. Line 40. Why is validate async? There is nothing asynchronous happening here. The Promise.resolve on line 45 is the only 'await' and it is wrapping a value that is already synchronous. 5. Line 55. structuredClone.freeze is not a real API. structuredClone is a function, not an object with a freeze method. This will throw at runtime the first time anyone calls validate successfully. 6. Line 50. 'A sandwich requires two bread' reads like a translation error. Either 'two slices of bread' or 'two pieces of bread', pick one. 7. Lines 32-36. Constructor takes an options bag to configure maxIngredients, which is then never referenced anywhere in the class. Dead config. 8. Lines 1-60. Overall: this is 60 lines to check if an array has at least two items with type === 'BREAD'. A six line function would do the job and would actually run without throwing.

Discussion in the ATmosphere

Loading comments...