One of the challenges of good polymorphic design is code consistency. We are building a way to communicate with developers. Therefore, our language or syntax needs to be easy to understand. Likewise, we need to set and meet expectations properly.
Code Consistency In ResultsThe most common error I find in this area of coding is found in the values returned. When we stick to native types and numbers, it tends to be easy enough to stay consistent. However, strings and structures lend themselves to issues.
For example, an address can have many properties and formats. We may be able to start with an output of: "address line, city, state zip." However, addresses vary. What happens when we want to add in a country or a different zip code format? The best approach to take in these cases is to extend as opposed to convert.
Lowest Common DenominatorThis thought process leads us to a focus on the lowest common denominator among classes and polymorphic methods. We can achieve this within a hierarchy by sticking to extending. However, it is not as easy to do this across classes. Think about a physical address when compared to an email address. These are very different collections of properties. When you consider a "print" method for these, there are multiple issues to consider.
Is there an expected limit to the length? Do we allow multiple lines? Should we include field labels? Are there multiple formats (CSV, XML, JSON, etc.) to be supported?When designing for polymorphic behavior, the answers to these questions should be the same across all instances of the method. For example, we should not allow some print functions to go multi-line while others keep all the values to one line (when a class has multiple attributes). Likewise, we should not have a "save" that does not pair properly with its corresponding "load" method. Development is difficult enough, do not add to our headaches with seemingly random functionality across methods with the same name.