Interchangeable Implementations0:00
We now have our payment option interface that outlines all of the methods we need to manage our payment options. Our classes implement that interface, they're small, they're specific, we're two out of five on the solid implementation. Our interfaces are segregated, our classes have a single responsibility. So far, so good. Now, the purpose of having an interface and different classes that implement it is for us to be able to use the classes interchangeably. Let's take our show method as an example. So what this does, it takes the instance of the proper class and then gives the fields
Explaining Liskov Principle0:34
Let's take our show method as an example. So what this does, it takes the instance of the proper class and then gives the fields from that particular class. Now if Pioneer's fields, for example, return a different format than the ones that we get from Wire, we won't be able to substitute one for the other without breaking the program. This is the Least Cost Substitution principle, the L in SOLID. Based on this principle, we want to be able to replace a class with any other class that implements the same interface, without breaking the program. What this means is that all classes should implement methods properly and return results that the program expects.
Extending with Pioneer1:12
What this means is that all classes should implement methods properly and return results that the program expects. The way we do it is by being mindful about what a program expects and covering the responses with tests to ensure that it works as expected, regardless of the instance that we use. Let's take a closer look through our example. Let's say that we have implemented a Wire payment as a single option at the moment, and right now we are asked to extend the functionality by enabling Pioneer as a second payment option. The first thing to do is dynamically show Pioneer's fields like we do for Wire. So with this hypothesis, the getFields method in the Pioneer repository is not yet implemented, and we want to implement it according to what we have in the Wire repository.
So with this hypothesis, the getFields method in the Pioneer repository is not yet implemented, and we want to implement it according to what we have in the Wire repository. So let's open that one. This is the structure we have. I will just go ahead and copy it and add it here to my getFields method in the repository. So the name here would be email because email is the only field I need for Pioneer. The label would be email, and I'm not confused by these two attributes over here. The required one, I get it. It is supposed to set whether the value is required or not. What about this style?
Fixing Missing Style Field2:31
It is supposed to set whether the value is required or not. What about this style? Assuming that this is the first time I'm encountering this code, and I'm implementing a new payment option that has only one field, I assume that there is a default it will pick. So I will just submit this one because I'm not sure what it does, and then try to make it work with this structure here. The page failed because it's missing a required property style. So if I scroll down here, I will notice that this field needs this style property to be able to display the input automatically.
So if I scroll down here, I will notice that this field needs this style property to be able to display the input automatically. It doesn't get a default value, even though you'd think so. So let's go back to our code and see how we can fix this. Since the style attribute is required, I will just add the style here, Excel 12, go back, run it again, and now it works. Now, this is an oversimplified example, but it's meant to demonstrate the purpose of the Liskov substitution principle. In reality, a common violation of this principle is when using APIs, for example. Oftentimes, we rely on the exact naming conventions.
API Substitution Pitfalls3:44
In reality, a common violation of this principle is when using APIs, for example. Oftentimes, we rely on the exact naming conventions and structures that the API services provide. So let's say we are using a bank API to validate the wire details before saving them. If I use a specific API from a given bank and rely on the naming conventions and the structure of the fields that they have, when a need arises to replace this with another bank or another service, the program will fail because the fields and the naming conventions of the other service will be different than the one I'm currently using. So a good practice here to avoid scenarios like this
Adapting Outputs for Swaps4:23
of the other service will be different than the one I'm currently using. So a good practice here to avoid scenarios like this is to always adapt the outputs whenever you're using external services so that you can easily interchange them in the future. The Liskov substitution principle, together with the other two we already discussed, set the ground for what we're about to cover next, and that is how to extend the functionality of our product by adding new code instead of changing existing one.
