SOLID Principles (Java)
Context: FIT2099_MOC Β· Robert C. Martinβs five design guidelines (not laws) Β· the shared rationale vocabulary for the design assignment Β· all aimed at Reducing Dependencies (ReD)
Quick Revision
- π― Objective: judge and justify a design against five principles β low coupling, high cohesion, easy extension.
- π¦ Core Components: S Β· O Β· L Β· I Β· D.
- β‘ Key Constraint: SOLID = guidelines, not laws β over-applying (too many tiny classes/abstractions) adds complexity; apply where it reduces real dependency pain.
π The Five Principles
| Principle | One-line | Smell | Fix | |
|---|---|---|---|---|
| S | Single Responsibility | one class, one reason to change | God class; unrelated methods | split by reason-to-change |
| O | Open-Closed | open to extend, closed to modify | instanceof chain grows per feature | abstract method / polymorphism |
| L | Liskov Substitution | a subtype must be usable as its base | override throws / empty / instanceof | fix the abstraction (sibling interface) |
| I | Interface Segregation | no client forced onto unused methods | empty method bodies to satisfy an interface | split into small interfaces |
| D | Dependency Inversion | depend on abstractions, not concretes | high-level class references concrete types | inject/hold an interface type |
- ReD thread β every principle ultimately reduces dependencies so the design tolerates change (coupling/cohesion/extensibility).
- Chained relationships β ISP feeds LSP (small interfaces are easier to fully honour) and SRP (small interfaces β focused classes).
π LCOM β measuring cohesion (SRP)
- Lack of Cohesion of Methods β where = methods, = instance fields, = methods touching field .
- Read it β LCOM = perfectly cohesive (every method uses every field); high LCOM (β 1) = the class splits into unrelated clusters β SRP candidate.
- Heuristic β with and is a warning sign (but hard to avoid entirely).
β οΈ Downcasting & instanceof (cross-cutting smell)
- Upcasting β subclass β supertype, implicit & safe (
Vehicle v = new Sedan();) β enables polymorphism; good. - Downcasting β supertype β subclass, explicit & risky (
((Truck) vehicle).cargo();) β bypasses compile checks, can throwClassCastException. - Why bad (design) β depends on a lower-level type (breaks abstraction), often signals an LSP and OCP violation, and grows
if (x instanceof Y)chains. - When tolerable β occasionally the cleaner-abstraction cost is too high; if you must downcast, guard with
instanceoffirst and justify it in the rationale (rarely needed in assignments).
π§ Active Recall
Why are SOLID principles called "guidelines, not laws", and what goes wrong if you over-apply them?
Answer
- Short answer: They are heuristics for reducing dependency, not absolute rules; over-applying (e.g. SRP splitting classes until theyβre trivially small, or DIP adding an interface for everything) overcomplicates the design and adds its own coupling/complexity.
- Why: Cost-benefit β each abstraction has a cost; apply a principle where it removes real change-pain, and stop when the abstraction costs more than the coupling it removes.