Refactoring 024 - Replace Global Variables with Dependency Injection
Break Hidden Dependencies for Cleaner Code

Iโm a senior software engineer loving clean code, and declarative designs. S.O.L.I.D. and agile methodologies fan.
Search for a command to run...
Break Hidden Dependencies for Cleaner Code

Iโm a senior software engineer loving clean code, and declarative designs. S.O.L.I.D. and agile methodologies fan.
No comments yet. Be the first to comment.
Approve the logic once, then let it run the same way forever.

Different stages need different brains.

One Second Brain doesn't scale past one skull.

Style errors double when nobody enforces them.

Know who speaks before the skill runs TL;DR: Always define a clear role at the top of every skill file so you know whose perspective drives the execution. Common Mistake โ You write a skill full of

TL;DR: Replace global variables with dependency injection to improve testability and reduce coupling. ๐
// This global variable holds the API configuration
const globalConfig = { apiUrl: "https://api.severance.com" };
function fetchOuties() {
return fetch(`${globalConfig.apiUrl}/outies`);
// globalConfig is NOT passed as parameter
}
function fetchOuties(parameterConfig) {
return fetch(`${parameterConfig.apiUrl}/outies`);
// 1. Identify global variables
// used across your codebase.
// 4. Refactor the existing code
// to use the new dependency-injected structure.
}
const applicationConfig = { apiUrl: "https://api.severance.com" };
// 2. Create a real-world abstraction
// to encapsulate these variables.
fetchOuties(applicationConfig);
// 3. Pass dependencies explicitly
// via function parameters or constructors.
// const globalConfig = { apiUrl: "https://api.severance.com" };
// 5. Remove the original
// global variable declarations.
// Why Is 'config' a Dependency?
// Because:
// outies() depends on knowing the API URL to work
// Without this information,
// The function can't perform its core task
// The dependency is
// explicitly declared in the function signature
A Step Beyond: API Reification
class ApiService {
constructor(parameterConfig) {
this.variableConfig = parameterConfig;
}
// parameterConfig, variableConfig
// and applicationConfig
// are very bad names.
// They are here to emphasize the change
fetchOuties() {
return fetch(`${this.variableConfig.apiUrl}/outies`);
}
}
const apiService =
new ApiService({ apiUrl: "https://api.severance.com" });
apiService.fetchOuties();
[X] Semi-Automatic
This refactoring is safe if you audit all global variable references and thoroughly test the code after injection.
Testability: Dependencies can be replaced (not mocked) for unit tests.
Explicit Contracts: Functions declare what they need.
Scalability: Configuration changes donโt require code edits.
Coupling: Code is less coupled.
By making dependencies explicit, the code mirrors real-world interactions where components rely on declared inputs, not hidden state.
You also reduce Coupling which is usually the more important problem you must solve.
Over-injection can lead to parameter bloat.
"But it's just a parameter!"
"This is too simple to be DI!"
"Dependency Injection vs Dependency Inversion"
You can use AI tools to analyze your codebase and identify global variables.
The AI can suggest where to implement dependency injection and help generate the necessary interfaces or classes for your dependencies.
Remember: AI Assistants make lots of mistakes
Suggested Prompt: 1. Identify global variables used across your codebase.2. Create a real-world abstraction to encapsulate these variables. 3. Pass dependencies explicitly via function parameters or constructors. 4. Refactor existing code to use the new dependency-injected structure. 5. Remove the original global variable declarations.
| Without Proper Instructions | With Specific Instructions |
| ChatGPT | ChatGPT |
| Claude | Claude |
| Perplexity | Perplexity |
| Copilot | Copilot |
| Gemini | Gemini |
| DeepSeek | DeepSeek |
| Meta AI | Meta AI |
| Qwen | Qwen |
[X] Intermediate
This article is part of the Refactoring Series.