Introduction
DIP Bad Example — Complete Guide is essential for .NET developers building ShopNest Enterprise Clean Architecture Platform — Toolliyo's 100-article SOLID Design Principles master path covering SRP, OCP, LSP, ISP, DIP, refactoring, Clean Architecture, and enterprise projects. Every article includes minimum 2 detailed enterprise real-world examples with bad code before good code (banking, e-commerce, ERP, SaaS, healthcare).
In Indian delivery projects (TCS, Infosys, Wipro), interviewers expect dip bad example with real HDFC-style banking SRP fixes, Flipkart OCP payment strategies, TCS ERP LSP, Freshworks ISP, or Apollo hospital refactoring examples — not toy animal demos. This article delivers two mandatory enterprise examples on Notifications.
After this article you will
- Explain DIP Bad Example in plain English and in SOLID principles and maintainable OOP terms
- Implement dip bad example in ShopNest Enterprise Clean Architecture Platform (Notifications)
- Compare the wrong approach vs the production-ready enterprise approach
- Answer fresher, mid-level, and senior SOLID principles and clean architecture interview questions confidently
- Connect this lesson to Article 53 and the 100-article SOLID Principles roadmap
Prerequisites
- Software: .NET 8 SDK, VS 2022 or VS Code, SQL Server Express / LocalDB
- Knowledge: C# basics
- Previous: Article 51 — Dependency Inversion Principle — Complete Guide
- Time: 24 min reading + 30–45 min hands-on
Concept deep-dive
Level 1 — Analogy
DIP is like hiring through HR contracts — departments depend on job descriptions, not specific people.
Level 2 — Technical
DIP Bad Example integrates with the LINQ query layer: write queries against IEnumerable or IQueryable, understand deferred execution, project to DTOs for ShopNest Clean Architecture reports. On ShopNest Clean Architecture this powers Notifications without coupling UI to database internals.
Level 3 — Architecture
[Browser] → [HTTPS/Kestrel] → [Middleware Pipeline]
→ [Routing] → [Controller Action] → [Service Layer]
→ [EF Core / Identity] → [Razor View Engine] → [HTML Response]
Common misconceptions
❌ MYTH: DIP Bad Example is only for senior architects on huge systems.
✅ TRUTH: ShopNest applies SOLID from day one — even small modules benefit when the team will grow beyond one developer.
❌ MYTH: SOLID means creating an interface for everything.
✅ TRUTH: Apply abstractions when you have multiple implementations or need test doubles — not prematurely.
❌ MYTH: Refactoring to SOLID always slows delivery.
✅ TRUTH: Short-term cost pays back in faster testing, fewer merge conflicts, and safer changes within 2–3 sprints.
Project structure
ShopNest Clean Architecture/
├── ShopNest Clean Architecture/
├── src/
│ ├── ShopNest Clean Architecture.Api/ ← ASP.NET Core Web API
│ ├── ShopNest Clean Architecture.Core/ ← Repository interfaces
│ ├── ShopNest Clean Architecture.AdoNet/ ← SqlConnection, SPs, transactions
│ ├── ShopNest Clean Architecture.Reports/ ← Streaming readers, GL reports
│ └── ShopNest Clean Architecture.Tests/ ← Integration tests (Testcontainers SQL)
├── sql/
│ ├── migrations/
│ └── stored-procedures/
└── docker-compose.yml ← SQL Server 2022 + Redis
Step-by-Step Implementation — ShopNest (Notifications)
Follow the prompt template: create project → core classes → interfaces → pattern implementation → client code → run → enterprise refactor.
Step 1 — The wrong way
// ❌ BAD — god class violates SRP, tight coupling, untestable
public class OrderService {
public void PlaceOrder(Order o) {
Validate(o);
_context.Orders.Add(o);
_context.SaveChanges();
SendEmail(o.CustomerEmail);
GenerateInvoicePdf(o);
}
}
Step 2 — The right way
// ✅ CORRECT — DIP Bad Example on ShopNest (Notifications) — SOLID applied
public sealed class PlaceOrderHandler(IOrderRepository repo, INotificationService notify)
: IRequestHandler
{
public async Task Handle(PlaceOrderCommand cmd, CancellationToken ct) {
var order = Order.Create(cmd.CustomerId, cmd.Items);
await repo.AddAsync(order, ct);
await notify.OrderPlacedAsync(order, ct);
return Result.Success(order.Id);
}
}
Step 3 — Apply DIP Bad Example
// DIP Bad Example — ShopNest Clean Architecture (Notifications)
builder.Services.AddScoped<IDIPBadExampleService, DIPBadExampleService>();
dotnet run --project ShopNest Clean Architecture.Api
# Verify DIP Bad Example — check Swagger UI and unit test pass rate and integration tests pass
The problem before SOLID
Without SOLID, ShopNest teams hit: tight coupling, god classes, untestable controllers, merge conflicts, and fear of refactoring. Indian IT projects (TCS, Infosys, Wipro) lose sprints when legacy code has no clear boundaries.
- Tight coupling — change SMS provider, break ledger posting
- Testing difficulty — cannot mock database from controller
- Scalability — monolith teams block each other
- Bug-prone — one class, five reasons to change
Real-time refactoring walkthrough — DIP
Step 1: Identify violation → Step 2: Extract interface → Step 3: Split responsibilities → Step 4: Register in DI → Step 5: Add unit tests. Commit each step separately for safe code review.
Real-World Example 1 — ShopNest Payments — DIP with Repository Abstractions
MANDATORY enterprise scenario (Payment Gateway): DIP Bad Example applied in ShopNest Clean Architecture Notifications.
Business problem
PaymentController directly new SqlPaymentRepository() — untestable, tied to SQL Server. DIP: IPaymentRepository injected; infrastructure implements ADO.NET or EF Core without changing API layer.
Before SOLID — bad design
public class PaymentController : ControllerBase {
public IActionResult Pay(PaymentDto dto) {
var repo = new SqlPaymentRepository(Configuration.GetConnectionString("Default"));
repo.Save(dto);
return Ok();
}
}
After SOLID — production design
public class PaymentController(IPaymentRepository repo) : ControllerBase {
[HttpPost]
public async Task<IActionResult> Pay(PaymentDto dto, CancellationToken ct) {
await repo.SaveAsync(dto.ToEntity(), ct);
return Ok();
}
}
// Program.cs: builder.Services.AddScoped<IPaymentRepository, SqlPaymentRepository>();
Outcome
xUnit tests use InMemoryPaymentRepository; swap to Azure SQL with one DI line in production.
Real-World Example 2 — HDFC Core Banking — Transfer Service SRP Violation Fix
MANDATORY enterprise scenario (Indian Banking): DIP Bad Example applied in ShopNest Clean Architecture Notifications.
Business problem
A 2,400-line TransferService handled validation, ledger posting, SMS, fraud checks, and PDF receipts. One change to SMS template broke fund transfers in production. SRP split into ITransferValidator, ILedgerService, IFraudChecker, INotificationService.
Before SOLID — bad design
// ❌ GOD CLASS — violates SRP
public class TransferService {
public void Transfer(Account from, Account to, decimal amount) {
ValidateAccounts(from, to);
CheckFraud(from, amount);
UpdateLedger(from, to, amount);
SendSms(from.CustomerPhone, "Transfer done");
GeneratePdfReceipt(from, to, amount);
}
}
After SOLID — production design
// ✅ SRP — each class one reason to change
public sealed class TransferOrchestrator {
private readonly ITransferValidator _validator;
private readonly ILedgerService _ledger;
private readonly IFraudChecker _fraud;
private readonly INotificationService _notify;
public async Task<Result> ExecuteAsync(TransferRequest req, CancellationToken ct) {
await _validator.ValidateAsync(req, ct);
await _fraud.CheckAsync(req, ct);
await _ledger.PostAsync(req, ct);
await _notify.SendTransferConfirmationAsync(req, ct);
return Result.Success();
}
}
Outcome
Deployment frequency for transfer module increased 4x; unit test count from 12 to 89 isolated tests.
SOLID in ASP.NET Core — DIP Bad Example
Register abstractions in Program.cs as Scoped. Keep controllers thin — delegate to MediatR handlers or application services. ShopNest Clean Architecture: Domain → Application → Infrastructure → Api.
builder.Services.AddScoped<IOrderService, OrderService>();
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(PlaceOrderHandler).Assembly));
SOLID and design patterns
SRP enables focused classes; OCP pairs with Strategy and Factory; LSP guards inheritance; ISP splits fat interfaces; DIP powers DI and Repository pattern. SOLID is the foundation — patterns are the tools.
Unit testing with SOLID
var mock = new Mock<IOrderRepository>();
mock.Setup(r => r.GetAsync(1, default)).ReturnsAsync(new Order(1, 100m));
var handler = new GetOrderHandler(mock.Object);
var result = await handler.Handle(new GetOrderQuery(1), default);
Assert.Equal(100m, result.Total);
Common errors & fixes
🔴 Mistake 1: God classes with 10+ responsibilities (SRP violation)
✅ Fix: Extract focused services — one reason to change per class.
🔴 Mistake 2: Adding if/else chains for every new feature (OCP violation)
✅ Fix: Use Strategy or Factory; extend via new classes, not edits.
🔴 Mistake 3: Subclass throws NotImplementedException (LSP violation)
✅ Fix: Prefer composition and role-specific interfaces over broken inheritance.
🔴 Mistake 4: Controllers new-ing concrete repositories (DIP violation)
✅ Fix: Inject interfaces via constructor DI in ASP.NET Core.
Best practices
- 🟢 Use async/await end-to-end for database and I/O calls
- 🟢 Register DbContext as Scoped; avoid capturing it in singletons
- 🟡 Use IQueryable until the last moment; avoid multiple enumeration; project with Select before ToList
- 🟡 Prefer method syntax for complex chains; use query syntax for joins when readability wins
- 🔴 Log structured data with Serilog — include OrderId, UserId, not passwords
- 🔴 Use HTTPS, secure cookies, and authorization policies in production
Interview questions
Fresher level
Q1: What is DIP Bad Example in ASP.NET Core MVC?
A: DIP Bad Example is a core MVC capability used in ShopNest Clean Architecture for Notifications. Explain in one sentence, then describe controller/view/service placement.
Q2: How would you implement DIP Bad Example on a TCS-style delivery project?
A: Deferred execution, IQueryable pipelines, Select projection, Skip/Take pagination, and SQL logging in development.
Q3: IEnumerable vs IQueryable — when to use which?
A: IEnumerable for in-memory collections; IQueryable for EF Core database queries that translate to SQL.
Mid / senior level
Q4: Explain LINQ deferred execution and query translation briefly.
A: LINQ → Expression Tree → IQueryProvider → SQL (EF) or Iterator (in-memory) → Results.
Q5: Common production mistake with this topic?
A: Skipping validation, exposing secrets in Git, or untested edge cases (null model, unauthorized user).
Q6: .NET LINQ vs SQL — when to push logic to database?
A: Core is cross-platform, faster, cloud-ready; Framework is maintenance mode on Windows/IIS.
Coding round
Implement DIP Bad Example for ShopNest Notifications: show interface, concrete class, DI registration, and xUnit test with mock.
public class DIPBadExamplePatternTests
{
[Fact]
public async Task ExecuteAsync_ReturnsSuccess()
{
var mock = new Mock();
mock.Setup(s => s.ExecuteAsync(It.IsAny(), default))
.ReturnsAsync(Result.Success("test-id"));
var result = await mock.Object.ExecuteAsync(new Request("test-id"));
Assert.True(result.IsSuccess);
}
}
Summary & next steps
- Article 52: DIP Bad Example — Complete Guide
- Module: Module 6: Dependency Inversion Principle (DIP) · Level: INTERMEDIATE
- Applied to ShopNest Clean Architecture — Notifications
Previous: Dependency Inversion Principle — Complete Guide
Next: DIP Refactoring — Complete Guide
Practice: Add one small feature using today's pattern — commit with feat(solid): article-52.
FAQ
Q1: What is DIP Bad Example?
DIP Bad Example helps ShopNest Clean Architecture implement Notifications using C# 12 LINQ with EF Core where applicable.
Q2: Do I need Visual Studio?
No — .NET 8 SDK with VS Code + C# Dev Kit works. Visual Studio 2022 Community is recommended for MVC scaffolding.
Q3: Is this asked in Indian IT interviews?
Yes — MVC topics from Modules 1–6 appear in TCS, Infosys, Wipro campus drives; architecture modules in lateral hires.
Q4: Which .NET version?
Examples target .NET 8 LTS and .NET 9 with C# 12+ syntax.
Q5: How does this fit ShopNest Clean Architecture?
Article 52 adds dip bad example to Notifications. By Article 100 you have a portfolio-ready ShopNest Clean Architecture enterprise database layer.