Are you considering using interfaces in Magento 2? In the second article of our Magento 2 Development series, Yoda – one of our certified Magento developers – explains the pros and cons of using interfaces. Find out what his experience with them has taught him.
What Are Interfaces Used For?
I must have first learned about interfaces properly when I started learning Java in 2004. By that point, I already thought I was pretty hot on programming and as a student, interfaces didn’t seem like that useful a tool. After all, they’re just templates for your code, right?
The trick here is that interfaces aren’t just templates for your code, they’re templates for everyone’s code. When you’re working on a big system like Magento 2 where anyone could alter things or even completely change things around, it’s important to know what you can rely on. And that’s where interfaces come in.
Interfaces set a minimum standard for blocks, models, and other PHP classes within Magento 2. If an implementation of an interface doesn’t match the minimum requirements set within the interface then PHP will throw an error and won’t allow it to run.
They aren’t foolproof. Realistically, you’re just setting down some rules to say that any instance of this interface will implement these functions in this way. But it does mean that every instance of that interface will have those functions available – no matter how badly they function.
When you’re in a situation where a third-party Magento 2 module could completely change how the Product model works, it’s good to know there will always be some minimum standards they have to keep to.
Of course, interfaces in Magento 2 aren’t just used for defining code; they’re used to define other standards as well. No PHP class can be passed as an argument to an M2 block unless it implements the ArgumentInterface – it doesn’t require any functions to be added, it’s just used to ensure that only classes intended to be arguments get passed as arguments.
Why Use Interfaces Rather Than Models?
There are a few reasons. Most of them we covered above, but there’s another important one: it’s what Magento supplies through its repositories. Repositories are Magento’s preferred way of getting models like Products, Orders, or Customers, and they don’t return instances of the model you might be expecting – they return instances of the relevant interface and that can be very important.
Magento\Catalog\Model\Product implements Magento\Catalog\Api\Data\ProductInterface but Magento\Customer\Model\Customer does not implement Magento\Customer\Api\Data\CustomerInterface.
This is important because the ProductRepositoryInterface->get() function returns instances of ProductInterface which are likely to return Product models but the CustomerRepositoryInterface->get() function returns instances of CustomerInterface which will never be Customer models – the same functions will never exist in the two. So you can’t write code expecting to get a Customer model because you’ll never get one.
Another reason to use interfaces is that it works better with Dependency Injection, which is how we get objects passed to our constructors. Magento will determine which object to use for a given interface specification and that might not be the one you expect it to be using, so it’s best to work based on what the interface provides rather than on what the model you want to use provides.
Difficulties of Using Interfaces
We’ve covered the advantages of using interfaces – they provide security in development, your code won’t get given objects that don’t have functions it doesn’t expect. But there must be downsides, right?
There are a few, yes. Probably the biggest disadvantage of working with interfaces rather than models is that you can’t rely on the functions of the model being available.
The Product model has the function getFinalPrice() which works out the final price for the product. The ProductInterface does not have this, which means you can’t rely on that function existing. There are ways around this, of course. Having fetched the ProductInterface through the ProductRepository, you can then use a ProductFactory to get the Product model you wanted in the first place. A bit more convoluted, but it’s better code and it’s more reliable as a consequence.
Working with interfaces in Magento is hard work, but it’s work that results in better, cleaner code that will work more reliably long-term no matter what gets thrown at it. It’s worth overcoming the difficulties now to get code that will work just as well in the future.