Tax Hurdle — Technical Architecture & Code Analysis
Deep dive into design patterns, implementation details, and code quality assessment.
📑 Quick Navigation
- System Architecture
- Design Patterns
- Code Quality Analysis
- Thread Safety
- Performance Analysis
- Testing Strategy
- Recommendations
📐 System Architecture
Component Diagram
┌─────────────────────────────────────────────────────┐
│ InvestingHurdleBootstrapper (Singleton) │
│ • main() - entry point │
│ • getInstance() - singleton instance │
│ • reporterTesting() - output generation │
└─────────────┬───────────────────────────┬───────────┘
│ │
┌─────▼──────┐ ┌───▼────────┐ ┌─▼──────────┐
│WorkbookLoader│ │EquityLoader│ │HurdleLogger│
│ • loadBuys() │ │•calculateSTC│ │•getLogger()│
│ • loadSells()│ │•returnQtr() │ │•setupLog() │
└─────┬────────┘ └───┬────────┘ └────────────┘
│ │
└────────┬───────┘
│
┌────────▼────────┐
│ Security DAO │
│ • getter/setter│
│ • P&L compute │
└─────────────────┘
ConcurrentHashMap<String, Queue<Security>>
🏛️ Design Patterns
1. Singleton Pattern — InvestingHurdleBootstrapper
Purpose: Single application instance throughout lifecycle
Benefits: ✅ Single state ✅ Global access ✅ Thread-safe
Drawbacks: ⚠️ Hard to test ⚠️ Global state ⚠️ Difficult to mock
2. Factory Pattern — Security Object Creation
Purpose: Encapsulate creation of trade records
Benefits: ✅ Centralized creation ✅ Validation in one place ✅ Easy changes
3. Queue Pattern — FIFO Trade Processing
Purpose: Process buy/sell transactions chronologically
Implementation:
ConcurrentHashMap<String, Queue<Security>> securityMap
Benefits: ✅ Order preserved ✅ Natural FIFO matching ✅ Thread-safe
4. Strategy Pattern — Tax Calculation
Purpose: Different strategies for STCG vs. intraday
Recommendation: Create explicit strategy interface for clarity
🔍 Code Quality Analysis
Strengths ✅
| Aspect | Evidence |
|---|---|
| Error Handling | Custom InvalidSecurityException for validation |
| Logging | Comprehensive Log4j2 setup with rotation |
| Thread Safety | ConcurrentHashMap + ConcurrentLinkedQueue |
| Encapsulation | Private members, public getters/setters |
| Organization | Logical package structure |
| Constants | Dedicated HurdleConstant class |
Weaknesses ⚠️
| Issue | Severity | Impact |
|---|---|---|
| Hardcoded Quarter Dates | 🔴 HIGH | Only works for one FY |
Empty setAveragePrices() |
🔴 HIGH | Cost basis not calculated |
| No Unit Tests | 🔴 HIGH | No test coverage |
| Exception Swallowing | 🟡 MEDIUM | Errors lost in catch blocks |
| Static File Paths | 🟡 MEDIUM | No configuration flexibility |
| String Comparisons | 🟡 MEDIUM | Locale-dependent, fragile |
🔐 Thread Safety Analysis
Current Implementation:
private ConcurrentHashMap<String, Queue<Security>> securityMap =
new ConcurrentHashMap<>();
Thread-Safe Operations: ✅
computeIfAbsent()— atomicConcurrentLinkedQueue.offer()— thread-safe- Multiple threads can add to different queues
Potential Issues: ⚠️
- Check-then-act patterns need synchronization
- Complex multi-operation sequences may need coordination
📈 Performance Considerations
Time Complexity
| Operation | Complexity | Notes |
|---|---|---|
| Load buys | O(n) | n = buy rows |
| Load sells | O(n) | n = sell rows |
| Calculate STCG | O(m) | m = equity rows |
| Find quarter | O(1) | Fixed 5 comparisons |
| Overall | O(n + m) | Linear |
Space Complexity
- securityMap: O(n) where n = transactions
- Quarter buckets: O(5) — fixed
- Overall: O(n) — linear
🧪 Testing Strategy
Unit Tests Needed
@Test
public void testReturnQuarter_Q1() {
LocalDate q1Date = LocalDate.of(2021, 5, 15);
assertEquals(1, equityLoader.returnQuarter(q1Date));
}
@Test(expected = InvalidSecurityException.class)
public void testLoadBuys_NullSecurityName() {
loader.loadBuys();
}
@Test
public void testCalculateSTCG_Sum() {
Map<Integer, Double> result = equityLoader.calculateSTCG();
double totalSTCG = result.values().stream()
.mapToDouble(Double::doubleValue).sum();
assertTrue(totalSTCG > 0);
}
@Test
public void testSecurityCalculatesPLCorrectly() {
Security security = new Security("TCS", new Date(), 100, 10, 110);
assertEquals((110 - 100) * 10, security.calculatePL(), 0.01);
}
Integration Tests
@Test
public void testEndToEndTaxCalculation() {
// Create test Excel files, run workflow
InvestingHurdleBootstrapper app = InvestingHurdleBootstrapper.getInstance();
app.loadAndCalculate();
// Verify STCG matches expected
assertEquals(expectedTotal, app.getTotalSTCG(), 0.01);
}
Recommended Coverage
- ✅ 80%+ code coverage target
- ✅ All edge cases (boundary dates, zero values, negative P&L)
- ✅ Exception paths
- ✅ Thread safety scenarios
🎯 Recommendations Summary
Priority 1: Critical
- Add Unit Tests — Target 80%+ coverage
- Fix Hardcoded Quarter Dates — Support multi-year, use
LocalDate - Implement
setAveragePrices()— Critical for cost basis
Priority 2: Important
- Improve Exception Handling — Specific exceptions, proper logging
- Parameterize File Paths — Command-line args or config file
- Add Input Validation — Type checks, range validation
Priority 3: Enhancements
- Export Functionality — CSV, JSON, PDF formats
- Migrate to Java 8+ — Stream API,
java.timepackage - Database Integration — Persistence and queries
- Web UI — Spring Boot API + React/Vue frontend
Document Version: 1.0
Last Updated: December 31, 2025
| ← Back to Hub | Next: Refactoring Guide → |