❔ 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 🌊💃OP16mo 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
x0rld16mo ago
yeap your Sample doesn't need to know if there is any cache system
FestivalDelGelato
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
Accord16mo 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.

Did you find this page helpful?