-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSOLID_Principles.cpp
More file actions
59 lines (34 loc) · 3.49 KB
/
Copy pathSOLID_Principles.cpp
File metadata and controls
59 lines (34 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
SOLID Principles: For every major class, state which SOLID principles it adheres to. (e.g., "I'm making ParkingFeeCalculator an interface to follow OCP and DIP.")
Trade-offs: If a design choice is made (e.g., using a Strategy Pattern), explicitly mention the trade-off (e.g., "The trade-off is slightly higher code complexity due to more interfaces, but vastly improved maintainability and extensibility.").
Encapsulation/Abstraction: Define the clear public interfaces (APIs) and hide implementation details.
UML: Use simple, clear boxes and arrows to show the relationships (Association, Inheritance, Composition).
🛠️ Core Principles & Patterns to Showcase
For Principal Engineer and similar senior roles, your discussion should go beyond just drawing a class diagram. You must justify your design choices
using core software engineering principles:
SOLID Principles: Be ready to articulate exactly how each principle applies to your design.
Single Responsibility Principle (SRP): Each class/module should have only one reason to change (e.g., Booking class handles bookings, not payments).
Open-Closed Principle (OCP): Software entities should be open for extension but closed for modification
(e.g., adding a new vehicle type in a parking lot should not require modifying the core ParkingLot class).
Liskov Substitution Principle (LSP): Subtypes must be substitutable for their base types
(e.g., all vehicle types can be parked by the same ParkingLot methods).
Interface Segregation Principle (ISP):
Clients should not be forced to depend on interfaces they do not use (e.g., separate interfaces for Admin vs. User functions).
Dependency Inversion Principle (DIP):
Depend on abstractions, not concrete implementations (e.g., the VendingMachine depends on a PaymentProcessor interface, not a concrete CreditCardProcessor class).
Design Patterns:
Be able to use and name appropriate GoF Design Patterns to solve specific problems. Common ones include Factory, Singleton, Strategy, Observer, State, and Decorator.
Concurrency:
Discuss thread safety, locking mechanisms, and handling concurrent access to shared resources (e.g., simultaneous bookings for a seat, concurrent updates to a cache).
💡 Principal Engineer Differentiation
For a Principal Engineer, the expectations are much higher than for a general Software Development Engineer:
Trade-off Analysis: Deeply analyze trade-offs between different design choices (e.g., using an array vs. a hash map + doubly linked list for LRU cache,
or choosing a specific database/cache for a component).
Scalability & Reliability at LLD:
Discuss how your LLD approach makes the component easier to scale and more reliable within the context of the larger system. For instance,
designing a thread-safe cache or using the Factory Pattern to make components easily swappable (e.g., different payment gateways).
Extensibility (OCP focus):
Provide examples of how your design is easily extensible for future requirements without changing core code
(e.g., "If we add a new premium parking spot type, we only need to add a new class that extends ParkingSpot").
Integration Points: Explicitly define the APIs/interfaces of your LLD component that the High-Level Design (HLD) services would consume.
The video below explains how to master Low-Level Design interviews using free resources, which is a great starting point for tackling these problems.
How I Mastered Low Level Design Interviews is a resource that shares tips on mastering Low-Level Design interviews.