2023-05-08 11:46:16
"High-level modules should not
What is the difference between "high-level" and "low-level"?
High-Level
- More abstract
- Related to the problem domain:
- Business rules
- Process-oriented
- Further from I/O.
Low-Level
- Closer to I/O.
- "Plumbing" code
- Interacts with specific external systems and hardware.
What is an abstraction?
Types you cannot instantiate.
- Interfaces
<-- Prefered - Abstract base classes
Detials and Abstractions
- Abstractions shouldn't be
coupled with details. - Abstractions describe what
- Send a message
- Store a Customer record
- Details specify how
- Send an SMTP email over port 25
- Serialise Customer to JSON and store in a text file.
public interface IOrderDataAccess {SqlDataReader ListOrders(SqlParamterCollection params); }
public interface IOrderDataAccess {List<Order> ListOrders(Dictionary<string, string> params); }
Low Level Dependencies
Hidden Direct Dependencies
- Direct use of low level dependencies
- Static calls and new
- Causes pain
- Tight coupling
- Difficult to isolate and unit test
- Duplication
New Is Glue
- Using new to create dependencies glues your code to that dependency
- New isn't bad - just bear in mind the coupling it creates
- Do you need to specify the implementation?
- Could you use an abstraction instead?
Explicit Dependencies Principle
- Your classes shouldn't surprise clients with dependenciess
- List them up from, in the constructor
- Think of them as ingredients in a cooking recipe.
Dependencies with Abstractions
Dependency Injection
- Don't create your own dependencies
- Depend on abstractions
- Request dependencies from client
- CLient injects dependencies as
- Constructor arguments
<-- Preferred approach - Properties
- Method arguments
- Constructor arguments
See: Strategy Desing Pattern
Prefer Constructor Injection
- Follows Explicit Dependencies Principle
- Injected classes are never in an uninitialised state.
- Can leverage an IOC container to construct types and their dependencies
Organising and Extending Your SOLID Project
Use Feature Folders
- Online Store
- Catalogue
- Search
- Cart
Example of clean archtecture: github.com/ardalis/CleanArchitecture
Key Takeaways
- Most classes should
depend on abstractions , not implementation details. - Abstractions
shouldn't leak details. - Cleints should
inject dependencies when they create other classes. Structure your solutions to leverage dependency inversion.