Software Architecture Skill
This skill provides architectural guidance for enhancing and cleaning up the lib-electronic-components library.
Architecture Overview
┌─────────────────────────────────────────────────────────────────┐
│ ComponentType (Enum) │
│ ~200 component types │
│ Base types (RESISTOR) + Specific (RESISTOR_CHIP_VISHAY) │
└────────────────────────┬────────────────────────────────────────┘
│ matched by
▼
┌─────────────────────────────────────────────────────────────────┐
│ ComponentManufacturer (Enum) │
│ 50+ manufacturers │
│ Each holds: regex pattern + ManufacturerHandler │
└────────────────────────┬────────────────────────────────────────┘
│ delegates to
▼
┌─────────────────────────────────────────────────────────────────┐
│ ManufacturerHandler (Interface) │
│ 50+ implementations │
│ initializePatterns(), extractPackageCode(), extractSeries() │
└────────────────────────┬────────────────────────────────────────┘
│ populates
▼
┌─────────────────────────────────────────────────────────────────┐
│ PatternRegistry (Class) │
│ Map<ComponentType, Map<Class<?>, Set<Pattern>>> │
│ Multi-handler pattern storage │
└────────────────────────┬────────────────────────────────────────┘
│ used by
▼
┌─────────────────────────────────────────────────────────────────┐
│ ComponentSimilarityCalculator (Interface) │
│ 20+ implementations │
│ Per-component-type similarity strategies │
└─────────────────────────────────────────────────────────────────┘
Design Patterns In Use
| Pattern |
Implementation |
Location |
| Registry |
PatternRegistry |
Stores patterns by type and handler |
| Factory |
ManufacturerHandlerFactory |
Dynamic handler discovery |
| Strategy |
ComponentSimilarityCalculator |
Different algorithms per type |
| Enum Dispatch |
ComponentManufacturer |
Enum + handler association |
| Template Method |
ManufacturerHandler.matches() |
Default with override |
Critical Issues to Fix
RESOLVED ISSUES (PR #74, #75)
The following issues have been fixed:
TIHandler Pattern Duplication - FIXED
- Removed ~170 lines of duplicate COMPONENT_SERIES entries
- Fixed LM35/LM358 pattern conflict (LM35 sensors use letter suffix A-D)
No Base Handler Class - FIXED
- Created
AbstractManufacturerHandler with shared helper methods
- Methods:
extractSuffixAfterHyphen(), extractTrailingSuffix(), findFirstDigitIndex(), findLastDigitIndex()
Package Code Duplication - FIXED
- Created
PackageCodeRegistry with centralized mappings
- Includes standard codes (N→DIP, D→SOIC) and Atmel-specific (PU→PDIP, AU→TQFP)
Flaky Tests - FIXED
- Changed
ManufacturerHandlerFactory from HashSet to TreeSet with deterministic ordering
- Handler iteration order is now consistent across all test runs
ComponentType.getManufacturer() Fragile - FIXED
- Was using string matching on manufacturer names (fragile)
- Fixed with explicit
MANUFACTURER_SUFFIX_MAP for special cases (ON→ON_SEMI, AD→ANALOG_DEVICES)
- Direct enum
valueOf() lookup for standard cases
TIHandlerPatterns.java Unused - FIXED (deleted)
- File existed but was never used after TIHandler consolidation
- Safely deleted
Package Code Registry (IMPLEMENTED)
The PackageCodeRegistry class has been created to centralize package code mappings:
// Usage in handlers:
String resolvedCode = PackageCodeRegistry.resolve("PU"); // Returns "PDIP"
boolean isKnown = PackageCodeRegistry.isKnownCode("N"); // Returns true
boolean isPower = PackageCodeRegistry.isPowerPackage("TO-220"); // Returns true
Supported codes include:
- Standard: N→DIP, D→SOIC, PW→TSSOP, DGK→MSOP, DBV→SOT-23
- Power: T→TO-220, KC→TO-252, MP→SOT-223
- Atmel-specific: PU→PDIP, AU→TQFP, MU→QFN, SU→SOIC, XU→TSSOP
Next step: Migrate existing handlers to use the registry instead of inline maps.
Test Coverage Status (January 2026)
| Area |
Files |
With Tests |
Gap |
Priority |
| Handlers |
56 |
40 (71.4%) |
16 handlers |
HIGH |
| Similarity Calculators |
20 |
0 (0%) |
All untested |
HIGH |
| PatternRegistry |
1 |
0 |
No tests |
MEDIUM |
| ManufacturerHandlerFactory |
1 |
0 |
No tests |
LOW |
Handlers WITHOUT Tests (16):
Abracon, AKM, Cree, DiodesInc, Epson, Fairchild, IQD, LG, LogicIC, Lumileds, NDK, Nexteria, OSRAM, Qualcomm, Spansion, Unknown
Similarity Calculators (ALL untested):
CapacitorSimilarityCalculator, ConnectorSimilarityCalculator, DiodeSimilarityCalculator, LEDSimilarityCalculator, MCUSimilarityCalculator, MemorySimilarityCalculator, MosfetSimilarityCalculator, OpAmpSimilarityCalculator, ResistorSimilarityCalculator, SensorSimilarityCalculator, TransistorSimilarityCalculator, VoltageRegulatorSimilarityCalculator, MicrocontrollerSimilarityCalculator, DefaultSimilarityCalculator, PassiveComponentCalculator, LevenshteinCalculator
Priority tests to add:
Handler tests - For each handler:
@Test void shouldDetectComponentType()
@Test void shouldExtractPackageCode()
@Test void shouldExtractSeries()
@Test void shouldIdentifyReplacements()
Pattern conflict tests:
@Test void noTwoHandlersShouldClaimSameMPN()
Similarity calculator tests:
@Test void resistorsSameValueShouldBeHighSimilarity()
@Test void differentComponentTypesShouldBeLowSimilarity()
Refactoring Priorities
COMPLETED (PR #74, #75)
Deduplicate TIHandler COMPONENT_SERIES - Done, removed ~170 lines
Create AbstractManufacturerHandler - Done
Create PackageCodeRegistry - Done
Fix flaky tests (handler ordering) - Done, uses TreeSet now
Priority 1: High (Structural Improvements)
Migrate handlers to use AbstractManufacturerHandler
- Many handlers still use duplicate helper methods
- Files:
*Handler.java in manufacturers/
Migrate handlers to use PackageCodeRegistry
- Replace inline PACKAGE_CODES maps with registry calls
- Files:
*Handler.java in manufacturers/
Delete TIHandlerPatterns.java - DONE
Priority 2: Medium (Quality Improvements)
Add Handler Unit Tests
- Test each handler's pattern matching
- New files:
*HandlerTest.java
Fix ComponentType.getManufacturer() - DONE
- Fixed with explicit MANUFACTURER_SUFFIX_MAP
Add Similarity Calculator Tests
- Test each calculator
- New files:
*SimilarityCalculatorTest.java
Priority 3: Low (Enhancements)
- Standardize Pattern Approaches
- Consistent regex style across handlers
- All handlers in
manufacturers/
Technical Debt Inventory (January 2026)
Production Debug Statements (181 total - HIGH priority)
| File |
Count |
Notes |
| MPNUtils.java |
35 |
Heaviest concentration |
| ManufacturerHandlerFactory.java |
17 |
Also has 8 printStackTrace() |
| ComponentTypeDetector.java |
17 |
|
| ConnectorSimilarityCalculator.java |
16 |
|
| Similarity calculators (combined) |
97 |
All 13 calculators affected |
Action: Replace with SLF4J logging framework.
printStackTrace() Calls (9 total - HIGH priority)
| File |
Lines |
| ManufacturerHandlerFactory.java |
56, 66, 110, 123, 149, 155, 186, 191 |
| MPNUtils.java |
298 |
Action: Replace with logger.error("message", exception).
Inconsistent getSupportedTypes() Pattern
| Pattern |
Count |
Handlers |
| Set.of() (modern) |
28 |
AtmelHandler, STHandler, TIHandler, BoschHandler, HiroseHandler, JSTHandler, MolexHandler, EspressifHandler, LogicICHandler, MaximHandler, PanasonicHandler, VishayHandler, etc. |
| new HashSet() (legacy) |
29 |
CreeHandler, AbraconHandler, LGHandler, NordicHandler, etc. |
Action: Standardize all to Set.of() for immutability and conciseness.
Note: 5 handlers fixed in PR #89: EspressifHandler, LogicICHandler, MaximHandler, PanasonicHandler, VishayHandler
Type/Pattern Registration Mismatches (Critical bugs)
| Handler |
Issue |
Status |
| MaximHandler |
Declared INTERFACE_IC_MAXIM, RTC_MAXIM, BATTERY_MANAGEMENT_MAXIM without patterns |
✅ FIXED (PR #89) |
| EspressifHandler |
Declared ESP8266_SOC, ESP32_SOC, all module types but only registered MICROCONTROLLER |
✅ FIXED (PR #89) |
| PanasonicHandler |
Declared capacitor/inductor types but no patterns registered |
✅ FIXED (PR #89) |
Impact: matches() returns false for declared types because patterns aren't registered.
Fix pattern: When adding a type to getSupportedTypes(), MUST also add patterns in initializePatterns().
Code Quality Issues
| File |
Issue |
Line(s) |
Status |
| LogicICHandler.java |
Debug System.out.println in production code |
70, 75, 84, 85 |
✅ FIXED (PR #89) |
| EspressifHandler.java |
NPE risk - substring without indexOf check |
153-154 |
✅ FIXED (PR #89) |
| InfineonHandler.java |
Commented-out code blocks |
44, 49, 51 |
Open |
Magic Numbers in Scoring (108+ instances)
All similarity calculators use hardcoded weights:
// Varies by calculator - no consistent values!
HIGH_SIMILARITY = 0.9
MEDIUM_SIMILARITY = 0.5-0.7 // Inconsistent!
LOW_SIMILARITY = 0.3
// Scoring increments vary wildly
valueMatch = 0.3-0.5
packageMatch = 0.2-0.4
Action: Extract to configurable SimilarityWeights constants class.
Code Smell Indicators
When reviewing code, watch for:
| Smell |
Example |
Fix |
| Duplicate Map.put() |
Same key added twice |
Remove duplicate |
| Hardcoded package codes |
return "TO-220" |
Use PackageCodeRegistry |
| Copy-pasted regex |
Same pattern in 3 handlers |
Extract to constant |
| Giant switch statement |
50+ cases |
Use Map lookup |
| Unused ComponentSeriesInfo |
Defined but never queried |
Remove or use |
File Reference Quick Guide
| Task |
Primary Files |
| Add manufacturer |
ComponentManufacturer.java, new *Handler.java |
| Add component type |
ComponentType.java, handler initializePatterns() |
| Fix pattern matching |
Handler's matches() method |
| Add similarity logic |
New *SimilarityCalculator.java, register in MPNUtils |
| Debug MPN detection |
ComponentManufacturer.fromMPN(), handler patterns |
Learnings & Quirks
Architecture Decisions
ComponentManufacturer enum tightly couples manufacturer identity with handler - this is intentional for performance (single lookup)
PatternRegistry supports multi-handler per type but this feature is largely unused
- Similarity calculators are registered in
MPNUtils static initializer (lines 34-48)
Critical Implementation Details
Handler Ordering (PR #75):
ManufacturerHandlerFactory MUST use TreeSet with deterministic comparator
HashSet caused flaky tests because iteration order varied between runs
- First matching handler wins in
getManufacturerHandler() - order is critical!
Type Detection Specificity (PR #74):
MPNUtils.getComponentType() uses specificity scoring via getTypeSpecificityScore()
- Manufacturer-specific types (OPAMP_TI) score +150, generic types (IC) score -50
- Without scoring, iteration order could return IC instead of OPAMP_TI
ComponentType.getBaseType() Completeness:
- All manufacturer-specific types MUST be in the switch statement
- Missing types fall through to
default -> this (returns self, not base type)
- Fixed in PR #74: Added TRANSISTOR_VISHAY, TRANSISTOR_NXP, OPAMP_ON, OPAMP_NXP, OPAMP_ROHM
ComponentType.getManufacturer() Mapping (PR #76):
- Uses explicit
MANUFACTURER_SUFFIX_MAP for special cases (ON→ON_SEMI, AD→ANALOG_DEVICES, SILABS→SILICON_LABS, DIODES→DIODES_INC)
- Falls back to direct
ComponentManufacturer.valueOf(suffix) for standard cases
- Much more reliable than previous string-contains matching
Cross-Handler Pattern Matching (PR #90 - CRITICAL FIX):
- Default
ManufacturerHandler.matches() was using PatternRegistry.getPattern(type) which returned the first pattern from ANY handler
- This caused false matches when handlers were tested in alphabetical order (e.g., CypressHandler before STHandler)
- Fix: Added
matchesForCurrentHandler() to PatternRegistry that only checks patterns for the current handler
- IMPORTANT: 7 handlers had custom
matches() overrides with the same bug (using patterns.getPattern(type) as fallback):
- NXPHandler, FairchildHandler, OnSemiHandler, MaximHandler, KemetHandler, WinbondHandler, TIHandler
- All fixed by replacing fallback with
patterns.matchesForCurrentHandler()
- Key insight: If tests pass locally but fail in CI, check for HashMap iteration order differences
Known Gotchas
- Handler order in
ComponentManufacturer affects detection priority for ambiguous MPNs
- Some MPNs legitimately match multiple manufacturers (second-source parts)
- Handlers with custom matches() overrides: Must use
patterns.matchesForCurrentHandler() NOT patterns.getPattern(type) for fallback matching
- CI vs Local differences: Usually caused by HashMap/HashSet iteration order - always use deterministic collections
Historical Context
- CI test failures (pre-PR #75) were caused by non-deterministic HashSet iteration
- Test stability now achieved via TreeSet with class name comparator
- PR #90: Fixed cross-handler pattern matching that caused STM32 MPNs to match CypressHandler
- Some handlers have commented-out patterns (e.g.,
ComponentManufacturer.java lines 45-53) - unclear if deprecated or WIP
See Also
Advanced Skills
/handler-pattern-design - Handler patterns, anti-patterns, and cleanup checklists
/similarity-calculator-architecture - Calculator ordering and architectural patterns
/component-type-detection-hierarchy - Type system architecture and specificity
/manufacturer-detection-from-mpn - Manufacturer detection patterns and ordering
Documentation
- HISTORY.md - Technical debt history and completed work
- .docs/history/ - Detailed analyses of architectural decisions
1---2name: architecture-183description: Use when refactoring, cleaning up, or enhancing the lib-electronic-components codebase. Provides guidance on architecture patterns, known issues, duplication hotspots, and recommended improvements.4---5
6# Software Architecture Skill
7
8This skill provides architectural guidance for enhancing and cleaning up the lib-electronic-components library.
9
10## Architecture Overview
11
12```
13┌─────────────────────────────────────────────────────────────────┐
14│ ComponentType (Enum) │
15│ ~200 component types │
16│ Base types (RESISTOR) + Specific (RESISTOR_CHIP_VISHAY) │
17└────────────────────────┬────────────────────────────────────────┘
18 │ matched by
19 ▼
20┌─────────────────────────────────────────────────────────────────┐
21│ ComponentManufacturer (Enum) │
22│ 50+ manufacturers │
23│ Each holds: regex pattern + ManufacturerHandler │
24└────────────────────────┬────────────────────────────────────────┘
25 │ delegates to
26 ▼
27┌─────────────────────────────────────────────────────────────────┐
28│ ManufacturerHandler (Interface) │
29│ 50+ implementations │
30│ initializePatterns(), extractPackageCode(), extractSeries() │
31└────────────────────────┬────────────────────────────────────────┘
32 │ populates
33 ▼
34┌─────────────────────────────────────────────────────────────────┐
35│ PatternRegistry (Class) │
36│ Map<ComponentType, Map<Class<?>, Set<Pattern>>> │
37│ Multi-handler pattern storage │
38└────────────────────────┬────────────────────────────────────────┘
39 │ used by
40 ▼
41┌─────────────────────────────────────────────────────────────────┐
42│ ComponentSimilarityCalculator (Interface) │
43│ 20+ implementations │
44│ Per-component-type similarity strategies │
45└─────────────────────────────────────────────────────────────────┘
46```
47
48## Design Patterns In Use
49
50| Pattern | Implementation | Location |
51|---------|---------------|----------|
52| Registry | `PatternRegistry` | Stores patterns by type and handler |
53| Factory | `ManufacturerHandlerFactory` | Dynamic handler discovery |
54| Strategy | `ComponentSimilarityCalculator` | Different algorithms per type |
55| Enum Dispatch | `ComponentManufacturer` | Enum + handler association |
56| Template Method | `ManufacturerHandler.matches()` | Default with override |
57
58---
59
60## Critical Issues to Fix
61
62### RESOLVED ISSUES (PR #74, #75)
63
64The following issues have been fixed:
65
661. **TIHandler Pattern Duplication** - FIXED
67 - Removed ~170 lines of duplicate COMPONENT_SERIES entries
68 - Fixed LM35/LM358 pattern conflict (LM35 sensors use letter suffix A-D)
69
702. **No Base Handler Class** - FIXED
71 - Created `AbstractManufacturerHandler` with shared helper methods
72 - Methods: `extractSuffixAfterHyphen()`, `extractTrailingSuffix()`, `findFirstDigitIndex()`, `findLastDigitIndex()`
73
743. **Package Code Duplication** - FIXED
75 - Created `PackageCodeRegistry` with centralized mappings
76 - Includes standard codes (N→DIP, D→SOIC) and Atmel-specific (PU→PDIP, AU→TQFP)
77
784. **Flaky Tests** - FIXED
79 - Changed `ManufacturerHandlerFactory` from `HashSet` to `TreeSet` with deterministic ordering
80 - Handler iteration order is now consistent across all test runs
81
825. **ComponentType.getManufacturer() Fragile** - FIXED
83 - Was using string matching on manufacturer names (fragile)
84 - Fixed with explicit `MANUFACTURER_SUFFIX_MAP` for special cases (ON→ON_SEMI, AD→ANALOG_DEVICES)
85 - Direct enum `valueOf()` lookup for standard cases
86
876. **TIHandlerPatterns.java Unused** - FIXED (deleted)
88 - File existed but was never used after TIHandler consolidation
89 - Safely deleted
90
91---
92
93## Package Code Registry (IMPLEMENTED)
94
95The `PackageCodeRegistry` class has been created to centralize package code mappings:
96
97```java
98// Usage in handlers:
99String resolvedCode = PackageCodeRegistry.resolve("PU"); // Returns "PDIP"
100boolean isKnown = PackageCodeRegistry.isKnownCode("N"); // Returns true
101boolean isPower = PackageCodeRegistry.isPowerPackage("TO-220"); // Returns true
102```
103
104**Supported codes include**:
105- Standard: N→DIP, D→SOIC, PW→TSSOP, DGK→MSOP, DBV→SOT-23
106- Power: T→TO-220, KC→TO-252, MP→SOT-223
107- Atmel-specific: PU→PDIP, AU→TQFP, MU→QFN, SU→SOIC, XU→TSSOP
108
109**Next step**: Migrate existing handlers to use the registry instead of inline maps.
110
111---
112
113## Test Coverage Status (January 2026)
114
115| Area | Files | With Tests | Gap | Priority |
116|------|-------|------------|-----|----------|
117| Handlers | 56 | 40 (71.4%) | 16 handlers | HIGH |
118| Similarity Calculators | 20 | 0 (0%) | All untested | HIGH |
119| PatternRegistry | 1 | 0 | No tests | MEDIUM |
120| ManufacturerHandlerFactory | 1 | 0 | No tests | LOW |
121
122**Handlers WITHOUT Tests (16)**:
123Abracon, AKM, Cree, DiodesInc, Epson, Fairchild, IQD, LG, LogicIC, Lumileds, NDK, Nexteria, OSRAM, Qualcomm, Spansion, Unknown
124
125**Similarity Calculators (ALL untested)**:
126CapacitorSimilarityCalculator, ConnectorSimilarityCalculator, DiodeSimilarityCalculator, LEDSimilarityCalculator, MCUSimilarityCalculator, MemorySimilarityCalculator, MosfetSimilarityCalculator, OpAmpSimilarityCalculator, ResistorSimilarityCalculator, SensorSimilarityCalculator, TransistorSimilarityCalculator, VoltageRegulatorSimilarityCalculator, MicrocontrollerSimilarityCalculator, DefaultSimilarityCalculator, PassiveComponentCalculator, LevenshteinCalculator
127
128**Priority tests to add**:
129
1301. **Handler tests** - For each handler:
131 ```java
132 @Test void shouldDetectComponentType()
133 @Test void shouldExtractPackageCode()
134 @Test void shouldExtractSeries()
135 @Test void shouldIdentifyReplacements()
136 ```
137
1382. **Pattern conflict tests**:
139 ```java
140 @Test void noTwoHandlersShouldClaimSameMPN()
141 ```
142
1433. **Similarity calculator tests**:
144 ```java
145 @Test void resistorsSameValueShouldBeHighSimilarity()
146 @Test void differentComponentTypesShouldBeLowSimilarity()
147 ```
148
149---
150
151## Refactoring Priorities
152
153### COMPLETED (PR #74, #75)
154
155- ~~Deduplicate TIHandler COMPONENT_SERIES~~ - Done, removed ~170 lines
156- ~~Create AbstractManufacturerHandler~~ - Done
157- ~~Create PackageCodeRegistry~~ - Done
158- ~~Fix flaky tests (handler ordering)~~ - Done, uses TreeSet now
159
160### Priority 1: High (Structural Improvements)
161
1621. **Migrate handlers to use AbstractManufacturerHandler**
163 - Many handlers still use duplicate helper methods
164 - Files: `*Handler.java` in `manufacturers/`
165
1662. **Migrate handlers to use PackageCodeRegistry**
167 - Replace inline PACKAGE_CODES maps with registry calls
168 - Files: `*Handler.java` in `manufacturers/`
169
1703. ~~**Delete TIHandlerPatterns.java**~~ - DONE
171 - Deleted unused file
172
173### Priority 2: Medium (Quality Improvements)
174
1754. **Add Handler Unit Tests**
176 - Test each handler's pattern matching
177 - New files: `*HandlerTest.java`
178
1795. ~~**Fix ComponentType.getManufacturer()**~~ - DONE
180 - Fixed with explicit MANUFACTURER_SUFFIX_MAP
181
1826. **Add Similarity Calculator Tests**
183 - Test each calculator
184 - New files: `*SimilarityCalculatorTest.java`
185
186### Priority 3: Low (Enhancements)
187
1887. **Standardize Pattern Approaches**
189 - Consistent regex style across handlers
190 - All handlers in `manufacturers/`
191
192---
193
194## Technical Debt Inventory (January 2026)
195
196### Production Debug Statements (181 total - HIGH priority)
197
198| File | Count | Notes |
199|------|-------|-------|
200| MPNUtils.java | 35 | Heaviest concentration |
201| ManufacturerHandlerFactory.java | 17 | Also has 8 printStackTrace() |
202| ComponentTypeDetector.java | 17 | |
203| ConnectorSimilarityCalculator.java | 16 | |
204| Similarity calculators (combined) | 97 | All 13 calculators affected |
205
206**Action**: Replace with SLF4J logging framework.
207
208### printStackTrace() Calls (9 total - HIGH priority)
209
210| File | Lines |
211|------|-------|
212| ManufacturerHandlerFactory.java | 56, 66, 110, 123, 149, 155, 186, 191 |
213| MPNUtils.java | 298 |
214
215**Action**: Replace with `logger.error("message", exception)`.
216
217### Inconsistent getSupportedTypes() Pattern
218
219| Pattern | Count | Handlers |
220|---------|-------|----------|
221| **Set.of() (modern)** | 28 | AtmelHandler, STHandler, TIHandler, BoschHandler, HiroseHandler, JSTHandler, MolexHandler, EspressifHandler, LogicICHandler, MaximHandler, PanasonicHandler, VishayHandler, etc. |
222| **new HashSet() (legacy)** | 29 | CreeHandler, AbraconHandler, LGHandler, NordicHandler, etc. |
223
224**Action**: Standardize all to Set.of() for immutability and conciseness.
225**Note**: 5 handlers fixed in PR #89: EspressifHandler, LogicICHandler, MaximHandler, PanasonicHandler, VishayHandler
226
227### Type/Pattern Registration Mismatches (Critical bugs)
228
229| Handler | Issue | Status |
230|---------|-------|--------|
231| MaximHandler | Declared INTERFACE_IC_MAXIM, RTC_MAXIM, BATTERY_MANAGEMENT_MAXIM without patterns | ✅ FIXED (PR #89) |
232| EspressifHandler | Declared ESP8266_SOC, ESP32_SOC, all module types but only registered MICROCONTROLLER | ✅ FIXED (PR #89) |
233| PanasonicHandler | Declared capacitor/inductor types but no patterns registered | ✅ FIXED (PR #89) |
234
235**Impact**: `matches()` returns false for declared types because patterns aren't registered.
236
237**Fix pattern**: When adding a type to `getSupportedTypes()`, MUST also add patterns in `initializePatterns()`.
238
239### Code Quality Issues
240
241| File | Issue | Line(s) | Status |
242|------|-------|---------|--------|
243| LogicICHandler.java | Debug System.out.println in production code | 70, 75, 84, 85 | ✅ FIXED (PR #89) |
244| EspressifHandler.java | NPE risk - substring without indexOf check | 153-154 | ✅ FIXED (PR #89) |
245| InfineonHandler.java | Commented-out code blocks | 44, 49, 51 | Open |
246
247### Magic Numbers in Scoring (108+ instances)
248
249All similarity calculators use hardcoded weights:
250```java
251// Varies by calculator - no consistent values!
252HIGH_SIMILARITY = 0.9
253MEDIUM_SIMILARITY = 0.5-0.7 // Inconsistent!
254LOW_SIMILARITY = 0.3
255
256// Scoring increments vary wildly
257valueMatch = 0.3-0.5
258packageMatch = 0.2-0.4
259```
260
261**Action**: Extract to configurable SimilarityWeights constants class.
262
263---
264
265## Code Smell Indicators
266
267When reviewing code, watch for:
268
269| Smell | Example | Fix |
270|-------|---------|-----|
271| Duplicate Map.put() | Same key added twice | Remove duplicate |
272| Hardcoded package codes | `return "TO-220"` | Use PackageCodeRegistry |
273| Copy-pasted regex | Same pattern in 3 handlers | Extract to constant |
274| Giant switch statement | 50+ cases | Use Map lookup |
275| Unused ComponentSeriesInfo | Defined but never queried | Remove or use |
276
277---
278
279## File Reference Quick Guide
280
281| Task | Primary Files |
282|------|---------------|
283| Add manufacturer | `ComponentManufacturer.java`, new `*Handler.java` |
284| Add component type | `ComponentType.java`, handler `initializePatterns()` |
285| Fix pattern matching | Handler's `matches()` method |
286| Add similarity logic | New `*SimilarityCalculator.java`, register in `MPNUtils` |
287| Debug MPN detection | `ComponentManufacturer.fromMPN()`, handler patterns |
288
289---
290
291## Learnings & Quirks
292
293### Architecture Decisions
294- `ComponentManufacturer` enum tightly couples manufacturer identity with handler - this is intentional for performance (single lookup)
295- `PatternRegistry` supports multi-handler per type but this feature is largely unused
296- Similarity calculators are registered in `MPNUtils` static initializer (lines 34-48)
297
298### Critical Implementation Details
299
300**Handler Ordering (PR #75)**:
301- `ManufacturerHandlerFactory` MUST use `TreeSet` with deterministic comparator
302- `HashSet` caused flaky tests because iteration order varied between runs
303- First matching handler wins in `getManufacturerHandler()` - order is critical!
304
305**Type Detection Specificity (PR #74)**:
306- `MPNUtils.getComponentType()` uses specificity scoring via `getTypeSpecificityScore()`
307- Manufacturer-specific types (OPAMP_TI) score +150, generic types (IC) score -50
308- Without scoring, iteration order could return IC instead of OPAMP_TI
309
310**ComponentType.getBaseType() Completeness**:
311- All manufacturer-specific types MUST be in the switch statement
312- Missing types fall through to `default -> this` (returns self, not base type)
313- Fixed in PR #74: Added TRANSISTOR_VISHAY, TRANSISTOR_NXP, OPAMP_ON, OPAMP_NXP, OPAMP_ROHM
314
315**ComponentType.getManufacturer() Mapping (PR #76)**:
316- Uses explicit `MANUFACTURER_SUFFIX_MAP` for special cases (ON→ON_SEMI, AD→ANALOG_DEVICES, SILABS→SILICON_LABS, DIODES→DIODES_INC)
317- Falls back to direct `ComponentManufacturer.valueOf(suffix)` for standard cases
318- Much more reliable than previous string-contains matching
319
320**Cross-Handler Pattern Matching (PR #90 - CRITICAL FIX)**:
321- Default `ManufacturerHandler.matches()` was using `PatternRegistry.getPattern(type)` which returned the first pattern from ANY handler
322- This caused false matches when handlers were tested in alphabetical order (e.g., CypressHandler before STHandler)
323- Fix: Added `matchesForCurrentHandler()` to PatternRegistry that only checks patterns for the current handler
324- **IMPORTANT**: 7 handlers had custom `matches()` overrides with the same bug (using `patterns.getPattern(type)` as fallback):
325 - NXPHandler, FairchildHandler, OnSemiHandler, MaximHandler, KemetHandler, WinbondHandler, TIHandler
326 - All fixed by replacing fallback with `patterns.matchesForCurrentHandler()`
327- Key insight: If tests pass locally but fail in CI, check for HashMap iteration order differences
328
329### Known Gotchas
330- Handler order in `ComponentManufacturer` affects detection priority for ambiguous MPNs
331- Some MPNs legitimately match multiple manufacturers (second-source parts)
332- **Handlers with custom matches() overrides**: Must use `patterns.matchesForCurrentHandler()` NOT `patterns.getPattern(type)` for fallback matching
333- **CI vs Local differences**: Usually caused by HashMap/HashSet iteration order - always use deterministic collections
334
335### Historical Context
336- CI test failures (pre-PR #75) were caused by non-deterministic HashSet iteration
337- Test stability now achieved via TreeSet with class name comparator
338- PR #90: Fixed cross-handler pattern matching that caused STM32 MPNs to match CypressHandler
339- Some handlers have commented-out patterns (e.g., `ComponentManufacturer.java` lines 45-53) - unclear if deprecated or WIP
340
341---
342
343## See Also
344
345### Advanced Skills
346- `/handler-pattern-design` - Handler patterns, anti-patterns, and cleanup checklists
347- `/similarity-calculator-architecture` - Calculator ordering and architectural patterns
348- `/component-type-detection-hierarchy` - Type system architecture and specificity
349- `/manufacturer-detection-from-mpn` - Manufacturer detection patterns and ordering
350
351### Documentation
352- **HISTORY.md** - Technical debt history and completed work
353- **.docs/history/** - Detailed analyses of architectural decisions
354
355---
356
357<!-- Add new learnings above this line -->