A few opinionated reasons I don't like the traditional ORM and ActiveRecord patterns:
- They work only with a database. Sometimes I'm dealing with objects from an API and other objects from a database. All the implementations I have seen don't allow for that. Feel free to clue me in if I'm wrong on this.
- They are brittle. Changes in the database will likely break your implemenation. Some implementations can help reduce this, but a few of the ones I've seen don't.
- Their very design is influenced by the database. If I want to switch to using an API, I'll have to redesign the object to get it to work (likely).
- It seems to violate the single-responsibility pattern. They know what they are and how they act, but they also know how they are created, destroyed and saved? Seems a bit much.
What about an approach that is somewhat more familiar in PHP: implementing an interface? In php 5.4, we'll have the JsonSerializable
interface that defines the data to be json_encode
d, so users will become accustomed to this type of thing. What if there was a ResourceSerializable
interface? This is still an ORM by name, but certainly not by tradition.
interface ResourceSerializable {
/**
* Returns the id that identifies the resource.
*/
function resourceId();
/**
* Returns the 'type' of the resource.
*/
function resourceType();
/**
* Returns the data to be serialized.
*/
function resourceSerialize();
}
Things might be poorly named, I'll take suggestions.
Notes:
ResourceId
will work for API's and databases. As long as your primary key in the database is the same as the resource ID in the API, there is no conflict. All of the API's I've worked with have a unique ID for the resource, so I don't see any issues there.ResourceType
is the group or type associated with the resource. You can use this to map the resource to an API call or a database table. If theResourceType
wasperson
, it could map to/api/1/person/{resourceId}
and the tablepersons
(orpeople
, if it's smart enough).- resourceSerialize() returns the data to be stored. Keys would identify API parameters and database table columns.
- This also seems easier to test than ActiveRecord / Orm implemenations. I haven't done much automated testing on traditional ActiveRecord/ORM implemenations, so this is merely a guess. But it seems that I being able to create objects independently of the library helps me. I don't have to use
load()
to get an existing resource, I can simply create one and set all the right properties. This is not so easy in the ActiveRecord / Orm implemenations I've dealt with.
Downsides:
- You need another object to serialize it. This also means you have more code in general as you have to use more objects.
- You have to map resource types to API calls and database tables. This is even more work, but some ORMs and ActiveRecord implementations require you to map objects to table names anyway.
Are there other downsides that you see?
Does this seem feasible to you?
How would you improve it?
Note: I almost asked this on StackOverflow because it might be too vague for their standards, but I'm still not really familiar with programmers.stackexchange.com, so please help me improve my question if it doesn't shape up to standards here.