Dependency Injection Principle: high-level modules should not depend on low-level modules, both should depend on abstractions. Abstractions should not depend on details, but abstractions.
We adopt the following practices:
- Do not refer to volatile concrete classes.
- Do not derive from volatile concrete classes.
- Do not override concrete functions.
- Never mention the name of anything concrete and volatile.
Example Violation: lets say we have two classes Keyboard and Printer, the Copier repeatedly calls the read method on the Keyboard to get the next character which it then passes to the Printer to write. Instead the Copier class should depend on abstractions instead, such as InputDevice and OutputDevice which both read and write, but Copier is not concerned with what sort of devices they are.