pdd-skills 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1478 -0
- package/bin/pdd.js +354 -0
- package/config/bpmn-rules.yaml +166 -0
- package/config/checkstyle.xml +105 -0
- package/config/eslint.config.js +48 -0
- package/config/pmd.xml +91 -0
- package/config/prd-rules.yaml +113 -0
- package/config/ruff.toml +45 -0
- package/config/sqlfluff.cfg +82 -0
- package/hooks/hook-executor.js +332 -0
- package/index.js +43 -0
- package/lib/api-routes.js +750 -0
- package/lib/api-server.js +408 -0
- package/lib/cache/cache-config.js +209 -0
- package/lib/cache/system-cache.js +852 -0
- package/lib/config-manager.js +373 -0
- package/lib/generate.js +528 -0
- package/lib/grpc/grpc-routes.js +1134 -0
- package/lib/grpc/grpc-server.js +912 -0
- package/lib/grpc/proto-definitions.js +1033 -0
- package/lib/init.js +172 -0
- package/lib/iteration/auto-fixer.js +1025 -0
- package/lib/iteration/auto-reviewer.js +923 -0
- package/lib/iteration/controller.js +577 -0
- package/lib/list.js +130 -0
- package/lib/mcp-server.js +548 -0
- package/lib/openclaw/api-integration.js +535 -0
- package/lib/openclaw/cli-integration.js +567 -0
- package/lib/openclaw/data-sync.js +845 -0
- package/lib/openclaw/openclaw-adapter.js +783 -0
- package/lib/plugin/example-plugins/code-stats/index.js +332 -0
- package/lib/plugin/example-plugins/code-stats/plugin.json +1 -0
- package/lib/plugin/example-plugins/custom-linter/index.js +472 -0
- package/lib/plugin/example-plugins/custom-linter/plugin.json +1 -0
- package/lib/plugin/example-plugins/hello-world/index.js +86 -0
- package/lib/plugin/example-plugins/hello-world/plugin.json +1 -0
- package/lib/plugin/plugin-manager.js +655 -0
- package/lib/plugin/plugin-sdk.js +565 -0
- package/lib/plugin/sandbox.js +627 -0
- package/lib/quality/rules/maintainability.js +418 -0
- package/lib/quality/rules/performance.js +498 -0
- package/lib/quality/rules/readability.js +441 -0
- package/lib/quality/rules/robustness.js +504 -0
- package/lib/quality/rules/security.js +444 -0
- package/lib/quality/scorer.js +576 -0
- package/lib/report.js +669 -0
- package/lib/sdk-base.js +301 -0
- package/lib/sdk-js.js +446 -0
- package/lib/sdk-python/README.md +546 -0
- package/lib/sdk-python/examples/basic_usage.py +450 -0
- package/lib/sdk-python/pdd_sdk/__init__.py +180 -0
- package/lib/sdk-python/pdd_sdk/client.py +1170 -0
- package/lib/sdk-python/pdd_sdk/events.py +423 -0
- package/lib/sdk-python/pdd_sdk/exceptions.py +158 -0
- package/lib/sdk-python/pdd_sdk/models.py +518 -0
- package/lib/sdk-python/pdd_sdk/utils.py +759 -0
- package/lib/token/budget-alert.js +367 -0
- package/lib/token/budget-manager.js +485 -0
- package/lib/update.js +54 -0
- package/lib/utils/logger.js +88 -0
- package/lib/verify.js +741 -0
- package/lib/version.js +52 -0
- package/lib/vm/README.md +102 -0
- package/lib/vm/dashboard/api-routes.js +669 -0
- package/lib/vm/dashboard/server.js +391 -0
- package/lib/vm/dashboard/sse.js +358 -0
- package/lib/vm/dashboard/static/css/dashboard.css +1378 -0
- package/lib/vm/dashboard/static/index.html +118 -0
- package/lib/vm/dashboard/static/js/app.js +949 -0
- package/lib/vm/dashboard/static/js/charts.js +913 -0
- package/lib/vm/dashboard/static/js/kanban-view.js +1053 -0
- package/lib/vm/dashboard/static/js/pipeline-view.js +463 -0
- package/lib/vm/dashboard/static/js/quality-view.js +598 -0
- package/lib/vm/dashboard/static/js/system-view.js +1021 -0
- package/lib/vm/data-provider.js +1191 -0
- package/lib/vm/event-bus.js +402 -0
- package/lib/vm/hooks/extract-hook.js +307 -0
- package/lib/vm/hooks/generate-hook.js +374 -0
- package/lib/vm/hooks/hook-interface.js +458 -0
- package/lib/vm/hooks/report-hook.js +331 -0
- package/lib/vm/hooks/verify-hook.js +454 -0
- package/lib/vm/models.js +1003 -0
- package/lib/vm/reconciler.js +855 -0
- package/lib/vm/scanner.js +988 -0
- package/lib/vm/state-schema.js +955 -0
- package/lib/vm/state-store.js +733 -0
- package/lib/vm/tui/components/card.js +339 -0
- package/lib/vm/tui/components/progress-bar.js +368 -0
- package/lib/vm/tui/components/sparkline.js +327 -0
- package/lib/vm/tui/components/status-light.js +294 -0
- package/lib/vm/tui/components/table.js +370 -0
- package/lib/vm/tui/input.js +335 -0
- package/lib/vm/tui/renderer.js +548 -0
- package/lib/vm/tui/screens/kanban-screen.js +397 -0
- package/lib/vm/tui/screens/overview-screen.js +357 -0
- package/lib/vm/tui/screens/quality-screen.js +336 -0
- package/lib/vm/tui/screens/system-screen.js +379 -0
- package/lib/vm/tui/tui.js +805 -0
- package/package.json +1 -0
- package/scripts/cso-analyzer.js +198 -0
- package/scripts/eval-runner.js +359 -0
- package/scripts/i18n-checker.js +109 -0
- package/scripts/linter/activiti-linter.js +272 -0
- package/scripts/linter/prd-linter.js +162 -0
- package/scripts/linter/report-generator.js +207 -0
- package/scripts/linter/run-linters.js +285 -0
- package/scripts/linter/sql-linter.js +166 -0
- package/scripts/token-analyzer.js +162 -0
- package/scripts/vm-test.js +180 -0
- package/skills/core/official-doc-writer/LICENSE +21 -0
- package/skills/core/official-doc-writer/README.md +232 -0
- package/skills/core/official-doc-writer/SKILL.md +475 -0
- package/skills/core/official-doc-writer/_meta.json +1 -0
- package/skills/core/official-doc-writer/document_generator.py +580 -0
- package/skills/core/official-doc-writer/evals/default-evals.json +1 -0
- package/skills/core/official-doc-writer/examples.md +150 -0
- package/skills/core/official-doc-writer/fonts/FONTS_LIST.md +45 -0
- package/skills/core/official-doc-writer/fonts/README.md +141 -0
- package/skills/core/official-doc-writer/fonts/SIMFANG.TTF +0 -0
- package/skills/core/official-doc-writer/fonts/SIMHEI.TTF +0 -0
- package/skills/core/official-doc-writer/fonts/SIMKAI.TTF +0 -0
- package/skills/core/official-doc-writer/fonts/SIMSUN.TTC +0 -0
- package/skills/core/official-doc-writer/fonts//346/226/271/346/255/243/345/260/217/346/240/207/345/256/213GBK.TTF +0 -0
- package/skills/core/official-doc-writer/references/GBT_9704-2012_/345/205/232/346/224/277/346/234/272/345/205/263/345/205/254/346/226/207/346/240/274/345/274/217.md +422 -0
- package/skills/core/official-doc-writer/scripts/__pycache__/generate_official_doc.cpython-313.pyc +0 -0
- package/skills/core/official-doc-writer/scripts/dialog_manager.py +564 -0
- package/skills/core/official-doc-writer/scripts/generate_official_doc.py +252 -0
- package/skills/core/official-doc-writer/scripts/install_fonts.py +390 -0
- package/skills/core/official-doc-writer/scripts/smart_prompts.py +363 -0
- package/skills/core/pdd-ba/SKILL.md +305 -0
- package/skills/core/pdd-ba/_meta.json +1 -0
- package/skills/core/pdd-ba/evals/default-evals.json +1 -0
- package/skills/core/pdd-code-reviewer/SKILL.md +378 -0
- package/skills/core/pdd-code-reviewer/_meta.json +1 -0
- package/skills/core/pdd-code-reviewer/evals/default-evals.json +1 -0
- package/skills/core/pdd-doc-change/SKILL.md +350 -0
- package/skills/core/pdd-doc-change/_meta.json +1 -0
- package/skills/core/pdd-doc-change/evals/default-evals.json +1 -0
- package/skills/core/pdd-doc-gardener/SKILL.md +248 -0
- package/skills/core/pdd-doc-gardener/_meta.json +1 -0
- package/skills/core/pdd-doc-gardener/evals/default-evals.json +1 -0
- package/skills/core/pdd-entropy-reduction/SKILL.md +360 -0
- package/skills/core/pdd-entropy-reduction/_meta.json +1 -0
- package/skills/core/pdd-entropy-reduction/evals/default-evals.json +1 -0
- package/skills/core/pdd-entropy-reduction/references/entropy-report-template.md +287 -0
- package/skills/core/pdd-entropy-reduction/references/golden-principles.md +573 -0
- package/skills/core/pdd-entropy-reduction/scripts/entropy_scan.py +712 -0
- package/skills/core/pdd-extract-features/SKILL.md +320 -0
- package/skills/core/pdd-extract-features/_meta.json +1 -0
- package/skills/core/pdd-extract-features/evals/default-evals.json +1 -0
- package/skills/core/pdd-generate-spec/SKILL.md +418 -0
- package/skills/core/pdd-generate-spec/_meta.json +1 -0
- package/skills/core/pdd-generate-spec/evals/default-evals.json +1 -0
- package/skills/core/pdd-implement-feature/SKILL.md +332 -0
- package/skills/core/pdd-implement-feature/_meta.json +1 -0
- package/skills/core/pdd-implement-feature/evals/default-evals.json +1 -0
- package/skills/core/pdd-main/SKILL.md +540 -0
- package/skills/core/pdd-main/_meta.json +1 -0
- package/skills/core/pdd-main/evals/default-evals.json +1 -0
- package/skills/core/pdd-main/evals/evals.json +215 -0
- package/skills/core/pdd-verify-feature/SKILL.md +474 -0
- package/skills/core/pdd-verify-feature/_meta.json +1 -0
- package/skills/core/pdd-verify-feature/evals/default-evals.json +1 -0
- package/skills/core/pdd-vm/evals/default-evals.json +1 -0
- package/skills/core/traffic-accident-assessor/LICENSE +29 -0
- package/skills/core/traffic-accident-assessor/SKILL.md +439 -0
- package/skills/core/traffic-accident-assessor/evals/evals.json +1 -0
- package/skills/core/traffic-accident-assessor/references/accident-types.md +369 -0
- package/skills/core/traffic-accident-assessor/references/liability-rules.md +287 -0
- package/skills/core/traffic-accident-assessor/references/traffic-laws.md +226 -0
- package/skills/core/traffic-accident-assessor/references//351/253/230/345/260/224/345/244/253/350/257/264/346/230/216/344/271/246.pdf +32576 -106
- package/skills/core/traffic-accident-assessor/scripts/generate_official_statement.py +588 -0
- package/skills/core/traffic-accident-assessor/scripts/generate_report.py +495 -0
- package/skills/core/traffic-accident-assessor/scripts/generate_statement.py +528 -0
- package/skills/core/traffic-accident-assessor.zip +0 -0
- package/skills/entropy/expert-arch-enforcer/SKILL.md +292 -0
- package/skills/entropy/expert-arch-enforcer/_meta.json +1 -0
- package/skills/entropy/expert-arch-enforcer/evals/default-evals.json +1 -0
- package/skills/entropy/expert-auto-refactor/SKILL.md +327 -0
- package/skills/entropy/expert-auto-refactor/_meta.json +1 -0
- package/skills/entropy/expert-auto-refactor/evals/default-evals.json +1 -0
- package/skills/entropy/expert-code-quality/SKILL.md +468 -0
- package/skills/entropy/expert-code-quality/_meta.json +1 -0
- package/skills/entropy/expert-code-quality/evals/default-evals.json +1 -0
- package/skills/entropy/expert-code-quality/evals/evals.json +109 -0
- package/skills/entropy/expert-code-quality/references/code-smells.md +605 -0
- package/skills/entropy/expert-code-quality/references/design-patterns.md +1111 -0
- package/skills/entropy/expert-code-quality/references/refactoring-catalog.md +1281 -0
- package/skills/entropy/expert-code-quality/references/solid-principles.md +524 -0
- package/skills/entropy/expert-entropy-auditor/SKILL.md +276 -0
- package/skills/entropy/expert-entropy-auditor/_meta.json +1 -0
- package/skills/entropy/expert-entropy-auditor/evals/default-evals.json +1 -0
- package/skills/expert/expert-activiti/SKILL.md +497 -0
- package/skills/expert/expert-activiti/_meta.json +1 -0
- package/skills/expert/expert-mysql/SKILL.md +832 -0
- package/skills/expert/expert-mysql/_meta.json +1 -0
- package/skills/expert/expert-performance/SKILL.md +379 -0
- package/skills/expert/expert-performance/_meta.json +1 -0
- package/skills/expert/expert-performance/evals/default-evals.json +1 -0
- package/skills/expert/expert-ruoyi/SKILL.md +472 -0
- package/skills/expert/expert-ruoyi/_meta.json +1 -0
- package/skills/expert/expert-security/SKILL.md +1341 -0
- package/skills/expert/expert-security/_meta.json +1 -0
- package/skills/expert/expert-security/evals/default-evals.json +1 -0
- package/skills/expert/software-architect/SKILL.md +350 -0
- package/skills/expert/software-architect/_meta.json +1 -0
- package/skills/expert/software-engineer/SKILL.md +437 -0
- package/skills/expert/software-engineer/_meta.json +1 -0
- package/skills/expert/software-engineer/architecture.md +130 -0
- package/skills/expert/software-engineer/patterns.md +151 -0
- package/skills/expert/software-engineer/testing.md +135 -0
- package/skills/expert/system-architect/SKILL.md +628 -0
- package/skills/expert/system-architect/_meta.json +1 -0
- package/skills/expert/system-architect/assets/templates/ARCHITECTURE.md +25 -0
- package/skills/expert/system-architect/assets/templates/README.md +44 -0
- package/skills/expert/system-architect/references/js-ts-standards.md +18 -0
- package/skills/expert/system-architect/references/python-standards.md +19 -0
- package/skills/expert/system-architect/references/scaffolding.md +61 -0
- package/skills/expert/system-architect/references/security-checklist.md +21 -0
- package/skills/openspec/openspec-apply-change/SKILL.md +156 -0
- package/skills/openspec/openspec-apply-change/_meta.json +1 -0
- package/skills/openspec/openspec-archive-change/SKILL.md +114 -0
- package/skills/openspec/openspec-archive-change/_meta.json +1 -0
- package/skills/openspec/openspec-bulk-archive-change/SKILL.md +246 -0
- package/skills/openspec/openspec-bulk-archive-change/_meta.json +1 -0
- package/skills/openspec/openspec-continue-change/SKILL.md +118 -0
- package/skills/openspec/openspec-continue-change/_meta.json +1 -0
- package/skills/openspec/openspec-explore/SKILL.md +288 -0
- package/skills/openspec/openspec-explore/_meta.json +1 -0
- package/skills/openspec/openspec-ff-change/SKILL.md +101 -0
- package/skills/openspec/openspec-ff-change/_meta.json +1 -0
- package/skills/openspec/openspec-new-change/SKILL.md +74 -0
- package/skills/openspec/openspec-new-change/_meta.json +1 -0
- package/skills/openspec/openspec-onboard/SKILL.md +554 -0
- package/skills/openspec/openspec-onboard/_meta.json +1 -0
- package/skills/openspec/openspec-sync-specs/SKILL.md +138 -0
- package/skills/openspec/openspec-sync-specs/_meta.json +1 -0
- package/skills/openspec/openspec-verify-change/SKILL.md +168 -0
- package/skills/openspec/openspec-verify-change/_meta.json +1 -0
- package/skills/pr/pdd-multi-review/SKILL.md +534 -0
- package/skills/pr/pdd-multi-review/_meta.json +1 -0
- package/skills/pr/pdd-pr-batch/SKILL.md +303 -0
- package/skills/pr/pdd-pr-batch/_meta.json +1 -0
- package/skills/pr/pdd-pr-create/SKILL.md +344 -0
- package/skills/pr/pdd-pr-create/_meta.json +1 -0
- package/skills/pr/pdd-pr-merge/SKILL.md +286 -0
- package/skills/pr/pdd-pr-merge/_meta.json +1 -0
- package/skills/pr/pdd-pr-review/SKILL.md +217 -0
- package/skills/pr/pdd-pr-review/_meta.json +1 -0
- package/skills/pr/pdd-task-manager/SKILL.md +636 -0
- package/skills/pr/pdd-task-manager/_meta.json +1 -0
- package/skills/pr/pdd-template-engine/SKILL.md +306 -0
- package/skills/pr/pdd-template-engine/_meta.json +1 -0
- package/templates/behavior-shaping/iron-law-template.md +87 -0
- package/templates/behavior-shaping/rationalization-template.md +62 -0
- package/templates/behavior-shaping/red-flags-template.md +70 -0
- package/templates/bilingual-template.md +139 -0
- package/templates/config/default.yaml +47 -0
- package/templates/project/default/README.md +31 -0
- package/templates/project/frontend/README.md +46 -0
- package/templates/project/java/README.md +48 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
# SOLID Principles Reference
|
|
2
|
+
|
|
3
|
+
A comprehensive guide to the five SOLID principles of object-oriented design.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Overview](#1-overview)
|
|
8
|
+
2. [Single Responsibility Principle (SRP)](#2-single-responsibility-principle-srp)
|
|
9
|
+
3. [Open/Closed Principle (OCP)](#3-openclosed-principle-ocp)
|
|
10
|
+
4. [Liskov Substitution Principle (LSP)](#4-liskov-substitution-principle-lsp)
|
|
11
|
+
5. [Interface Segregation Principle (ISP)](#5-interface-segregation-principle-isp)
|
|
12
|
+
6. [Dependency Inversion Principle (DIP)](#6-dependency-inversion-principle-dip)
|
|
13
|
+
7. [SOLID Quick Reference](#7-solid-quick-reference)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. Overview
|
|
18
|
+
|
|
19
|
+
SOLID is an acronym for five design principles intended to make software designs more understandable, flexible, and maintainable.
|
|
20
|
+
|
|
21
|
+
| Letter | Principle | Key Concept |
|
|
22
|
+
|--------|-----------|-------------|
|
|
23
|
+
| **S** | Single Responsibility | One reason to change |
|
|
24
|
+
| **O** | Open/Closed | Open for extension, closed for modification |
|
|
25
|
+
| **L** | Liskov Substitution | Subtypes must be substitutable |
|
|
26
|
+
| **I** | Interface Segregation | Small, focused interfaces |
|
|
27
|
+
| **D** | Dependency Inversion | Depend on abstractions |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2. Single Responsibility Principle (SRP)
|
|
32
|
+
|
|
33
|
+
### Definition
|
|
34
|
+
|
|
35
|
+
> A class should have only one reason to change.
|
|
36
|
+
|
|
37
|
+
### Explanation
|
|
38
|
+
|
|
39
|
+
Every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class.
|
|
40
|
+
|
|
41
|
+
### Violation Detection
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
□ Does the class have more than one "reason to change"?
|
|
45
|
+
□ Does the class name contain "and" or "or"?
|
|
46
|
+
□ Are there groups of methods using different instance variables?
|
|
47
|
+
□ Is the class doing more than one thing?
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Example: Violation
|
|
51
|
+
|
|
52
|
+
```java
|
|
53
|
+
// VIOLATION: Employee has multiple reasons to change
|
|
54
|
+
public class Employee {
|
|
55
|
+
private String name;
|
|
56
|
+
private double salary;
|
|
57
|
+
|
|
58
|
+
// Reason 1: Employee data changes
|
|
59
|
+
public String getName() { return name; }
|
|
60
|
+
public double getSalary() { return salary; }
|
|
61
|
+
|
|
62
|
+
// Reason 2: Pay calculation changes
|
|
63
|
+
public double calculatePay() { /* ... */ }
|
|
64
|
+
public double calculateTax() { /* ... */ }
|
|
65
|
+
|
|
66
|
+
// Reason 3: Reporting changes
|
|
67
|
+
public String generateReport() { /* ... */ }
|
|
68
|
+
public void printReport() { /* ... */ }
|
|
69
|
+
|
|
70
|
+
// Reason 4: Persistence changes
|
|
71
|
+
public void save() { /* ... */ }
|
|
72
|
+
public void load() { /* ... */ }
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Example: Correct
|
|
77
|
+
|
|
78
|
+
```java
|
|
79
|
+
// Each class has one reason to change
|
|
80
|
+
public class Employee {
|
|
81
|
+
private String name;
|
|
82
|
+
private double salary;
|
|
83
|
+
|
|
84
|
+
public String getName() { return name; }
|
|
85
|
+
public double getSalary() { return salary; }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public class PayCalculator {
|
|
89
|
+
public double calculatePay(Employee employee) { /* ... */ }
|
|
90
|
+
public double calculateTax(Employee employee) { /* ... */ }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public class EmployeeReporter {
|
|
94
|
+
public String generateReport(Employee employee) { /* ... */ }
|
|
95
|
+
public void printReport(String report) { /* ... */ }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public class EmployeeRepository {
|
|
99
|
+
public void save(Employee employee) { /* ... */ }
|
|
100
|
+
public Employee load(int id) { /* ... */ }
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Benefits
|
|
105
|
+
|
|
106
|
+
- Easier to understand
|
|
107
|
+
- Easier to test
|
|
108
|
+
- Easier to maintain
|
|
109
|
+
- Lower coupling
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 3. Open/Closed Principle (OCP)
|
|
114
|
+
|
|
115
|
+
### Definition
|
|
116
|
+
|
|
117
|
+
> Software entities should be open for extension, but closed for modification.
|
|
118
|
+
|
|
119
|
+
### Explanation
|
|
120
|
+
|
|
121
|
+
You should be able to extend a class's behavior without modifying its source code. This is typically achieved through abstractions and polymorphism.
|
|
122
|
+
|
|
123
|
+
### Violation Detection
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
□ Do you need to modify existing code to add new behavior?
|
|
127
|
+
□ Are there switch statements on type?
|
|
128
|
+
□ Do you need to touch multiple files for one feature?
|
|
129
|
+
□ Is adding new types difficult?
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Example: Violation
|
|
133
|
+
|
|
134
|
+
```java
|
|
135
|
+
// VIOLATION: Must modify class to add new shapes
|
|
136
|
+
public class AreaCalculator {
|
|
137
|
+
public double calculateArea(Object shape) {
|
|
138
|
+
if (shape instanceof Circle) {
|
|
139
|
+
Circle circle = (Circle) shape;
|
|
140
|
+
return Math.PI * circle.getRadius() * circle.getRadius();
|
|
141
|
+
} else if (shape instanceof Rectangle) {
|
|
142
|
+
Rectangle rectangle = (Rectangle) shape;
|
|
143
|
+
return rectangle.getWidth() * rectangle.getHeight();
|
|
144
|
+
}
|
|
145
|
+
// Must add new "else if" for each new shape!
|
|
146
|
+
throw new IllegalArgumentException("Unknown shape");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Example: Correct
|
|
152
|
+
|
|
153
|
+
```java
|
|
154
|
+
// Open for extension, closed for modification
|
|
155
|
+
public interface Shape {
|
|
156
|
+
double calculateArea();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public class Circle implements Shape {
|
|
160
|
+
private double radius;
|
|
161
|
+
|
|
162
|
+
public double calculateArea() {
|
|
163
|
+
return Math.PI * radius * radius;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public class Rectangle implements Shape {
|
|
168
|
+
private double width;
|
|
169
|
+
private double height;
|
|
170
|
+
|
|
171
|
+
public double calculateArea() {
|
|
172
|
+
return width * height;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Adding new shapes doesn't require modifying existing code
|
|
177
|
+
public class Triangle implements Shape {
|
|
178
|
+
private double base;
|
|
179
|
+
private double height;
|
|
180
|
+
|
|
181
|
+
public double calculateArea() {
|
|
182
|
+
return 0.5 * base * height;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Calculator never needs modification
|
|
187
|
+
public class AreaCalculator {
|
|
188
|
+
public double calculateArea(Shape shape) {
|
|
189
|
+
return shape.calculateArea();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Benefits
|
|
195
|
+
|
|
196
|
+
- No risk of breaking existing functionality
|
|
197
|
+
- Easy to add new features
|
|
198
|
+
- Follows Single Responsibility Principle
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 4. Liskov Substitution Principle (LSP)
|
|
203
|
+
|
|
204
|
+
### Definition
|
|
205
|
+
|
|
206
|
+
> Subtypes must be substitutable for their base types without altering the correctness of the program.
|
|
207
|
+
|
|
208
|
+
### Explanation
|
|
209
|
+
|
|
210
|
+
If S is a subtype of T, then objects of type T may be replaced with objects of type S without altering any of the desirable properties of the program.
|
|
211
|
+
|
|
212
|
+
### Violation Detection
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
□ Does subclass throw unexpected exceptions?
|
|
216
|
+
□ Does subclass return unexpected values?
|
|
217
|
+
□ Does subclass have stricter preconditions?
|
|
218
|
+
□ Does subclass have weaker postconditions?
|
|
219
|
+
□ Does subclass violate base class invariants?
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Example: Violation
|
|
223
|
+
|
|
224
|
+
```java
|
|
225
|
+
// VIOLATION: Square is not a proper Rectangle
|
|
226
|
+
public class Rectangle {
|
|
227
|
+
protected double width;
|
|
228
|
+
protected double height;
|
|
229
|
+
|
|
230
|
+
public void setWidth(double width) { this.width = width; }
|
|
231
|
+
public void setHeight(double height) { this.height = height; }
|
|
232
|
+
|
|
233
|
+
public double getArea() { return width * height; }
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
public class Square extends Rectangle {
|
|
237
|
+
@Override
|
|
238
|
+
public void setWidth(double width) {
|
|
239
|
+
this.width = width;
|
|
240
|
+
this.height = width; // Violates Rectangle behavior!
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@Override
|
|
244
|
+
public void setHeight(double height) {
|
|
245
|
+
this.width = height; // Violates Rectangle behavior!
|
|
246
|
+
this.height = height;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Client code breaks
|
|
251
|
+
void resizeRectangle(Rectangle rect) {
|
|
252
|
+
rect.setWidth(5);
|
|
253
|
+
rect.setHeight(4);
|
|
254
|
+
// Expected: area = 20
|
|
255
|
+
// With Square: area = 16 (unexpected!)
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Example: Correct
|
|
260
|
+
|
|
261
|
+
```java
|
|
262
|
+
// Correct: Use composition or proper hierarchy
|
|
263
|
+
public abstract class Shape {
|
|
264
|
+
public abstract double getArea();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
public class Rectangle extends Shape {
|
|
268
|
+
private double width;
|
|
269
|
+
private double height;
|
|
270
|
+
|
|
271
|
+
public double getArea() { return width * height; }
|
|
272
|
+
// setWidth and setHeight are Rectangle-specific
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
public class Square extends Shape {
|
|
276
|
+
private double side;
|
|
277
|
+
|
|
278
|
+
public double getArea() { return side * side; }
|
|
279
|
+
public void setSide(double side) { this.side = side; }
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### LSP Rules
|
|
284
|
+
|
|
285
|
+
| Rule | Description |
|
|
286
|
+
|------|-------------|
|
|
287
|
+
| **Signature Rule** | Subtype method signatures must match |
|
|
288
|
+
| **Methods Rule** | Subtype methods must return subtype |
|
|
289
|
+
| **Properties Rule** | Subtype must preserve invariants |
|
|
290
|
+
| **Preconditions** | Cannot be stronger in subtype |
|
|
291
|
+
| **Postconditions** | Cannot be weaker in subtype |
|
|
292
|
+
|
|
293
|
+
### Benefits
|
|
294
|
+
|
|
295
|
+
- Reliable polymorphism
|
|
296
|
+
- Predictable behavior
|
|
297
|
+
- Reusable code
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## 5. Interface Segregation Principle (ISP)
|
|
302
|
+
|
|
303
|
+
### Definition
|
|
304
|
+
|
|
305
|
+
> Clients should not be forced to depend on interfaces they do not use.
|
|
306
|
+
|
|
307
|
+
### Explanation
|
|
308
|
+
|
|
309
|
+
Many client-specific interfaces are better than one general-purpose interface. No client should be forced to depend on methods it does not use.
|
|
310
|
+
|
|
311
|
+
### Violation Detection
|
|
312
|
+
|
|
313
|
+
```
|
|
314
|
+
□ Does interface have many methods?
|
|
315
|
+
□ Do implementations throw "UnsupportedOperationException"?
|
|
316
|
+
□ Do clients only use some methods?
|
|
317
|
+
□ Is interface "fat"?
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Example: Violation
|
|
321
|
+
|
|
322
|
+
```java
|
|
323
|
+
// VIOLATION: Fat interface
|
|
324
|
+
public interface Worker {
|
|
325
|
+
void work();
|
|
326
|
+
void eat();
|
|
327
|
+
void sleep();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
public class Human implements Worker {
|
|
331
|
+
public void work() { /* works */ }
|
|
332
|
+
public void eat() { /* eats */ }
|
|
333
|
+
public void sleep() { /* sleeps */ }
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
public class Robot implements Worker {
|
|
337
|
+
public void work() { /* works */ }
|
|
338
|
+
public void eat() {
|
|
339
|
+
throw new UnsupportedOperationException("Robots don't eat!");
|
|
340
|
+
}
|
|
341
|
+
public void sleep() {
|
|
342
|
+
throw new UnsupportedOperationException("Robots don't sleep!");
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Example: Correct
|
|
348
|
+
|
|
349
|
+
```java
|
|
350
|
+
// Segregated interfaces
|
|
351
|
+
public interface Workable {
|
|
352
|
+
void work();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
public interface Feedable {
|
|
356
|
+
void eat();
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
public interface Sleepable {
|
|
360
|
+
void sleep();
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
public class Human implements Workable, Feedable, Sleepable {
|
|
364
|
+
public void work() { /* works */ }
|
|
365
|
+
public void eat() { /* eats */ }
|
|
366
|
+
public void sleep() { /* sleeps */ }
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
public class Robot implements Workable {
|
|
370
|
+
public void work() { /* works */ }
|
|
371
|
+
// No need to implement eat() or sleep()
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### Benefits
|
|
376
|
+
|
|
377
|
+
- No unnecessary dependencies
|
|
378
|
+
- Easier to implement
|
|
379
|
+
- Clearer contracts
|
|
380
|
+
- Better cohesion
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## 6. Dependency Inversion Principle (DIP)
|
|
385
|
+
|
|
386
|
+
### Definition
|
|
387
|
+
|
|
388
|
+
> High-level modules should not depend on low-level modules. Both should depend on abstractions.
|
|
389
|
+
> Abstractions should not depend on details. Details should depend on abstractions.
|
|
390
|
+
|
|
391
|
+
### Explanation
|
|
392
|
+
|
|
393
|
+
The principle suggests that we should decouple high-level modules from low-level modules by introducing an abstraction layer between them.
|
|
394
|
+
|
|
395
|
+
### Violation Detection
|
|
396
|
+
|
|
397
|
+
```
|
|
398
|
+
□ Does high-level class directly instantiate low-level class?
|
|
399
|
+
□ Are there "new" keywords in business logic?
|
|
400
|
+
□ Is code difficult to test?
|
|
401
|
+
□ Are dependencies hardcoded?
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Example: Violation
|
|
405
|
+
|
|
406
|
+
```java
|
|
407
|
+
// VIOLATION: High-level depends on low-level
|
|
408
|
+
public class UserService {
|
|
409
|
+
private MySQLDatabase database; // Direct dependency
|
|
410
|
+
|
|
411
|
+
public UserService() {
|
|
412
|
+
this.database = new MySQLDatabase(); // Hardcoded
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
public User getUser(int id) {
|
|
416
|
+
return database.query("SELECT * FROM users WHERE id = " + id);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### Example: Correct
|
|
422
|
+
|
|
423
|
+
```java
|
|
424
|
+
// Correct: Depend on abstractions
|
|
425
|
+
public interface Database {
|
|
426
|
+
User query(String sql);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
public class MySQLDatabase implements Database {
|
|
430
|
+
public User query(String sql) { /* MySQL implementation */ }
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
public class PostgreSQLDatabase implements Database {
|
|
434
|
+
public User query(String sql) { /* PostgreSQL implementation */ }
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
public class UserService {
|
|
438
|
+
private Database database; // Depends on abstraction
|
|
439
|
+
|
|
440
|
+
public UserService(Database database) { // Dependency injection
|
|
441
|
+
this.database = database;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
public User getUser(int id) {
|
|
445
|
+
return database.query("SELECT * FROM users WHERE id = " + id);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Usage
|
|
450
|
+
UserService service = new UserService(new MySQLDatabase());
|
|
451
|
+
UserService service = new UserService(new PostgreSQLDatabase());
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Dependency Injection Types
|
|
455
|
+
|
|
456
|
+
| Type | Description |
|
|
457
|
+
|------|-------------|
|
|
458
|
+
| **Constructor Injection** | Dependencies passed in constructor |
|
|
459
|
+
| **Setter Injection** | Dependencies set via setters |
|
|
460
|
+
| **Interface Injection** | Dependencies via interface method |
|
|
461
|
+
| **Field Injection** | Dependencies set directly on fields (not recommended) |
|
|
462
|
+
|
|
463
|
+
### Benefits
|
|
464
|
+
|
|
465
|
+
- Loose coupling
|
|
466
|
+
- Easy to test (mock dependencies)
|
|
467
|
+
- Easy to change implementations
|
|
468
|
+
- Follows Open/Closed Principle
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## 7. SOLID Quick Reference
|
|
473
|
+
|
|
474
|
+
### Principle Summary
|
|
475
|
+
|
|
476
|
+
| Principle | Problem | Solution |
|
|
477
|
+
|-----------|---------|----------|
|
|
478
|
+
| **SRP** | Class doing too much | Split into focused classes |
|
|
479
|
+
| **OCP** | Must modify to extend | Use abstractions |
|
|
480
|
+
| **LSP** | Subclass breaks behavior | Ensure substitutability |
|
|
481
|
+
| **ISP** | Fat interfaces | Split into small interfaces |
|
|
482
|
+
| **DIP** | High depends on low | Depend on abstractions |
|
|
483
|
+
|
|
484
|
+
### Code Smell → SOLID Principle
|
|
485
|
+
|
|
486
|
+
| Code Smell | Violated Principle |
|
|
487
|
+
|------------|-------------------|
|
|
488
|
+
| Large Class | SRP |
|
|
489
|
+
| Divergent Change | SRP |
|
|
490
|
+
| Shotgun Surgery | OCP |
|
|
491
|
+
| Switch Statements | OCP |
|
|
492
|
+
| Refused Bequest | LSP |
|
|
493
|
+
| Fat Interface | ISP |
|
|
494
|
+
| Tight Coupling | DIP |
|
|
495
|
+
|
|
496
|
+
### SOLID → Pattern Mapping
|
|
497
|
+
|
|
498
|
+
| Principle | Supporting Patterns |
|
|
499
|
+
|-----------|---------------------|
|
|
500
|
+
| **SRP** | Facade, Mediator |
|
|
501
|
+
| **OCP** | Strategy, Observer, Decorator |
|
|
502
|
+
| **LSP** | Template Method, Null Object |
|
|
503
|
+
| **ISP** | Adapter, Facade |
|
|
504
|
+
| **DIP** | Dependency Injection, Factory, Strategy |
|
|
505
|
+
|
|
506
|
+
### Quick Checklist
|
|
507
|
+
|
|
508
|
+
```
|
|
509
|
+
□ Does each class have one responsibility?
|
|
510
|
+
□ Can you extend without modifying?
|
|
511
|
+
□ Are subclasses substitutable for parents?
|
|
512
|
+
□ Are interfaces small and focused?
|
|
513
|
+
□ Do you depend on abstractions, not concretions?
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Refactoring to SOLID
|
|
517
|
+
|
|
518
|
+
| From | To | Refactoring |
|
|
519
|
+
|------|-----|-------------|
|
|
520
|
+
| Large class | SRP | Extract Class |
|
|
521
|
+
| Switch on type | OCP | Replace Conditional with Polymorphism |
|
|
522
|
+
| Subclass violations | LSP | Replace Inheritance with Delegation |
|
|
523
|
+
| Fat interface | ISP | Extract Interface |
|
|
524
|
+
| Direct instantiation | DIP | Replace Constructor with Factory |
|