Replies: 1 comment
-
Just subscribing myself to this since we were discussing it in the community slack. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
In an effort to simplify user experience with products by combining simple and variable products into a single template (pcQJnU-2f6-p2), we accidentally unearthed a series of long-standing issues within products in WooCommerce.
After looking through a number of extensions that make use of these features and heavy discussion around templating compatibility with types and templates, I've been contemplating if it's possible to completely remove product types in favor of product traits. At the very least, we need a better, more formal trait management system.
Note that in this post I use "trait" or "product trait" to refer to the similar existing concept of "product type options" in order to differentiate this idea from product types.
Difference between product types and traits
Product types and traits are tools to help control the features of a kind of product, but are commonly misused in extensions.
Product traits
Traits extend the functionality of existing product types and can be applied to some or all product types. A trait can be compatible with another trait
Traits are a very flexible way to add in functionality to existing product types and features, that provides the opportunity for cross-compatibility with other traits going forward.
Product types
Product types are a way to distinguish the behavior of a specific kind of product and explicitly declare that a product is not compatible with other product types.
In many ways, product types are really just like product traits with the exception that they cannot ever be compatible with another product type.
What's wrong with product types?
Types across templates
This is what spurred this exploration and relevant discussion around types/traits/templates (pcQJnU-2f6-p2). The new product editing experience attempts to simplify merchant experience by allowing creation of simple or variable products from within the same product template. It attempts to reduce the complexity of types that is usually offloaded to merchants by creating a simpler UI to create the intended product.
The issue with attempting to incorporate multiple product types within a single template is that we create a "tug-of-war" between two or more product types when an underlying action triggers a product type change.
While this may be something we can solve in the simple product template for core product types, this problem gets further compounded when extensions add their own templates. For example, if we create a "Gift card" template, this template is now forced to figure out which other traits its compatible with, which product types its compatible with, and how product types should be converted to one another.
It's possible that this means we should just stick to a 1:1 for product templates and product types, but I do see high value in the opportunity for templates to be used as starting points for a variety of combinations of product types, traits, and predefined product data.
Inability to share functionality
Product types make a definitive assertion that they will never be compatible with other product types since a product can never have multiple types.
The fact that a type declares incompatibility with other types isn't inherently a bad thing, but unfortunately this is very limiting as we've seen time and time again as we experience lock-in with a product type that we later realize could benefit from integrating with another product type's functionality.
A good example of this is WooCommerce Subscriptions which creates 2 new product types:
subscription
variable-subscription
It's easy to say that this should have been a trait as multiple product types could be "subscribable," but given that subscriptions needs both
simple
andvariable
product types, it really did not have much choice other than creating 2 new brand new product types. So instead of having a single product type that can have a combination of being subscribable and/or variable, we end up with 4 product types in total to maintain (simple,
variable,
subscription,
variable-subscription`).I think the argument could easily be made that product types are fine as is and what we're really seeing here is misuse of product types. But in reality it is very difficult, if not impossible, to know in advance that a newly created product type will never be compatible with any other product types.
Why aren't product traits used more often?
For most of the extensions and use cases that I've come across, traits seem to be the more correct answer to the problem being solved. They can extend functionality across the entire product or limit it to certain areas where not needed or incompatible.
So why do more extensions seem to prefer using product types over traits?
The above problems can all be resolved between a new compatibility system for traits, the introduction of product templates, and better documentation around how to use these features. The one exception to this is dealing with the "separation of behavior" issue or conflict resolution between two traits modifying similar behavior.
Proof of concept
In #44585, I've introduced the concept of compatibility between various traits. What this means is that traits can choose to be:
This effectively covers everything product types can do and more, but comes with the major advantage that compatibility between traits can be declared at a future date.
#44657 (while incomplete and very hacky with its heavy reliance on the __call magic method) makes an effort to continue supporting $product->get_type() and allowing product traits to continue extending the product class with custom methods. If we moved towards this solution, we would want to come up with an extensive deprecation strategy to phase out types while continuing to support them since so many extensions rely on plugin types and even product types registered by other third party extensions.
Also something that the POC hints at is the idea that many core features, even down to images and downloads, could be represented by traits to allow easier declaration of compatibility by custom traits if they do not support these base features. This better encapsulates logic around these features, but also more easily allows us to hide or disable features that are not compatible with third party traits.
How are conflicts dealt with?
The unresolved issue with moving towards a trait-based system is dealing with collision between 2 product types. As a simple example, let's take the
add_to_cart_text()
method in product types that is used to determine which "add to cart text" to show on the product page.Moving towards a trait-based system means that two different traits may be trying to modify this text simultaneously and fighting for control. However, I think this might be less of an issue than it appears on the surface.
In concept, traits should not compatible with one another until declaring compatibility. This means that luckily there is an opportunity to resolve conflicts since compatibility is explicitly declared. If we rely on the filter that already exists for "add to cart text" and continuing with our example from earlier:
Next steps
I think that creating a product trait system to check compatibility is an easy win, but deprecating product types is a much larger project. This is obviously a huge change and not something we should consider without extensive discussion.
I think in order for this to be a viable solution, we need to validate a few points:
I realize this is a potentially controversial take on product types and definitely welcome any criticism or concerns around this approach. While I really like this concept in theory, I'm sure there are a number of cases that will make this transition very challenging to accomplish.
@woocommerce/mothra @woocommerce/somewherewarm @woocommerce/rubik @woocommerce/woo-fse
Beta Was this translation helpful? Give feedback.
All reactions