I wrote a post some time ago called Inheritance with symfony and Doctrine ORM. In it I explored the different types of inheritance Doctrine ORM offers. I have a strong opinion on which is best; others strongly disagreed with what I said and it was clear the topic needed further exploration.
But maybe we’re barking up the wrong tree with the whole inheritance thing.
Since relational databases are relational and object-oriented programs are object-oriented, it seems that there’s a necessary awkwardness when trying to get the two paradigms to talk to each other in the same terms. As far as I know, no good solution exists.
I’ve come up with a solution to this problem by redefining the problem. Instead of asking, “How can I get a relational database to map nicely to inheriting classes?” I’ve said, “Let’s take away the inheritance. What happens when we get a relational database to make to a composite instead of an object hierarchy?” In my opinion, so far, it seems to work out pretty well. At least, better than inheritance. (By the way, I’m sure I’m not the first person to think about this problem this way.)
Let’s look at an example. Let’s say we have three types of vehicle: a bicycle, a golf cart and a car. I would design this with four tables:
vehicle make model color bicycle vehicle_id style golf_cart vehicle_id number_of_seats car vehicle_id body_type transmission_type
Here’s how you might create a new Car (in Ruby):
car = Car.new # Vehicle attributes car.vehicle.make = "Geo" car.vehicle.model = "Metro" car.vehicle.color = "red" # Car attributes car.body_type = "coupe" car.transmission_type = "manual" car.save
The advantage I see to this is that you don’t have to have object-relational mapping handling inheritance. I admit that it’s a little awkward to have to say car.vehicle.model instead of just car.model. However, I don’t know of any ORM design that’s free of awkwardness and to me this is less awkward than trying to tell your ORM which tables inherit from which and all that stuff.
Maybe this is a great idea. Maybe it’s not a very good idea at all. I’m not sure yet. I do know that I used inheritance in a good-sized app and it’s caused me headaches, and I used composition in a different good-sized app and it’s working out great. I’ll probably use composition for everything in any future projects. I’d love to know what you think of it.
I have been struggling with doctrine inheritance these days, and in the end decided to go with the column aggregation model. Not the prettiest thing, but the only approach that enables “almost” real object inheritance.
As for your alternative, nice concept, but has some serious disadvantages.
Relationally its ok (not logically, but it works), but as oop goes, it has nothing to to with it pretty much. There is no real inheritance, logically vehicle in not a part of the car, it is the car.
Lets say you have some real “part of” object. For example car can be composed of various parts: engine, seats, headlights, bumpers, stereo…. It could be very confusing to treat the vehicle object same as “real parts”.
For “smaller” sites which basically just do CRUD operations I guess it is ok, as for larger projects, personally I wouldn’t be very happy to compromise oop over db. In the end you are working with objects, db is just a storage dump.
As for the “awkward” syntax, take a look at Record Filters. Never used them, but from the docs it looks like it could do the trick and make the inheritance even more “fake” :)
http://www.doctrine-project.org/projects/orm/1.2/docs/manual/defining-models/en#record-filters
You’re right, there is no real inheritance. What I’m suggesting is an ALTERNATIVE to inheritance, since ORMs seem to handle inheritance poorly. I agree that what I’m suggesting still has its awkward parts but I feel like this is at least an improvement over the other methods I’ve seen. Also keep in mind that you can have OOP without having inheritance everywhere.
Having said that, my goal is to find the best way to handle the whole ORM problem, not to convince anyone how good this particular idea is. Any good idea should be able to stand up to scrutiny, so I’m glad people you’re scrutinizing this idea.