Jump to content

The PW data-model and the Entity/Component pattern


mindplay.dk
 Share

Recommended Posts

I had a realization recently about the PW data-model that I would like to share.

The PW model is actually very akin to that of the Entity/Component model.

Pages can be seen as Entities, and Fields can be seen as Components of those Entities. Templates can be seen as Component Types.

One important difference from the E/C model, in terms of implementation, is the shape of the resulting entities - Fields are mapped directly onto Pages; or in other words, Component properties are mapped directly onto Entities, which means the Components themselves are limited to a single property at the model-level, even though some Field types are backed by tables with more than one property value, e.g. more than one data-column.

I can't help thinking the resulting model is really close, but one step removed from being anywhere near as powerful as a real E/C data-model.

To explain why I feel this way, here's a very simple case example.

Let's say you have a shop with different types of products, many of which have at least one thing in common - they have a unit price, product title, and manufacturer name.

With the PW model, I will add these three fields individually to every Template that describes a product type, and I will address these as, say, $page->price, $page->title and $page->manufacturer.

Fetching these three fields requires three joins to separate tables.

Conceptually, these three fields are meaningless on their own - they belong to a single component that defines the necessary properties required for something to "be" a product in our system. The, let's say, shopping cart service, for example, is dependent on the presence of all of these three fields and doesn't function if one of them is missing.

With the Entity/Component model, instead of adding three individual fields, you define a component type that defines these three fields. You would address them as, say, $page->product->price, $page->product->title and $page->product->manufacturer. In other words, these three fields, which belong together, are exposed in the model as a single, integral component.

Fetching these three fields requires a single join to one table.

The ability to group together related properties in components has performance advantages (fewer joins/queries) but more importantly, it has practical advantages in terms of programming. You wouldn't need to group together related fields by prefixing them with "name_" anymore, which seems like an unnatural way to create a kind of "pseudo component". Adding/removing properties to a component property would naturally propagate that change to every entity that uses that component, rather than having to run around and update them manually. Controllers/services could define their requirements in terms of component shape.

I realize it's a pretty substantial departure from the PW data-model, but perhaps something to think about for an eventual future 3.0.

Or perhaps just an idea to consider for a different CMF in the future.

Or perhaps just something interesting to think about and do nothing :-)

  • Like 5
Link to comment
Share on other sites

What you're describing is actually already kind of a part of processwire. In fact you do not add fields to a template per se, but to a fieldgroup. The only thing missing is the ability to link more than one fieldgroup to a template. If additional fieldgroups would get there own database table it should work quite well. I have thought about such a feature in the past, too. Maybe some day something like this will get integrated.

Link to comment
Share on other sites

At the database-level, yes, it does closely resemble the E/C model - fieldgroups, however, are a logical grouping of fields, not a physical grouping; the difference being, fields inside a fieldgroup are still exposed at the root of the entity, just like any other non-grouped field. Because it's only a logical grouping, the model does not reflect this grouping as such.

Getting fieldgroups their own database table would not be possible given the current architecture, as far as I can figure - field types manage things like table schema and query construction. I could be wrong, but pretty sure some drastic changes would be required to switch to a full-blown entity/component model.

Link to comment
Share on other sites

I don't think that such drastic changes need to be operated, since it is already possible to create compound FieldTypes that group different values. An example of this is the Events Fieldtype/Inputfield created by Ryan to demonstrate how to create custom fieldtypes. The Date, Location and Notes of an event are stored as different columns in a single table, and could therefore be compared to the Component.

What would be needed is a good way to create such compound fields in the admin section. As I understand, this is what the Table ProField does, though it is still a little limited, since you can't use page fields for example. But this would tend to indicate that the changes to be done would not be so drastic.

  • Like 2
Link to comment
Share on other sites

I'm actually not that big of a backend guy, so maybe it does only seem easy to me. You're right with the database being dependent on fields. I had that wrong in mind. But I still think, that the ability to add additional fieldgroups beyond the "root" one shouldn't be crazy hard to pull of.

For me it would also not really matter how this fits any models or if the database uses less joins, I just know that predefined groups of fields and reusing them are something that ProcessWire does not pull of nicely by now. The only thing I'm not so sure about is, if adding a additional layer between fields and templates really is the key to more success (productivity / ease of management / …). Wouldn't we have the case that after including this layer people would come and suggest adding another layer, because they want another level of grouping, and we'll get in some kind of loop.

  • Like 1
Link to comment
Share on other sites

I don't see it so much as adding another layer. The underlying data model already resembles entity/component - I see it more as getting to a run-time model that more accurately reflects the underlying data-model.

I didn't know about ProFields - it looks like it does add a kind of "compound field", managing to reuse those field-types that can co-exist in a single, flat table - so, as far as I understand, any type that isn't multi-valued, e.g. doesn't require it's own table.

So effectively, this does implement an entity/component pattern - though it kind of feels like an afterthought to me... I wish the field-type model had been built from the ground up using this pattern consistently...

  • Like 1
Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...