Andrew Savetchuk
Andrew Savetchuk's Blog

Andrew Savetchuk's Blog

Overview of the Active Record Pattern

Overview of the Active Record Pattern

Description of the pattern with an example of implementation, its pros and cons, and suggestion of an alternative

Andrew Savetchuk's photo
Andrew Savetchuk
·Mar 19, 2022·

4 min read

Table of contents

  • Definition
  • Name origin
  • Implementation
  • When to use it
  • Criticism
  • Conclusion
  • Source

Definition

The active record design pattern (considered an architectural pattern) is an approach to accessing data in a database.

The active record is an object that wraps a row in the database table or view, encapsulates the database access and adds domain logic on that data. An object carries both data and behavior. Much of this data is persistent and needs to be stored in a database.

Active Record uses the most obvious approach, putting data access logic in the domain object. This way all people know how to read and write their data to and from the database. The interface on an object conforming to this pattern would include functions such as Insert, Update, and Delete, and properties that correspond more or less directly to the columns in the underlying database table.

After the creation of an object, a new row is added to the table upon save. Any object loaded gets its information from the database. When an object is updated, the corresponding row in the table is also updated. The wrapper class implements accessor methods or properties for each column in the table or view.

The active record pattern is becoming a core part of many programming frameworks that store in-memory object data in relational databases. It is commonly used by object persistence tools and in object-relational mapping (ORM).

Name origin

The pattern was named by Martin Fowler in his book Patterns of Enterprise Application Architecture (2003).

Implementation

This pattern is intended to make simple CRUD (Create, Read, Update, Delete) tasks quicker to achieve. For example, instead of writing a lot of SQL queries to insert or update many common and simple data objects, it allows us to simply assign values to the data object and run a command to save it, e.g. $object->save(). The SQL for inserting/updating data will be compiled and executed for us.

For example, if there is a table users in a database with columns name (string type) and age (number type), and the Active Record pattern is implemented in the class User, the pseudo-code

$user = new User();
$user->name = 'John Doe';
$user->age = 25;
$user->save();

will create a new row in the users table with the given values, and is roughly equivalent to the SQL command:

INSERT INTO users (name, age) VALUES ('John Doe', 25);

Conversely, the class can be used to query the database:

$user = User::where('name', 'John Doe')->first();

This will find a new User object based on the first matching row from the users table whose name column has the value "John Doe". The SQL command used might be similar to the following, depending on the SQL implementation details of the database:

SELECT * FROM users WHERE name = 'John Doe' LIMIT 1;

Most frameworks also implement data relationships within their respective Active Record models which can greatly simplify accessing data related to our object. For example, in Laravel, if we specified that a Category "has many" Product`s then after loading the Category object from the database, we can list its child Product`s with a simple line of code:

foreach ($category->products as $product) {
  echo $product->name;
}

When to use it

Active Record is a good choice for domain logic that is not too complex, such as creates, reads, updates, and deletes. Derivations and validations based on a single record work well in this structure.

Criticism

Mapping issues

Active Record has the primary advantage of simplicity. It is easy to build Active Records, and they are easy to understand. Their primary problem is that they work well only if the Active Record objects correspond directly to the database tables: an isomorphic schema.

If your business logic is complex, you will soon want to use your object's direct relationships, collections, inheritance, and so forth. These do not map easily onto Active Record, and adding them piecemeal gets very messy. That is what will lead you to use Data Mapper instead.

Testability

Due to the coupling of database interaction and application logic when using the active record pattern, unit testing an active record object without a database becomes difficult. These negative effects on the testability of the active record pattern can be reduced by using mocking or dependency injection frameworks to substitute the real data tier with a simulated one.

Distributed systems

Record-based patterns work poorly in distributed systems, especially where concurrency is impossible (e.g. offline). i.e. two updates both may have one field that is correct but only one of the two records can win.

Single responsibility principle and separation of concerns

Due to the strong coupling of database interaction and application logic, an active record object does not follow the single responsibility principle and separation of concerns as opposed to multitier architecture which properly addresses these practices.

Conclusion

Active Record is good for quick CRUD-based applications where the Model is relatively flat (as in, not a lot of class hierarchies). However, for applications with complex OO hierarchies, a DataMapper is probably a better solution.

Source

  1. Active record pattern - Wikipedia
  2. What is the purpose of Active Records? - StackOverflow
  3. Patterns of Enterprise Application Architecture (2003)

The end. I hope you found this article helpful. Stay tuned for more content!

If you want to support me, you can buy me a coffee :)

 
Share this