Refactoring
Design principles are guidelines; there are no laws! As with everything in life, you can go too far with applying these principles at the cost of making a design more complicated than it should be. You should try to be pragmatic and don't take these principles as dogma!
One strategy to keep the balance is to start simple (with a good enough design) but be prepared to refactor as you progress. In his classic book, Refactoring, Martin Fowler defines refactoring as:
**Refactoring ** The process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.
It may surprise you to learn software rots! It rots because of improper design; because over time, easy code changes are made instead of difficult design changes. Refactoring is the art of making design changes over time to keep the software fit for its purpose and ready for more changes. It takes attention; one must be able to recognize the smell of (software) rot to act in time.
Code smells Code smells are structures in the code that indicate a violation of design principles and negatively impact software quality.
Exploring code smells in detail is beyond the scope of this course. We will give an example and leave it to you to explore the subject further.
Example Code Smell: Large Class
Large Class A class contains many fields/methods/lines of code.
It is mentally less taxing to place a new feature in an existing class than to create a new class for the feature. So, classes usually start small, but over time as the program matures, they get bloated. It's like the Hotel California; something is always being added to a class but nothing is ever taken out!
Here is the fix:
-
When a class is (or is about to get) bloated, it is likely to have too many responsibilities. Consider splitting it up into separate (smaller and more cohesive) components (think Single Responsibility Principle).
-
If the issue is not extra responsibilities but more so about handling special cases, consider extracting subclasses (think Open/Closed Principle).
-
In the latter case, it makes for a better design to create abstractions (interfaces) to keep the inheritance hierarchies flat (think Dependency Inversion and Interface Segregation principles).