2

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_encoded, 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 the ResourceType was person, it could map to /api/1/person/{resourceId} and the table persons (or people, 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.

4
  • 1
    It looks a bit like you are trying to badly reinvent the document database. I'd check out something in that sphere . . . Commented Nov 18, 2011 at 22:17
  • @WyattBarnett You are going to have to give me a link, I'm not exactly sure what you are talking about. Commented Nov 18, 2011 at 22:35
  • @WyattBarnett I think you misunderstand: I'm creating an object that knows what data is essential for it to be stored under any circumstances, not creating a database. Care to explain more? Commented Nov 18, 2011 at 23:38

2 Answers 2

1

Not all ORM's are the same. For instance, (sorry for my non-PHP background here -- see later) Hibernate and NHibernate make a big deal out of the fact that your entity classes are "Plain Old Java Objects" or "Plain Old CLR Objects" (aka POJO's and POCO's). EntityFramework 4.0 apparently allows this too.

That means they don't know anything about persisting themselves. So if you use the Repository Pattern, then your persistence logic is all hidden away. Inside your repository implementation you create a mapping from your entities to whatever database/service/whatever you want. (N)Hibernate has options for specifying this in XML or fluently with an API. However, you could replace this with a repository that persists your entities over a web service.

Downsides?

It's more work than entities auto-generated from the database, if your database already exists. (On the other hand, (N)Hibernate can actually generate your database schema for you based on your entity mapping.)

Feasible?

Yes, I think it's just the repository pattern with another name. However, I don't like the idea of having to derive my entity classes from a special base class, as you've defined.

Improve it?

Careful not to re-invent the wheel here. Make sure you do a good survey of all your options first, like Doctrine or Propel. Many brighter minds than us have been working at this kind of stuff for decades now, and they've come up with some very advanced and flexible solutions.

3
  • Keep in mind it's not deriving from a class, it's implementing an interface. In my mind that's a WORLD of difference. Also, Doctrine and Propel are obviously the the main choices in PHP and I dislike both of them (Although I haven't tried Doctrine 2, which is supposedly like Hibernate). They both violate the principles I outlined in my question. Commented Nov 18, 2011 at 20:28
  • After checking out Doctrine 2, it is very tightly coupled with the data objects. That's not really attractive either. Commented Nov 18, 2011 at 21:04
  • @LeviMorrison - isn't the repository pattern the best bet anyway? You define your entities, then you define repositories that know how to persist the entities, and inject those repositories into your business classes. If you want to change out your peristence logic, you change out your repository. The entities and business logic remain unaffected. Commented Nov 22, 2011 at 16:57
1

There is much talk about ORM's being storage-independent, under the theory that you might want to change out the underlying data store. In practice this hardly ever happens, and it's a lot of work when it does; it's not simply a matter of unplugging one vendor's RDBMS and plugging in another.

You can stay vendor-independent by sticking to a dialect of SQL that works with all the vendors, but in the end you're still talking about a SQL database (as opposed to a key-value store like BigTable), and if you need SQL's unique capabilities, then you're pretty much stuck with an RDBMS.

Notice that the farther away you get from SQL, the less shape your data objects have, and the more work you have to do yourself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.