SOLID Principles in OOP: Design & Analysis
- SOLID principles are five core object-oriented design guidelines that emphasize modularity, extensibility, and maintainability.
- They identify semantic design flaws through characteristic violation patterns—like god classes and extensive type-dispatch—which facilitate automated code analysis across Java, Python, Kotlin, and C#.
- Empirical benchmarks using SOLID assess various prompting strategies and model performances, offering actionable insights for AI-assisted refactoring and design evaluation.
Searching arXiv for relevant papers on SOLID principles and adjacent program-analysis work.
SOLID is a five-part set of object-oriented design principles comprising the Single Responsibility Principle, Open/Closed Principle, Liskov Substitution Principle, Interface Segregation Principle, and Dependency Inversion Principle. In the material considered here, it functions both as a conceptual framework for identifying semantic design flaws and as an explicit classification target in empirical studies of AI-assisted code analysis, where code samples are labeled as SRP, OCP, LSP, ISP, DIP, or No Violation (Pehlivan et al., 3 Sep 2025).
1. Conceptual structure of SOLID
SOLID organizes object-oriented design quality around five distinct constraints on modular decomposition, extensibility, substitutability, interface granularity, and dependency structure. The study that operationalizes these principles for automated analysis defines them concisely and couples each definition to characteristic violation patterns across Java, Python, Kotlin, and C# (Pehlivan et al., 3 Sep 2025).
| Principle | Definition | Typical violations |
|---|---|---|
| SRP | A class/module should have one reason to change—one cohesive responsibility | God classes; mixing persistence, business logic, and presentation |
| OCP | Entities should be open for extension, closed for modification | Growing if/else or switch based on type |
| LSP | Subtypes must be substitutable for their base types without altering desirable properties | Subclass breaks base contract |
| ISP | Prefer many client-specific interfaces over one fat interface | Clients implement unused methods |
| DIP | High-level modules should depend on abstractions, not concretions | Direct dependence on concrete classes |
The principles are not merely stylistic conventions. In the dataset and evaluation protocol, they are treated as semantic properties that require recognition of object-oriented structure rather than simple syntactic pattern matching. This is why the paper characterizes SOLID violations as “semantic design flaws” and notes that traditional static analysis methods struggle to detect them across all five principles and across multiple languages (Pehlivan et al., 3 Sep 2025).
2. Canonical violations and refactoring patterns
The Single Responsibility Principle is defined as the requirement that a class or module have one reason to change. The representative violation is a “God class” or a unit that mixes unrelated concerns. The study’s example is a UserService that both validates user input, sends emails, and writes audit logs. The corresponding refactoring separates these concerns into Validator, EmailSender, and AuditLogger (Pehlivan et al., 3 Sep 2025).
The Open/Closed Principle is framed around extensibility without modification. A standard violation is a render(shape) routine implemented through a type-dispatch cascade such as if shape.type == "circle"/"square"/…, where adding "triangle" requires editing existing code. The refactoring route is polymorphic dispatch, for example through a Shape interface with a polymorphic render() (Pehlivan et al., 3 Sep 2025).
The Liskov Substitution Principle concerns behavioral substitutability. The canonical example is the Rectangle/Square mismatch, where a Square subclass overrides setWidth and setHeight in a way that breaks clients expecting independent width and height. The violation is not reducible to inheritance alone; it arises when overriding alters the effective contract of the base type (Pehlivan et al., 3 Sep 2025).
The Interface Segregation Principle is formulated as a preference for client-specific interfaces over broad interfaces with unrelated methods. The example given is a Printer interface with print(), scan(), and fax(), forcing a SimplePrinter to implement scan() and fax() unnecessarily. The refactoring decomposes the contract into PrintService, ScanService, and FaxService (Pehlivan et al., 3 Sep 2025).
The Dependency Inversion Principle requires high-level modules to depend on abstractions rather than concretions. The representative violation is an OrderProcessor that directly instantiates SqlOrderRepository(). The refactored version depends on IOrderRepository and injects SqlOrderRepository via composition (Pehlivan et al., 3 Sep 2025).
Taken together, these examples show that SOLID is operationalized through concrete code cues: multiple unrelated responsibilities for SRP, extension-by-editing for OCP, contract breakage for LSP, unused obligations for ISP, and concretion-bound dependencies for DIP. A plausible implication is that practical SOLID analysis depends on recognizing design intent and interaction structure, not only local syntax.
3. SOLID as an empirical benchmark for code analysis
Recent work turns SOLID from a normative design vocabulary into a benchmark task for LLMs. The benchmark contains 240 unique, manually validated code samples covering all five principles, with both violating and refactored non-violating versions. It is built from 20 representative violation scenarios, four per principle, and each sample carries one of the labels {SRP, OCP, LSP, ISP, DIP, No Violation} (Pehlivan et al., 3 Sep 2025).
The dataset spans Java, Python, Kotlin, and C#, and stratifies difficulty into Easy, Moderate, and Hard, with difficulty labels corroborated by character count and cyclomatic complexity. Drafts were initially produced with [gpt-4o](https://www.emergentmind.com/topics/vocabulary-assistant-llm-gpt-4o), then refined by one author and independently verified by a second author, with disagreements resolved by consensus. The evaluation therefore treats SOLID detection as a controlled multi-class classification problem rather than an informal prompting exercise (Pehlivan et al., 3 Sep 2025).
Four code-oriented LLMs were benchmarked: GPT-4o Mini, Qwen2.5-Coder-32B, DeepSeekCoder-33B, and CodeLlama-70B. All experiments used Temperature = 0 to maximize determinism and reproducibility, and outputs were required to follow a structured JSON schema. Correctness was defined strictly: a response was counted as correct only if it output exactly one principle or “No Violation” matching the ground-truth label (Pehlivan et al., 3 Sep 2025).
This benchmark framing is significant because it makes explicit what automated SOLID analysis demands. The task is not general commentary on code quality; it is forced-choice identification of the single intended violation class, even in borderline cases where multiple interpretations may appear plausible.
4. Prompting strategies for SOLID detection
The study evaluates four prompting strategies, each designed to expose different reasoning modes in LLM-based design analysis. DEFAULT is a zero-shot prompt that directly requests classification with definition reminders and a strict JSON schema. It serves as the baseline and is reported as best for SRP and ISP, where structural cues are relatively obvious (Pehlivan et al., 3 Sep 2025).
EXAMPLE is a few-shot, hint-based strategy. It embeds one concise hint per principle, such as “unrelated responsibilities” for SRP, “repeated if/switch where polymorphism fits” for OCP, “subclass breaks base contract” for LSP, “fat interfaces with unused methods” for ISP, and “depends on concretes rather than abstractions” for DIP. Its observed strengths are LSP and DIP, where the hints appear to anchor more abstract reasoning (Pehlivan et al., 3 Sep 2025).
SMELL is a chain-of-thought-style two-step prompt. It first asks the model to list design smells, then to score each SOLID principle from 0–5 and select the most violated one. In the reported results, this strategy underperformed across the board, and the paper attributes this to error propagation caused by the implicit mapping from smells to principles (Pehlivan et al., 3 Sep 2025).
ENSEMBLE is a deliberative scoring strategy. It asks the model to score SRP, OCP, LSP, ISP, and DIP individually, with one-line evidence for each, then select the top violation. This strategy is reported to excel at OCP detection, plausibly because comparative per-principle scoring makes extension pressure and type-dispatch anti-patterns more salient (Pehlivan et al., 3 Sep 2025).
A central empirical conclusion follows directly from these results: prompt strategy has a dramatic impact, but no single strategy is universally best. That finding directly counters the common assumption that a single well-written prompt can act as a stable detector for all SOLID principles.
5. Quantitative behavior across models, languages, and difficulty
The reported results establish a clear model hierarchy. GPT-4o Mini is described as decisively top, with F1 SRP = 99.7, OCP = 74.5, and ISP = 71.1. Qwen2.5-Coder-32B is a distant second, with SRP = 89.0, OCP = 58.8, and DIP = 10.8. CodeLlama-70B reaches SRP = 55.6, with notably low ISP performance at 13.6. DeepSeekCoder-33B fails to exceed F1 = 40 for any principle beyond SRP (Pehlivan et al., 3 Sep 2025).
Prompt performance is similarly differentiated by principle. ENSEMBLE is best for OCP with F1 = 75.7. EXAMPLE is best for LSP with F1 = 52.3 and for DIP with F1 = 11.8. DEFAULT is strong for SRP with F1 = 82.6 and ISP with F1 = 61.4. SMELL is consistently poor, including OCP = 13.6 and LSP = 23.0 (Pehlivan et al., 3 Sep 2025).
Language characteristics materially affect performance. C# and Java are highest overall; for SRP, C# = 67.2 and Java = 66.7. Kotlin is roughly on par with Java for LSP, 28.1 vs 27.6, but lags on other principles. Python is the lowest-accuracy language for four of five principles, which the paper links to dynamic typing and looser structure that obscure abstraction boundaries and interface intent (Pehlivan et al., 3 Sep 2025).
Complexity degrades performance sharply. For OCP, accuracy falls from 64.8 on easy samples to 18.0 on hard samples. LSP and DIP drop below 25 accuracy for moderate and hard samples. The study also reports a substantial tooling burden: 1,431 of 3,840 responses (37%) required manual review and labeling because of schema non-adherence and ambiguous outputs (Pehlivan et al., 3 Sep 2025).
These results indicate that SOLID detection is highly nonuniform across principle type, programming language, model family, and code complexity. A plausible implication is that benchmark scores for “design understanding” should not be interpreted as monolithic capabilities.
6. Practical use, limitations, and research directions
The paper proposes a practical pipeline for AI-assisted SOLID analysis. The workflow begins with repository ingestion and normalization by language, followed by computation of basic metrics such as size and cyclomatic complexity. Prompt selection is then guided by principle and language, with temperature = 0 and strict JSON enforcement. Inference may be single-prompt or multi-prompt; for hard samples, the recommended combination is ENSEMBLE plus EXAMPLE. Aggregation can then use majority vote or weights derived from historical per-principle F1, followed by human review for low-confidence or conflicting outputs (Pehlivan et al., 3 Sep 2025).
The associated decision heuristic is explicitly principle-specific. DEFAULT is preferred for SRP and ISP, ENSEMBLE for OCP, EXAMPLE for LSP and DIP, and Python should always receive hints and evidence requests. Hard samples should use multiple prompts, strict JSON, and evidence fields. This suggests that SOLID detection is best treated as a context-matched inference problem rather than a single-model classification service (Pehlivan et al., 3 Sep 2025).
The limitations are equally explicit. The dataset contains 240 synthetic examples and may not capture large industrial systems. Language coverage is restricted to four languages. Results depend strongly on prompting and parsing discipline, as reflected in the 37% manual-review rate. The authors also note the risk of overfitting to exemplars, temporal instability in model rankings, and incomplete coverage of framework-heavy or mixed-paradigm code (Pehlivan et al., 3 Sep 2025).
Future work identified in the study includes expanding dataset size and diversity with real-world code, adding more languages and frameworks, integrating with static analysis tools such as AST and type checking to improve precision for DIP and LSP, and moving from detection to automated refactoring validated by tests and expert review (Pehlivan et al., 3 Sep 2025). Within that trajectory, SOLID remains both a design taxonomy and a demanding benchmark for semantic program analysis, especially where extensibility, substitutability, and abstraction boundaries must be inferred rather than merely parsed.