What I Love About Data Access Layer (DAL) When Building Small Backend Projects
If you have a medium.com membership, I would appreciate it if you read this article on medium.com instead to support me~ Thank You! đ
Intro
The data access layer (DAL) is a concept that has been around for ages. After playing around with the concept for several months, I thought this would be a perfect time to share my thoughts as well as how I abstracted the DAL
for my small projects (with multiple backend microservices) using a common data access library :)
Note that my backend microservices were developed using Spring Boot.
What’s the Data Access Layer (DAL)Â for?
The primary idea of the DAL is for abstraction. It is a layer that is responsible for managing data storage (Eg. create, read, update, delete). Some of the reasons to implement a DAL include:
- Provide the flexibility to replace the underlying database/data source. Eg. changing from MySQL to MongoDB.
- Abstract and separate the data access logic from the business logic allowing for both layers to evolve independently.
- Encapsulate data to allow any microservice to interact with the data
Every developer/engineer implements the DAL concept to some extent. This could be in the form of using a data access object (DAO), data transfer object (DTO) or simply separating the logic for accessing the database.
Introducing the Data Access Library
It is possible to implement the DAL
concepts within your microservice’s codebase. However, if you are working with multiple microservices, you might want to abstract your DAL
further by implementing a common external data access library.
A data access library is a custom external library that contains all the data access logic (AKA CRUD operations).
Disclaimer: This is an anti-pattern for microservice architecture. Following the microservice architecture pattern (single responsibility & loose coupling), each microservice should have its own database and hence, no shared data access library.
However, not everyone has the luxury to have a database-per-microservice due to the cost & maintenance effort. This is especially true when you are in the midst of migrating from monolithic to microservice architecture or when you have a very small project.
In this article, I am mainly focusing on small projects. Hence, I will be using a single shared database for all my microservice persistent data. For projects with a shared database, you can either have a common shared data access library or group the data access library by features.
Option A: Shared Data Access Library
Having a shared external data access library is particularly useful when you have a small project as it allows you to centralize all your data access logic in a single library. The key advantage is that you will only have to maintain and modify a single library while the disadvantage is that the shared library will have redundant logic for all your microservices.
Additionally, one thing you have to consider is library versioning.
- If you publish your library, then you will need a way to check all your microservices that are using the library whenever you update the library.
- If you pair it with Monorepo, then you wouldn’t need to worry about versioning as your test cases will tell you which microservices are affected by the library’s modifications.
Option B: Grouping Data Access Library by Features
To prevent too much redundant logic within the data access library, instead of having 1 single shared data access library for all your microservices, you could create multiple data access libraries and group them by features. This largely depends on the size of your project as well as how many people are working on the project.
However, do note that having too many data access libraries can also introduce difficulties in maintaining them. When this occurs, you should re-think your entire microservice architecture.
How to implement the Data Access Library
Whether you are using a shared common data access library or multiple data access library, the steps to implement an external library are the same. To implement the data access library, we will need to create a library with the following components.
#1â-âData Transfer Object (DTO) &Â Entity
The Data Transfer Object (DTO) pattern is a design pattern that allows us to de-couple the data access layer (DAL) and the business service layer as illustrated below.
The DTO
acts like a contract for transferring data between the client (business layer) and the library (data access layer), but not the internals of the library. As the client only interacts using the DTO
, this allows us to have greater flexibility to modify the internals of the library without affecting the client as long as the DTO
doesn’t change.
Note: You can think of the
DTO
as an object that transfers data between the business layer and the data layer while theEntity
is an object that represents the database schema/table. Themapper
acts as a bridge to convert betweenDTO
andEntity
and vice versa.
#2â-âData Access Object (DAO)
The Data Access Object (DAO) pattern is a design pattern that provides an abstract interface for interacting with the database. The DTO
pattern handles the transfer of data while the DAO
pattern handles the CRUD logic.
The DAO
encapsulates the data access logic for the microservice’s business requirements. This allows us to switch the underlying data access logic easily without affecting the business logic (Eg. database/schema/logic changes).
Note: You can think of the
DAO
as an interface with CRUD logic. Eg. create a new user, update user information, delete a user, etcâŚ
However, it is important to not complicate the DAO
with complex business logic as that is best left at the business layer.
#3â-âIntegration Testing
There are 2 types of integration testing that should be written here.
- Integration testing with the databaseâ-âThis is to test if all DAO logic works with the database. Eg. Increasing database version.
- Integration testing between microservice and the data access libraryâ-âThis allows us to quickly identify any affected changes when the data access library is updated.
That’s it! These are the 3 main components you will need to implement the data access library.
Conclusionâ-âIs Data Access Library a good idea?
It really depends! I would recommend it if you are working on small projects. More often than so, you wouldn’t be spinning up one database per microservice from the get-go. Instead, you will probably have a single shared database due to the cost & simplicity.
In such cases, having a common data access library (with DAL
concepts applied) that can be used across multiple microservices is very useful as it provides a good abstraction layer for code maintenance. It is also very convenient as you only need to manage a single shared data access library for all database-related operations. Moreover, it improves code readability and encourages developers/engineers to write integration tests. However, do note that as it is a common data access library, the data access library will be inflated with lots of redundant codes.
Note: Even if you are not using a shared database, you can still apply the data access layer concepts or even abstract the logic into a data access library.
That’s it! This is a summary of what I have learned and applied which I have written in the context of small projects with shared databases. It is definitely not something that can be applied to everything, especially when the shared database & shared data access library introduces coupling to your architecture. That being said, I hope that this article is useful for all new developers/engineers to learn more about the DAL
concepts.
Hope you enjoy this article! I will be following up on this article with an example of how to implement and test the data access library in Spring Boot.
Thank you for reading till the end! â
If you enjoyed this article and would like to support my work, feel free to buy me a coffee on Ko-fi. Your support helps me keep creating, and I truly appreciate it! đ