SOLID principles interview questions, with answers
SOLID is the design-principles question every fresher OOP round reaches at some point, and the weak answer is a list of five expansions. The strong answer names, for each principle, the specific kind of bad code it exists to prevent and what the fix looks like — because the interviewer's follow-up is always "show me a violation".
Below is each principle with its violation and its fix, then the questions that connect them. When you have read them, take the free OOP diagnostic — ten questions across all fifteen OOP topics, with the weak ones named.
The questions, with answers
1.What do the five SOLID principles stand for, and what problem does the set solve?
Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion — five guidelines collected by Robert C. Martin for object-oriented design. Together they aim at one thing: code that can be changed without breaking, because responsibilities are separated, extension does not require editing, subtypes are safe to substitute, interfaces are small and dependencies point at abstractions. In an interview, give the expansion in one breath and then pick the principle you understand best to go deep on, ideally with a violation you have actually fixed. Knowing that they are heuristics, not laws — applied with judgement, sometimes traded against each other — is itself a good answer.
2.What is the Single Responsibility Principle, and what does "one reason to change" mean?
A class should have one, and only one, reason to change — it should serve one actor or one concern. The classic violation is a Report class that computes the figures, formats them as HTML and saves them to disk: a change in the tax rules, a redesign of the page and a move to cloud storage all force edits to the same class, and a bug in one can break the others. Split it into a calculator, a formatter and a storage class and each changes for its own reason. The principle is not "a class should do one tiny thing"; it is about who asks for changes. A good test: list the stakeholders who could ask you to modify the class, and if there are two, it has two responsibilities.
3.What does the Open/Closed Principle mean, and how is it achieved?
Software entities should be open for extension but closed for modification: you add behaviour by adding new code, not by editing code that already works. The violation is a switch on a type field — a DiscountCalculator with a case for regular, gold and platinum customers that must be edited every time a tier is added, retested every time, and shipped with the risk of breaking the tiers that already worked. The fix is polymorphism: a DiscountPolicy interface with rate(), one class per tier, and a calculator that never changes again. The Shape example below is the same move in a different domain; strategy, template method and plugin architectures are the same idea at larger scale. The judgement call is which axis of change to open: you cannot make a class extensible in every direction, so open the one that actually varies.
interface Shape { double area(); } class Circle implements Shape { double r; public double area() { return Math.PI * r * r; } } class Square implements Shape { double s; public double area() { return s * s; } } double total(List<Shape> shapes) { // never edited when a new Shape appears double sum = 0; for (Shape sh : shapes) sum += sh.area(); return sum; }4.What is the Liskov Substitution Principle, and why is Square extends Rectangle a violation?
Any code written against a base type must keep working when handed an instance of a subtype, without knowing the difference. Square extending Rectangle breaks it: a square must keep its sides equal, so setWidth(5) also sets the height — and code written for Rectangle that calls setWidth(5), setHeight(4) and expects an area of 20 gets 16. The subtype has changed the base class's contract, so it cannot be substituted. Mathematically a square is a rectangle; behaviourally, with mutable setters, it is not. The fixes are to make both immutable value types, or to give them a common Shape interface with no shared setters. Other LSP violations to name: an override that throws UnsupportedOperationException, tightens a precondition or weakens a postcondition.
5.What is the Interface Segregation Principle?
No client should be forced to depend on methods it does not use — prefer several small, role-specific interfaces to one fat one. The violation is a Worker interface with work(), eat() and sleep() that a RobotWorker must implement, leaving eat() and sleep() as empty methods or ones that throw; every caller of Worker now has to know which implementations are real. Split it into Workable, Feedable and Sleepable, and each class implements only what it means. Java's Comparable, Iterable, Closeable and Runnable are the principle in the standard library: one capability each. ISP is Liskov's cousin — a fat interface is what tempts a subtype into methods it cannot honour.
6.What is the Dependency Inversion Principle, and how is it different from dependency injection?
High-level modules should not depend on low-level modules; both should depend on abstractions, and the abstractions should not depend on details. An OrderService that does new MySqlOrderRepository() inside itself is bound to MySQL forever and cannot be unit-tested without a database. Invert it: OrderService depends on an OrderRepository interface, and the concrete MySQL class is supplied from outside. Dependency injection is the mechanism that does the supplying — passing the dependency through a constructor, a setter or a framework — while inversion is the design principle that says which direction the dependency should point. You can inject a concrete class and still violate DIP; you can follow DIP with a hand-written factory and no framework at all.
interface OrderRepository { void save(Order o); } class OrderService { private final OrderRepository repo; OrderService(OrderRepository repo) { this.repo = repo; } // injected; depends on the abstraction void place(Order o) { repo.save(o); } } // production: new OrderService(new MySqlOrderRepository()) // tests: new OrderService(new InMemoryOrderRepository())7.How do you spot SOLID violations in code you are asked to review?
Look for the smells each principle names. A class whose name has "And" or "Manager" in it, or that imports both a database library and a UI library, is an SRP suspect. A switch or if-chain on a type code, repeated in several places, is Open/Closed. An override that throws "not supported", or an instanceof check before calling a method, is Liskov. Empty method bodies that exist only to satisfy an interface are ISP. A new keyword deep inside business logic creating a database, HTTP client or file object is DIP. In an interview, describe the smell, name the principle, and sketch the fix in a sentence — that structure is worth more than reciting all five expansions again.
8.Can following SOLID make code worse?
Yes, when applied mechanically. An interface for every class, a factory for every object and five files where one would do add indirection that nobody needed — the reader now has to open six files to find where anything happens. The principles describe how to manage change; a piece of code that will never change in that direction gains nothing from being made extensible along it. The honest interview answer: apply SOLID where you can point to the change it protects against, keep simple things simple, and refactor toward a principle when a second concrete case appears rather than in anticipation of one. Interviewers who ask this are checking for judgement, not for a memorised list of five.
How the diagnostic asks it
One question from the OOP bank, exactly as a sitting would show it. The bank has 4 on solid principles and 60 across OOP.
An AreaCalculator class computes areas with a large switch statement over shape types (circle, square, triangle). Every time a new shape is added, the switch statement inside AreaCalculator has to be edited and retested. Which SOLID principle does this most directly violate?
- 1Open/Closed Principlecorrect
- 2Dependency Inversion Principle
- 3Liskov Substitution Principle
- 4Single Responsibility Principle
The Open/Closed Principle says you should be able to add new behaviour (a new shape) by adding code, not by changing tested code. A switch over types forces modification for every extension; giving each Shape its own area() method lets AreaCalculator call shape.area() and never change again. SRP concerns a class having one reason to change, LSP concerns substitutability of subclasses, and DIP concerns depending on abstractions rather than concrete classes.
Measure it
Reading answers tells you what’s true. A diagnostic tells you what you get wrong.
10 OOP questions across its topics, easy to hard, about fifteen minutes. You get a readiness figure with the arithmetic shown, the topics you missed named, and a practice set sized for today. Free: 1 diagnostic a month and 15 problems a day. No card.