When to use Bundles vs Entity Types I have a design question:

I have several models that lend themselves to inheritance very well.

I have an animal object that has attributes that are shared between the dog, cat, and hamster objects very nicely.  However, the source of the dog, cat, and hamster are all from different APIs.

So what I started doing was to build my module around each of the APIs, with the necessary 'fields' effectively hardcoded in the module animal.  I knew that this horrifically violates the DRY principle; but am from the D6 (barely D7 era and hadn't really been introduced to entity types).  This was using custom tables, and custom 'models'.  This also means that I have to create the views, and all the other stuff associated with it myself.

So then I realized that I could actually use entity types for this.  The core animal module exposes only what it needs to (a small set of fields).  And the dog, cat, and hamster modules all extend the animal entity type thus giving me access to all the shared data without having to repeat myself and the added bonus of having views, handlers and the other stuff for almost free (a bit of boilerplate that is copy and paste...).

My questions are thus:


Is this thinking right, that content entity types are the way to go?
I know what I gain, but what do I lose by doing this?
Is this a good approach, i.e. is it fair to extend a base entity type?
Is it better to create bundles for each of the dog, cat, hamster or just use the extending of the animal content type?
When do you use a bundle vs extending a content type?
Yes, using content entity types for this seems like a good idea.

In regards to entity types vs. bundles, which one is better for you depends on your exact requirement (I only noticed after already writing most of this that you already mentioned and specifically asked about entity types vs. bundles, so might be too much explanation, but too lazy to rewrite now :)).

Entity types

You create separate content entity types. Whether you use inheritance for sharing the base field definitions or for example a trait is up to you. The inheritance only exists in code, the data itself knows no hierarchy, it is stored in separate tables.

But yes, sharing code there is perfectly valid. Drupal 8.4 for example adds a base class for publishable entity types: EditorialContentEntityBase, see https://www.drupal.org/node/2870643.

The advantage of this is that you can build each entity type with exactly the base fields that you need, which results in an optimized storage (1-4 base field tables, depending on whether you need revisions and/or translation support and separate tables for multi-value fields). However, the main drawback is that there is no API, neither views nor entity query that allows you to list different types of animals in a list. If that's a requirement, then this might be a no-go.

Bundles

You create a single animal entity type and different bundles for the different types of animals. This is like the node entity type and bundles. They share the same base fields and storage, additional type-specific fields can be added as configurable fields or maybe also per-bundle base fields (I honestly have no idea how well that actually work - and I'm supposed to be one of the maintainers of the entity system). This is the opposite of the above, it's easy to create lists with different animals but you might end up with a considerable amount of per-field tables if you have a lot of fields on your dogs/cats etc.

In regards to downsides, content entities are pretty heavy, they have a complex structure based on typed data and are therefore slower than plain custom objects. Their storage, while extensible, is also limited in various ways, you can only load full entities and there is no support for bulk update for example (but you can implement some things in a custom storage handler). But you get a ton of features for that, the mentioned views integration, widgets/formatters, cache handling/invalidation, revision and translation support and so on.