CONCEPT 02 · FOUNDATIONS
Pure Core / Thin Shell
"Keep business logic separate from side effects."
Plain English
Separate your business logic from your side effects. Keep the logic — calculations, decisions, transformations — in pure functions that take inputs and return outputs with no database or network calls. Push all the I/O to the outer edge of your system. The result: you can test 90% of your code with zero mocks, zero test infrastructure.
Analogy
A chef vs. a waiter. The chef (pure core) just cooks: given ingredients, produces food. The waiter (thin shell) handles the messy outside world: taking orders, running cards, dealing with complaints. You can test the chef's recipes in a kitchen lab without any customers. The waiter's job is thin enough that you can trust it with minimal testing.
You already know this
A function that calculates a discount — no DB calls, just numbers in/outRedux reducers: (state, action) => newState — pure core state machinesSQL: the query is logic; the database engine is the shell that executes itDomain-driven design: the domain model is the pure core
Code Example
JavaScript
// THIN SHELL — handles I/O at the edge, nothing else
async function processOrder(userId, cartId, promoCode) {
// Step 1: get data (side effect)
const cart = await db.getCart(cartId);
const user = await db.getUser(userId);
// Step 2: pure core — all the business logic
const total = calculateOrderTotal(cart.items, promoCode);
const discount = getDiscount(user.tier, total);
const finalTotal = total - discount;
// Step 3: save results (side effect)
await db.saveOrder({ userId, total: finalTotal });
return finalTotal;
}
// PURE CORE — testable with zero infrastructure
function calculateOrderTotal(items, promoCode) {
const subtotal = items.reduce((sum, i) => sum + i.price * i.qty, 0);
const promo = promoCode === 'SAVE10' ? 0.10 : 0;
return subtotal * (1 - promo);
}
function getDiscount(userTier, amount) {
if (userTier === 'gold' && amount > 100) return amount * 0.05;
return 0;
}
// Tests need zero mocks, zero DB setup:
assert(calculateOrderTotal([{price:50,qty:2}], 'SAVE10') === 90);
assert(getDiscount('gold', 200) === 10);Apply when
▸Before writing any function: ask "does this need to touch the database/network/filesystem?" If no — keep it pure
▸When you find yourself writing mocks in tests: the function you're testing is probably doing too much — extract the pure logic
▸Complex business rules (pricing, eligibility, calculations) should always be pure — they're the most important to test
▸When onboarding new devs: pure core functions are self-documenting — they show what the system does, not how it talks to the world
Check Your Understanding
You're writing a function that calculates shipping cost based on weight, destination, and carrier rates. Where should this logic live?