Active Record Design pattern is one of the design patterns used in Domain Driven Design. This pattern encapsulates the database and business logic implementation, and group them together, usually in a class, that developers can create. This pattern is mostly familiar in Object Oriented Programming due to its structure.
Benefits of Active Record Pattern
- Combines data and behaviour into a single object
- Simplifies CRUD operations, making it quick to implement
- Keeps business logic close to data it operates on
When to use it
- Small applications
- You build simple CRUD apps
- Your app and your database are very similar
- You focus on Rapid development
When should you avoid it
- Your app is not a typical CRUD app and has complex business logic that do not map to database tables
- When your classes are bloated with loads of methods
- Large scale apps
- Microservices
- When your database schema changes frequently
Example
In the example below, a Database operation has been encapsulated in a User class and provides methods, such as save, delete, findById and findAll and all of them interact with database.
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export class User {
id: number;
name: string;
email: string;
constructor(name: string, email: string, id?: number) {
this.name = name;
this.email = email;
this.id = id || 0;
}
async save(): Promise<User> {
if (this.id === 0) {
const user = await prisma.user.create({
data: {
name: this.name,
email: this.email,
},
});
this.id = user.id;
return this;
} else {
await prisma.user.update({
where: { id: this.id },
data: {
name: this.name,
email: this.email,
},
});
return this;
}
}
static async findById(id: number): Promise<User | null> {
const user = await prisma.user.findUnique({ where: { id } });
if (!user) return null;
return new User(user.name, user.email, user.id);
}
static async findAll(): Promise<User[]> {
const users = await prisma.user.findMany();
return users.map(u => new User(u.name, u.email, u.id));
}
async delete(): Promise<void> {
if (this.id !== 0) {
await prisma.user.delete({ where: { id: this.id } });
}
}
}