[MUSIC] Many design patterns that we've explored use generalization of concrete classes. These generalizations are presented as interfaces for client classes to use to indirectly invoke the behaviors of the concrete classes. Design patterns do this so that client classes become less dependant on concrete classes, allowing for changes to be made more easily. Interfaces play an important role in object oriented programming, so much so that you should strive to program to interfaces instead of concrete classes. However, an issue can arise if an interface contains too much. Can you think of any problems that this might cause? Consider this example. Imagine creating a system that represents the checkout area at a grocery store. In North American countries, there are two ways a customer can pay for their goods. They can approach a human cashier operating a till, or they can use the automated self-serve machines. The purpose between the two can be generalized with an interface. They both scan items that a customer wants to purchase, accept some form of payment and dispense change when needed, but there are some behaviors that are not shared between the two of them. While an automated self-serve machine can perform work indefinitely, a cashier needs to eat, go on breaks and leave at the end of their shift. Now, you can simply put these human behaviors into a concrete cashier class, but there's an issue with this design decision. A client class would not be able to use indirection to invoke these human behaviors, because they're not in the interface. But if your client class calls the method directly upon a cashier, it will become dependent on that concrete class. So then are you forced to add these human behaviors into the interface? Or do you just accept that your system now has a low level dependency and will just do extra work when you need to make changes? Luckily, you can use the interface segregation principle to tackle this issue so that you won't run in to dependency issues or be forced to generalize everything into the interface. The interface segregation principle states that a class should not be forced to depend on methods it does not use. This means that any classes that implement an interface should not have dummy implementations of any methods defined in the interface. Instead, you should split large interfaces into smaller generalizations. So how does this work? The ICashier interface does work for the human cashier class because all its behaviors are captured by the interface. But as you can see, this design is not ideal, because the self-serve machine should not need to clock in and out of work or take any breaks. You don't want to be forced to provide method implementations for the self-serve machine that don't fit the machine. These would essentially be dumb implementations that don't do anything, and these are not behaviors that a client class should expect or be able to ask a machine to do. So we should apply the interface segregation principle and split the ICashier interface into two smaller ones. This will allow each interface to be more accurate with its description of expected behaviors, and it will allow you to pick and choose which correct combinations of interfaces a concrete class should implement. In this design, the old ICashier interface is split into a new ICashier interface and an IHumanWorker interface. The ICashier interface describes the general behaviors of a cashier, human or machine, and the IHumanWorker interface describes the general behaviors of an employee. The HumanCashier class can implement both interfaces, and the SelfServeMachine class would only need to implement the ICashier interface. This way both of your concrete classes will only need to provide implementations for the interfaces that generalize their specific functionality. Interfaces are an integral part of object oriented systems. They will help you reduce coupling by generalizing concrete classes, but just like with all object oriented principles you should strive to use them properly. While large interfaces are not a poor design choice, you need to examine them in the context of your system to decide if you need to split it up into smaller generalizations using the interface segregation principle. This design principle states that a class should not be forced to depend on methods it does not use, and interfaces should be split up in such a way that it can properly describe the separate functionalities of your system. Sometimes it isn't always clear how to properly segregate your interface or to predict future changes in requirements that will need interfaces to be split up. Having a system with well-defined interfaces will help you to see these segregation points better. You should always strive to be as precise as possible when designing interfaces. Remember that they are descriptions of what parts of your system can do, and the better the description, the easier it will be to create, update and maintain your software.