User:OliverCharles/Data Access Objects

From MusicBrainz Wiki
Jump to navigationJump to search

Overview

The NGS codebase for MusicBrainz brings a new type of object model to the table - the methodology by which data is manipulated. Previously, MusicBrainz used a single class for each type of resource, where the class represented both an instance of the object and a method to manipulate sets of data (for example, updating artists was done by the same object that represents a single artist). Overtime, this method has begun to show signs of weakness, and it was necessary to give this API a rehaul for NGS.

NGS now uses a pattern known as "data access objects." The Sun document goes into more detail about this pattern, but essentially it decouples the represent of instances from the logic to fetch them. This decoupling is reflected by 2 separate namespaces in the code: MusicBrainz::Server::Data holds all data access objects, and MusicBrainz::Server::Entity holds transfer objects - instances of data.

Transfer objects

Transfer objects are very lightweight. They represent a single resource (such as an artist, a medium, a recording, etc) and are little more than Moose objects with a little bit of sugar and data-formatting functions.

The key point about transfer objects is that they do not hold an application context, and are thus mostly incapable of side effects. This isn't to say they are immutable, but changes to a single transfer object will not be persisted to storage without the use of a data access object (nor is the transfer object able to retrieve additional data).

Data access objects

Data access objects are more complex. Generally, data access objects follow a singleton pattern - they are accessed via a context object, of which there is normally only one throughout the lifetime of the application.

There are a few important naming conventions used in data access objects, that will help understand the type of data that you can expect. Firstly are the =get_= family of functions. These functions take some form of key, and will return all matching resources, where the key matches identically. For example, most data access objects have a =get_by_id= method (provided by the =Data::Entity= base class).

Alongside the =get_= methods are =find_= methods. These methods attempt to do some type of search, and do not guarantee to return data. For example, =find_by_name= in the Editor data access object attempts to search for editors by name.

Future plans

Currently, SQL is being written verbatim in the code, which is inflexible. This has a significant drawback that it cannot be manipulated as data. aCiD2 has completed some refactoring that moves all SQL generation to use Fey, and is just about complete (but will be waiting for an appropriate time to be reviewed).