Opening the book…
Dependencies are the joints where systems break and change spreads. When they are hidden inside functions as global lookups or new instances, you cannot see what a piece of code needs, cannot test it in isolation, and cannot swap a part without hunting through the body. Making dependencies visible at the boundary turns coupling into something you can read and control.
Pass dependencies in through parameters or constructors rather than reaching for them internally. Let a function's signature tell the whole story of what it touches. When a class quietly constructs a database client or reads a global, promote that to an argument so callers, and tests, can see and substitute it.
function sendInvoice(order) {
const db = new Database();
const mailer = Mailer.global();
// deps buried inside
}function sendInvoice(order, db, mailer) {
// deps stated in the signature
}Stable, ubiquitous utilities like logging or a clock can be injected but often are not worth the ceremony for small scripts. Pure functions with no external needs require none of this. Match the rigor to the blast radius.