SOLID Principles: 30 Interview Questions That Actually Test Understanding
Not "what does SRP stand for" - the questions that came after that one.
Most SOLID interview prep stops at definitions. "What is the Single Responsibility Principle?", "What does OCP stand for?" You can answer those from a glossary without ever having felt the pain the principle solves.
In real interviews, especially with senior interviewers, rarely stay there. They push into: What breaks if you don't do this? Where's the line before this becomes over-engineering? How does this hold up at scale, with a bigger team, under a tight deadline?
This is a curated set of 30 questions in that spirit where each question has a short, interview-ready answer.
1. If a class has only one public method, does that automatically mean it follows SRP?
Not necessarily. SRP is about having one reason to change, not one method. A class with a single method can still be doing multiple unrelated jobs internally like validating input, formatting output and writing to a database, all crammed inside that one method. Method count is a distraction, ask what would force this class to change and count the reasons.
2. You refactor a "God Class" into ten smaller classes. How do you kno you've actually improved the design and not just moved the mess around?
Check whether each new class can be described in one sentence without using the word "and". If OrderValidator still validates and logs and sends a notification, you've split the class physically but not by responsibility. Also check coupling, if changing one new class still forces you to touch three others, you've fragmented the problem, not fixed it.
3. Doesn't splitting responsibilities into many small classes hurt readability, since you now have to jump between files to understand one flow?
It's a real trade-off, not a myth. The fix isn't to avoid splitting, it's to split along boundaries that actually change independently and keep an orchestrating class or function that reads like a clear step-by-step summary of the flow, delegating the details to the smaller classes. If done well, the top-level flow becomes more readable even if you occasionally jump files.
4. How would you detect an SRP violation during a code review without a strict rule like "one class, one job"?
Look for classes that change for unrelated reasons across different tickets - a class touched both for a UI text change and a database migration is a strong signal. Also watch for classes with multiple unrelated groups of private helper methods or a constructor pulling in dependencies that have nothing to do with each other.
5. A junior developer says "SRP means every class should only have one method." How do you correct that without discouraging them?
Acknowledge the istinct is close, fewer methods often does correlate with focus but clarify that the actual test is "reason to change", not method count. A Rectangle class can have area(), perimeter() and scale() and still be perfectly SRP-compliant because all three exist for the same reason: describing rectangle geometry.
6. How does SRP affect your team's ability to work on the same codebase in parallel without merge conflicts?
When responsibilities are entagled in one large class, multiple developers editing unrelated features often end up modifying the same file, causing frequent merge conflicts. When responsibilities are cleanly separated, each developer's change tends to stay contained to the class relevant to their feature with fewer overlapping edits and fewer conflicts.
7. Doesn't OCP contradict the idea that "you should be able to modify and improve your code over time"? Isn't refusing to modify existing code a bad habit?
OCP isn't "never touch existing code", it's don't modify exisiting, working code just to add a new behavior. Fixing a genuine bug in existing code is still expected and healthy. OCP specificially targets the pattern of repeatedly editing the same class every time a new variant of behavior is added.
8. You have a large if/else chain that's grown for years. How would you refactor it toward OCP without a risky big-bang rewrite?
Introduce an interface or abstract base matching the existing branches' behavior, then migrate one branch at a time into its own class, keeping the old if/else running in parallel until every branch is migrated. Once all branches are extracted, replace the if/else with polymorphic dispatch. Incremental migration avoids a single risky rewrite.
9. How would you decide whether a new requirement should be added via extension (a new class) or by legitimately modifying an existing class?
Ask if the new requirement is a genuinely new variant of existing behavior (extension fits) or a correction/refinement of what's already there (modification is appropriate). Forcing every change into a new subclass, even small tweaks to existing logic, leads to unnecessary class explosion.
10. What's a realistic failure of over-applying OCP?
Class explosion - creating a new subclass for every tiny variation, even ones that will never realistically change independently. This adds indirection and cognitive overhead without a corresponding benefit, making the codebase harder to navigate for no real flexibility gained.
11. How does OCP affect the safety of shipping changes under a tight deadline?
Since new behavior is added via new code rather than editing shared, already-tested classes, the blast radius of a change shrinks, you're far less likely to accidentally break existing, unrelated behavior while rushing.
12. Give an example where OCP strictly would actually be the wrong call?
A single internal utility function used in exactly one place, unlikely to ever need a second variant - wrapping it in an interface "to be open for extension" adds overhead with no future payoff. OCP earns its value specificially where new variants are a realistic, recurring possibility, not as a default for every function.
13. A subclass overrides a method and throws an exception for a case the parent class handled fine. Is this always an LSP violation?
Usually yes, if code written against the parent type breaks when handed this subclass instead, that's the core of an LSP violation, regardless of whether the exception feels "justified" from the subclass's perspective.The fix is typically to reconsider the inheritance relationship itself, not just the exception.
14. How would you detect an LSP violation without deliberately testing every subclass against every possible use of the parent class?
Look for subclasses with overriden methods that narrow the accepted input range, widen the set of thrown exceptions, weaken guarantees the parent promised or leave a previously-working method as a no-op. Any of these are strong signals a subclass isn't truly substitutable.
15. Why is the classic Rectangle/Square inheritance example considered a violation, even though a square genuinely "is a" rectangle mathematically?
Mathematically true, but code correctness depends on behavioral substitutability, not geometric truth. If Rectangle allows setting width and height independently, and Square overrides that to keep both equal, code that sets width expecting height to stay unchanged silently breaks when handed a Square. The inheritance is geometrically valid but behaviorally unsafe.
16. Does LSP mean you should avoid inheritance altogether and always prefer composition.
No, LSP doesn't ban inheritance, it constraints how you use it: only inherit when the subclass can genuinely honor every behavioral promise the parent makes. "Prefer composition over inheritance" is a related, broader guideline but LSP specificially is about not breaking behavioral contracts when you do choose inheritance.
17. How does LSP violation affect a team working on a large, shared class heirarchy?
Developers writing code against the base type can no longer trust that any subclass will behave predictably, they end up adding type-checks to work around exceptions, which defeats the entire point of polymorphism and quietly reintroduces the tight coupling OCP was trying to remove.
18. How would you scale a class heirarchy that's starting to show LSP violations as more subclasses get added?
Revisit whether the base class's contract is too broad, sometimes the fix is splitting the base type into smaller, more specific interfaces so subclasses only commit to behaviors they can genuinely support, instead of inheriting a bloated contract they partially can't fulfill.