Reputation: 7524
In book 'Patterns of Enterprise Application Architecture', following is stated:
When thinking of a system in terms of layers, you imagine the principal subsystems in the software arranged in some form of layer cake, where each layer rests on a lower layer. In this scheme the higher layer uses various services defined by the lower layer, but the lower layer is unaware of the higher layer.
On other hand, in book 'Agile Principles, Patterns, and Practices', following is stated on Dependency-Inversion Principle:
High-level modules should not depend on low-level modules. Both should depend on abstractions.
This sort of confuses me. Am I mixing two different things here?
Upvotes: 0
Views: 65
Reputation: 3784
Am I mixing two different things here?
Yes.
The first case is about dependencies at run-time while the second case is about dependencies at compile-time.
For example, at run-time, business layer can call the functions/methods implemented in database layer. But at compile-time, business layer code does not mention any code in database layer. This is usually achieved with Polymorphism.
Upvotes: 0
Reputation: 2535
I suppose that it could speak to some the same principles, but at different levels of granularity. I would still view Dependency Inversion as something that stands on its own, however.
In the first instance, consider this example - in a simple layered architecture, you might have a presentation layer built in JavaScript, a business logic layer built in Java, and a data layer in SQL Server. These layers could be developed by different teams of people. The presentation layer knows how to make API calls to the business logic layer, but not the other way around. The business logic layer knows how to read/write to and from the database layer, but not the other way around. The distinction here happens at a high-level - you might even call it conceptual.
In the second instance, you want to prevent scenarios where supposedly generic code depends on specific implementations - and at this point, I see it as a relatively low-level concern that falls within the scope of a particular application (i.e. in code, not conceptually as in the previous example). If you have code that writes to a database, but you want to support different implementations - e.g. MySQL and SQL Server, where each of those might have some specific intricacies, don't make the calling code explicitly depend on either of those - abstract away the complexity through an interface. This is what the Dependency Inversion Principle addresses (see below).
public class UserService {
public UserRepository repository;
public void setUserRepository(UserRepository repository) {
this.repository = repository; //Is this a MySqlRepository or a SqlServerRepository? We don't care - the dependency is managed outside and we can change it without changing this class.
}
public void persistUser() {
this.repository.persist(user); //We just care about the abstraction - the interface.
}
}
Upvotes: 2