❔ Can someone help me understand this statement around dependency inversion with an example?

I was refreshing my memory on SOLID based on conversations in #chat today, and a particular statement is hurting my head this evening:
High-level modules should not depend on low-level modules. Both should depend on abstractions.
I'm wondering, can someone share a simple example that demonstrates how both can depend on abstractions? I think I'm just overthinking it at the moment.
4 Replies
Hazel 🌊💃
Hazel 🌊💃OP15mo ago
For clarity, the both part throws me off. I found another article that says what I currently do is fine So something like:
public interface IUserService {
Task<User> Get(Guid id, CancellationToken cancellationToken);
}
public class CachedUserService : IUserService {
...
public async Task<User> Get(Guid id, CancellationToken cancellationToken) {
if (_cache.TryGetValue(id, out User cachedUser))
return cachedUser;

var request = new UserByIdRequest(id);
var user = await _mediator.Send(request);
return user;
}
}
public class Sample {
private readonly IUserService _userService;
public Sample(IUserService userService) =>
_userService = userService;

// terrible example
public async Task PrintUsername(Guid userId) {
User user = await _userService.Get(userId);
if (user is null) {
Console.WriteLine($"User `{userId}` not found.");
return;
}

Console.WriteLine($"User `{userId}` has a username of `{user.Username ?? "null"}`.");
}
}
public interface IUserService {
Task<User> Get(Guid id, CancellationToken cancellationToken);
}
public class CachedUserService : IUserService {
...
public async Task<User> Get(Guid id, CancellationToken cancellationToken) {
if (_cache.TryGetValue(id, out User cachedUser))
return cachedUser;

var request = new UserByIdRequest(id);
var user = await _mediator.Send(request);
return user;
}
}
public class Sample {
private readonly IUserService _userService;
public Sample(IUserService userService) =>
_userService = userService;

// terrible example
public async Task PrintUsername(Guid userId) {
User user = await _userService.Get(userId);
if (user is null) {
Console.WriteLine($"User `{userId}` not found.");
return;
}

Console.WriteLine($"User `{userId}` has a username of `{user.Username ?? "null"}`.");
}
}
My understanding is that this is fine since I'm consuming the user service through an interface instead of interacting with CachedUserService directly.
x0rld 👻 🎃
x0rld 👻 🎃15mo ago
yeap your Sample doesn't need to know if there is any cache system
Omnissiah
Omnissiah15mo ago
yeah, essentially you have a layer of implementations which inherits from an accompanying layer of abstractions when you have to use something from that layer you register dependencies in a module and you're done ymmv depending on where those abstractions are, sometimes architecture could be more sophisticated than that
Accord
Accord15mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server