architecture3-tiermulti-tier

Removing database dependency from 3 tier architecture


I have worked as part of a team on some 3 tier applications for a considerable amount of time. I like this architecture, but in all of these applications I have noticed a heavy dependency of the topmost two layers on the data abstraction layer. This makes it hard to test and mock, since it is practically impossible to run the application or execute some methods without an existing database connection to a significantly large database. Is there a pattern that tries to solve this problem?


Solution

  • The Dependency Inversion Principle (DIP, one of the SOLID principles) exactly addresses the situation you describe:

    A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

    B. Abstractions should not depend on details. Details should depend on abstractions.

    For your situation, in particular part A is relevant: instead of having UI and business logic reference the data layer, those layers should only depend on abstractions (e.g. interfaces) that can be implemented in various ways. For the business layer this means that you define interfaces that the business layer depends on. The data layer provides an implementation of these interfaces.

    For tests you can provide another implementation of the relevant parts of the interfaces. This way, you can provide exactly the data that are used in a test instead of having a complete database ready for testing.

    This pattern is also referred to as Inversion of Control. You will find that you soon will have several interfaces that you need to provide implementations for when running your program. You can either solve this by using abstract factories or - easier - an Inversion of Control Container that is configured with registrations for the concrete types that implement the interfaces.

    Another pattern that you might find useful in this respect is the Repository pattern.