Think of your local transit agency as a dependency container. You just want to get from Point A to Point B, right? If the train’s out of commission, the agency swaps in a replacement bus, no problem. You don’t really care how they get you there, just that you arrive.

Disclaimer: Analogies are helpful, but they don’t always align perfectly. Let’s explore how this real-world scenario, despite its limitations, mirrors the powerful concept of dependency injection in software engineering.
Why
Software maintenance dominates engineering time, far outweighing new development. Simplicity is the key to manageable maintenance. Just as mechanics prefer Toyota’s straightforward engines to BMW’s complexity, engineers work more effectively with clean, well-structured code.
Dependency Injection makes software more flexible because components can be easily swapped out (like replacing that engine with a different one). It also makes testing easier since you can substitute real components with test versions. And maintenance becomes simpler because changes to one component don’t necessarily require changes to others.
How
Let’s get straight to the code
// Interface that defines our transit service contract
public interface ITransitService
{
string GetTransitInfo();
}
// Implementation for train transit
public class TrainTransitService : ITransitService
{
public string GetTransitInfo()
{
return "Train departing from platform 3 at 14:30";
}
}
// Implementation for bus transit
public class BusTransitService : ITransitService
{
public string GetTransitInfo()
{
return "Bus departing from bay 7 at 15:15";
}
}
[ApiController]
[Route("api/[controller]")]
public class TransportController : ControllerBase
{
private readonly ITransitService _transitService;
// Constructor injection - the dependency is injected here
public TransportController(ITransitService transitService)
{
_transitService = transitService;
}
[HttpGet]
public IActionResult Get()
{
return Ok(_transitService.GetTransitInfo());
}
}
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
// Register the service implementation to use
// Change this line to use TrainTransitService instead if
// needed or this can be controller
// via some external config/parameter which swaps this dynamically
builder.Services.AddScoped<ITransitService, BusTransitService>();
var app = builder.Build();
app.MapControllers();
app.Run();
}
}
Keep it clean, keep it maintainable, and you’ll thank yourself later when you’re not spending your weekends debugging spaghetti code instead of enjoying actual spaghetti!
Now, go fix some bugs!
