To finish the posts about Bad Smell on our blog, we will talk a little about the Object Orientation Abusers family, more specifically about “Refused Bequests and Alternative Classes with Different Interfaces", and you can check out parts 1 and 2 of this content here on our site.
The bad smell Refused Bequest is related to the use of inheritance and can be seen in derived classes that do not use most Parent class features. Even with this inheritance, the parent class and the derived class are not alike. This causes a big problem, as it violates the Liskov Substitution Principle.
Let's see an example to make it easier to understand:
The classes above show a classic example of Refused Bequest. The derived class ignores the Parent class feature (when it refuses to use the parent's behaviour by overriding the methods). This attitude also violates the Liskov Substitution Principle, since the derived class replaces the behaviour of the parent class affecting its functionality.
In some scenarios, we know that inheritance makes sense for extension and in other cases it does not. We went back to the implementation of the parent class and used the refactoring technique called Push Down Method, where we removed from the parent class the methods overwritten by the derived class, also changing their name to something more meaningful within their context, leaving only what makes sense for the base class, making sure that they do not need to overlap.
This bad smell is related to the situation in which two different classes seem to have similar responsibilities, but contain different interfaces, or names of methods or properties. Generally, this happens due to lack of communication among team members, who end up not checking if there is already something built for that purpose.
In the images above, we have two classes: Conversor and ConversorDePrecos. Both have almost identical implementations for converting a given value according to the type of currency. This code shows total disregard for the DRY principle, where the code has been duplicated, but with a small variation.
Depending on how the problem is presented, (if the classes behave in the same way implementing different interfaces), a solution would be to create an abstract (base) class, or a single interface allowing the classes to extend or implement as needed. The only thing we couldn't have were two implementations of the same type on the same interface, as it would make no sense. The ideal would be to delete one of the implementations and proceed with the other.
In the case of the Conversor and ConversorDePrecos classes, we will not solve the issue using abstract classes or interfaces. Let's just consider the Principle of sole responsibility, let's leave the implementation dedicated to the Conversor class and remove the method from the ConversorDePrecos class, by replacing the method with the single remaining implementation. This implementation brings us the benefits of having only one location for an eventual change (Single point of change) and is fully in line with DRY.
Interested in the subject? This content was produced by our .Net Developer, Thiago Chagas, and you can check out more technical details by accessing the content series: “Do you know what Bad Smell is? I’ve never seen it, I’ve just heard about it!!”.
May the force be with you!