Hands-on, evergreen guides for developers. Each one is built around real commands and worked examples, and says plainly when not to use the thing it covers.
Browse everything below, newest first.
Hands-on, evergreen guides for developers. Each one is built around real commands and worked examples, and says plainly when not to use the thing it covers.
Browse everything below, newest first.
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. ...
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: ...
A login endpoint hands back a JWT, and you have three places to put it: a cookie, localStorage, or sessionStorage. Pick the wrong one and either an XSS bug walks off with the token, or the token never reaches your API. All three store strings in the browser. They differ on who can read them, how long they last, and whether the server ever sees them. How localStorage, sessionStorage and cookies differ localStorage and sessionStorage are the same API, the Storage interface: setItem, getItem, removeItem, clear, string keys and string values. The difference is lifetime. localStorage survives closing the browser and rebooting the machine, and stays until something clears it. Safari is the exception: with tracking prevention on, it deletes script-written storage for a site the user hasn’t interacted with in seven days. sessionStorage belongs to one tab and dies when that tab closes. Type the same URL into a second tab and you get a fresh, empty sessionStorage; only “Duplicate tab” copies it over. ...
A Python dictionary lookup takes about 100 nanoseconds whether the dict holds 1,000 keys or 1,000,000. A nested loop that checks a list for duplicates takes half a millisecond on 200 items and 136 milliseconds on 3,200. Sixteen times the input, nearly 280 times the wait. Same machine, same Python. Big O notation is the name for that difference. What Big O notation measures Big O describes how the running time (or memory use) of a piece of code grows as the input gets larger. It is not a stopwatch reading, and it does not care whether your laptop is fast or slow. It cares about the shape of the growth curve: when you double the input, does the time double, quadruple, or barely move? ...
Run git reset --hard on a commit your team already pulled and you’ve just made your history disagree with theirs. Run git revert on a typo you haven’t pushed and you’ve added a pointless commit to the log. Git has four undo commands, restore, reset, commit --amend and revert, and they are not interchangeable. Pick the wrong one and it either does nothing or does far more than you wanted. ...
A wrong JOIN doesn’t throw an error. It runs, returns a result set, and the rows are wrong: customers missing, totals inflated, orphaned records hidden. Most of the time the query asked for exactly what it got, and the author picked the wrong join type or filtered in the wrong place. A join combines rows from two tables on a condition you write. Which rows survive depends on the join type, and the six types below give six different answers from the same two tables. ...
Here is a class you cannot unit test without a live database and a working SMTP server: 1 2 3 4 5 6 7 8 9 10 11 public class OrderService { private readonly SqlOrderRepository _repository = new SqlOrderRepository("Server=prod-db;Database=Orders;..."); private readonly SmtpEmailSender _emailSender = new SmtpEmailSender("smtp.company.com"); public void PlaceOrder(Order order) { _repository.Save(order); _emailSender.Send(order.CustomerEmail, "Order confirmed"); } } OrderService builds its own SqlOrderRepository and SmtpEmailSender with new, connection string and all. Every test that touches PlaceOrder needs a real Orders database and a real mail server, or it fails before your assertion runs. The logic you want to test is two lines: save the order, send the confirmation. It’s welded to two concrete classes you can’t swap out. ...
Install two Python projects on the same machine and the second one can break the first. One needs requests==2.28, the other needs requests==2.32, and pip has exactly one system-wide site-packages directory to write into. The last install wins, silently. You find out when the other project starts throwing errors that have nothing to do with the code you just changed. A virtual environment gives each project its own site-packages. Nothing global gets touched, and two projects can depend on incompatible versions of the same library without either one noticing. ...
A function can have 100% unit test coverage and the page that calls it can still return a 500 in production. That is not a contradiction. Unit tests, integration tests, and end-to-end tests check different things, and a suite that’s heavy on one and light on another has a specific, predictable hole in it. What unit, integration, and end-to-end tests each check Take a sign-up feature: a function validates the input, writes a row to a database, and sends a welcome email. Three tests can cover it, and each one answers a different question. ...
Run this in Node or a browser console: 1 2 3 4 console.log("1"); setTimeout(() => console.log("2"), 0); Promise.resolve().then(() => console.log("3")); console.log("4"); The output is 1 4 3 2. A setTimeout with a 0ms delay still runs after the promise callback, and both wait for every line of synchronous code below them. async/await is built on this ordering, not on something new. Most of the surprising behavior in async JavaScript comes from writing await as if it paused the whole program, when it only pauses the function it’s in. ...