What Is a Hash Table? Hashing and Collisions Explained

Look a key up in a Python dict with ten entries and it takes the same time as looking one up in a dict with ten million. That is not an accident of a fast language. Python’s dict, Java’s HashMap and JavaScript’s Map are all hash tables, and the whole design exists to make lookup, insert and delete run in O(1) on average. Big O notation gives that lookup the label “constant time”. Here is the mechanism that earns it. ...

November 4, 2026 Â· 8 min Â· 1514 words Â· SpaghettiCoder

Mocks vs Stubs vs Fakes vs Spies: Test Doubles Explained

A test for place_order needs a payment gateway, an SMS client, and a tax calculator. Wire in the real ones and every test run charges a card and texts a phone number. A unit test is supposed to run in milliseconds with no network, so all three have to be swapped for something else. That “something else” comes in five kinds, each solving a different problem, and treating them as interchangeable is why “just mock it” arguments in code review go in circles. ...

November 2, 2026 Â· 8 min Â· 1579 words Â· SpaghettiCoder

Regular Expressions Explained: How Regex Really Works

<.+> against <b>bold</b> and <i>italic</i> doesn’t match <b>. It matches the whole string, from the first < to the very last >. Nothing is broken. That is what a greedy quantifier is supposed to do, and it is also the most common “regex is matching too much” bug there is. Once you know what the engine does while it reads your pattern, this bug and most of its relatives stop being mysteries. ...

October 28, 2026 Â· 8 min Â· 1540 words Â· SpaghettiCoder

What Is Unicode and How UTF-8 Encoding Works

Open a file saved as UTF-8 in a tool that assumes a different encoding and cafĂ© turns into café. The bytes on disk did not change. Only the rule used to turn those bytes back into characters did, and the two rules disagree about what byte 0xC3 means. Most “weird characters” bugs come from the same mismatch: broken filenames, mangled form submissions, emoji that crash a database insert, two strings that look identical but fail an equality check. Behind each one is the same confusion between two separate things, Unicode and UTF-8. ...

October 20, 2026 Â· 8 min Â· 1514 words Â· SpaghettiCoder

What Is TDD and How the Red-Green-Refactor Cycle Works

A test written after the code tends to check what the code does, not what it was supposed to do. Test-driven development fixes that by flipping the order: write the test, watch it fail, then write the smallest piece of code that makes it pass. Because the test exists before the code it checks, it can’t quietly confirm whatever the code happens to return. Kent Beck formalized the loop as red, green, refactor in his 2002 book Test-Driven Development: By Example. The name stuck. ...

October 18, 2026 Â· 7 min Â· 1346 words Â· SpaghettiCoder

Recursion Explained: When to Use It and When Not To

A function that calls itself has a maximum depth, and it is smaller than most people expect: 1,000 calls in CPython by default, roughly 10,000-15,000 in Node and browser engines depending on how much each frame holds. Go past it and the program does not slow down gracefully. It crashes. Python raises RecursionError: maximum recursion depth exceeded; JavaScript raises RangeError: Maximum call stack size exceeded. Both errors have the same cause, and once you see it you will know when recursion is the right tool and when it is a liability. ...

October 13, 2026 Â· 7 min Â· 1408 words Â· SpaghettiCoder

SOLID Principles Explained With Python Examples

A class that saves a user to the database, sends them a welcome email, and formats a receipt is one change away from breaking two features it has nothing to do with. Touch the email template and you risk the database write. Touch the receipt layout and you risk the email. SOLID is five rules aimed at that kind of entanglement, each from a different angle, and they share one idea: a class should change for one reason, and the rest of the code should depend on what something promises to do rather than how it does it. ...

October 10, 2026 Â· 9 min Â· 1863 words Â· SpaghettiCoder

What Is a Race Condition and How to Fix One

Two requests hit the same “withdraw $100” endpoint half a millisecond apart. The account has $150. Both requests read that balance, both see enough funds, both approve, both subtract $100. The account ends at -$50, and no branch in the code should have allowed it. That is a race condition: the output depends on which operation happens to finish first, and “first” was never something the code decided. What causes a race condition? You need two ingredients at once: shared mutable state, and more than one path of execution touching it without coordination. The paths can be threads, async tasks, processes, or two servers hitting the same database row. Take away either ingredient and the bug disappears. A single thread can’t race against itself, and immutable state can’t be corrupted by being read twice. ...

October 9, 2026 Â· 9 min Â· 1803 words Â· SpaghettiCoder

Python Decorators Explained With Examples

What a decorator actually does to your function You want to time every function that calls a slow external API. You can paste time.perf_counter() calls into each one, or write the measurement once and apply it everywhere. A decorator is the second option. It is a function that takes another function, wraps it in extra behavior, and returns the wrapped version under the original name. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import time def timed(func): def wrapper(*args, **kwargs): start = time.perf_counter() result = func(*args, **kwargs) elapsed = time.perf_counter() - start print(f"{func.__name__} took {elapsed:.3f}s") return result return wrapper @timed def fetch_price(ticker): time.sleep(0.2) # stand-in for a network call return 142.50 fetch_price("AAPL") # fetch_price took 0.201s @timed above def fetch_price is shorthand for fetch_price = timed(fetch_price). Python calls timed once, right after fetch_price is defined, and rebinds the name fetch_price to whatever timed returns. That’s all the @ does. ...

October 7, 2026 Â· 6 min Â· 1244 words Â· SpaghettiCoder

Why 0.1 + 0.2 Doesn't Equal 0.3: Floating-Point Explained

Run 0.1 + 0.2 in a Python shell and it does not return 0.3. It returns 0.30000000000000004. Try it in JavaScript, Java, Go, C, or Rust and you get the same sixteen-digit tail. Every one of those languages is doing exactly what the hardware standard tells it to. A number that needs infinitely many binary digits is being squeezed into 64 bits, and something has to give. Why 0.1 can’t be stored exactly in binary Computers store floating-point numbers in base 2. In base 2, the fraction 1/10 is a repeating expansion, the same way 1/3 repeats forever in base 10 (0.3333...). Written out, 0.1 in binary starts: ...

October 6, 2026 Â· 6 min Â· 1108 words Â· SpaghettiCoder