Abstract vs Polymorphic

I have an abstract class. Another developer wants to take the abstract
class and make it polymorphic.

  1. Is this a good idea?
  2. The abstract class and its descendents have controllers. Will the
    controllers have to be changed?
  3. How is an abstract class implemented in terms of migrations and the
    database? Does the abstract class have a migration?

The idea is to minimize work.

Jan,

I believe the word “abstract class” is used in other languages to
describe what we in Ruby implement with a series of different patterns,
including mixins (modules), interfaces, services, and contexts. I will
admit that I rarely hear that term used in a Ruby context (because
really “abstract classes” aren’t native to Ruby, although you can use
Ruby to implement objects that will behave the way you are thinking of
an “abstract class” in another language).

It is difficult to answer your questions out of context, but generally
speaking I personally feel that polymorphism is like a secret magic
power that should be used only in rare circumstances. It may be
appropriate for you – but I’ve also seen many knee-jerk implementations
of polymorphism that ultimately turned out to be cases where greater
amounts of object encapsulation were more appropriate.

For example, let’s say you had a database of users, and some of these
users were also employees of the company. For employees, you need to
record many, many additional points of data (job title, reports to,
company division, etc). A Single Table Inheritance (STI) approach would
add all the fields to the users table. A object oriented (encapsulated)
approach would be to create a new table called Employees, and of course
use a foreign key to link the User record to the corresponding Employee
record.

If nearly all the records in the Users table were also Employees, STI
might make sense. If 99% of the users were not employees (thus making
all those fields blank on 99% of the records in the table) – a more
encapsulated data model might make more sense. (Of course there are
other factors too).

On the other hand, maybe you would have reasons to implement different
tables for Users and Employees, and in Ruby two different objects (User
and Employee) could share functionality via a mixin. I would ask
yourself these questions:

  1. What’s the most efficient way to encapsulate this data in the
    database?
  2. What’s the most efficient way to encapsulate this data in Ruby
    objects?
  3. How can I create an interface that abstracts the implementation from
    the interface as cleanly as possible?

Generally speaking, if I wanted to share functionality between objects,
I would start with a mix-in approach (using modules in Ruby). Wise
old-timer programmers say things like “prefer composition over
inheritance”
(Composition over inheritance - Wikipedia). In my
experience, developers who “go for” Polymorphic approaches (and STI,
which is a specific implementation of polymorphism in the context of a
RDBSM back-end) tend to like Inheritance a lot, and while not ruling out
STI for all situations, I look at it with a skeptical eye since I’ve
seen it implemented when it wasn’t necessary.

As far as question #2 - I can’t really answer that without looking at
your code.

As far as question #3 - as I said above, it’s not immediately clear
exactly the kind of Ruby implementation of “abstract class” you are
referring to since AFAIK the idea of an abstract class is not native to
Ruby. Migrations affect database tables, so if you are implementing your
classes with an underlying database table, you will write a migration to
affect the database table if it needs to be changed (or created, as the
case may be), regardless of how the Ruby (/ActiveRecord) objects that
read from/write to those database tables are defined.

Hope this helps!
-Jason