- Added Cache-Control headers to various endpoints in CatalogController and SubscriptionsController to improve caching behavior and reduce server load. - Updated response structures to ensure consistent caching strategies across different API endpoints. - Improved overall performance by implementing throttling and caching mechanisms for better request management.
242 lines
7.3 KiB
Markdown
242 lines
7.3 KiB
Markdown
# Codebase Cleanup Analysis - Unnecessary Abstractions
|
|
|
|
## Executive Summary
|
|
|
|
After comprehensive audit, identified several categories of unnecessary abstractions that add complexity without value. This document catalogs findings and proposes removals.
|
|
|
|
---
|
|
|
|
## ✅ Already Fixed
|
|
|
|
### 1. **Checkout Normalizers** (Removed ~280 lines)
|
|
- ❌ `buildInternetCheckoutSelections()` - Trivial string trimming
|
|
- ❌ `buildSimCheckoutSelections()` - Trivial string trimming
|
|
- ❌ `deriveInternetCheckoutState()` - Reverse transformations
|
|
- ❌ `deriveSimCheckoutState()` - Reverse transformations
|
|
- ❌ `coalescePlanSku()` - Obsolete after plan/planSku cleanup
|
|
|
|
**Impact**: Frontend now directly builds URLSearchParams without domain layer interference.
|
|
|
|
---
|
|
|
|
## 🔍 Findings by Category
|
|
|
|
### Category A: Thin Service Wrappers (Keep - Have Purpose)
|
|
|
|
#### ✅ **KEEP** these services - they add value:
|
|
|
|
**`apps/portal/src/features/*/services/*.service.ts`**:
|
|
- `accountService` - Centralizes API endpoints, good
|
|
- `checkoutService` - Wraps API calls, provides error handling
|
|
- `ordersService` - Validates with Zod schemas post-fetch
|
|
- `catalogService` - Parses and validates catalog data with domain parsers
|
|
- `simActionsService` - Type-safe API wrappers
|
|
|
|
**Why keep?**:
|
|
1. Centralized API endpoint management
|
|
2. Error handling and logging
|
|
3. Response validation with Zod
|
|
4. Type safety layer between API and components
|
|
|
|
### Category B: Unnecessary Utility Wrappers
|
|
|
|
#### ❌ **CurrencyService** - Remove class wrapper
|
|
|
|
**Current** (`apps/portal/src/lib/services/currency.service.ts`):
|
|
```typescript
|
|
class CurrencyServiceImpl implements CurrencyService {
|
|
async getDefaultCurrency(): Promise<CurrencyInfo> {
|
|
const response = await apiClient.GET("/api/currency/default");
|
|
if (!response.data) throw new Error("...");
|
|
return response.data as CurrencyInfo;
|
|
}
|
|
// ...
|
|
}
|
|
export const currencyService = new CurrencyServiceImpl();
|
|
```
|
|
|
|
**Problem**:
|
|
- Unnecessary class + interface abstraction
|
|
- Just wraps apiClient calls
|
|
- No business logic, no validation
|
|
- Instance creation overhead
|
|
|
|
**Fix**: Make it a plain object like other services:
|
|
```typescript
|
|
export const currencyService = {
|
|
async getDefaultCurrency(): Promise<CurrencyInfo> {
|
|
const response = await apiClient.GET("/api/currency/default");
|
|
return getDataOrThrow(response, "Failed to get default currency");
|
|
},
|
|
// ...
|
|
};
|
|
```
|
|
|
|
**Impact**: Remove 10 lines, simpler, consistent with other services.
|
|
|
|
---
|
|
|
|
### Category C: Trivial Utility Functions
|
|
|
|
#### ❌ **cn() utility** - Questionable value
|
|
|
|
**Current** (`apps/portal/src/lib/utils/cn.ts`):
|
|
```typescript
|
|
export function cn(...inputs: ClassValue[]) {
|
|
return twMerge(clsx(inputs));
|
|
}
|
|
```
|
|
|
|
**Analysis**:
|
|
- Just combines two library calls
|
|
- Used everywhere, hard to remove now
|
|
- Consider: Is `twMerge(clsx(...))` really so hard to type?
|
|
|
|
**Verdict**: KEEP - too embedded, minimal harm. But document that new projects shouldn't add such thin wrappers.
|
|
|
|
#### ✅ **useDebounce** - Keep, adds real value
|
|
|
|
Implements actual logic (setTimeout management), not just a wrapper.
|
|
|
|
#### ✅ **useLocalStorage** - Keep, adds real value
|
|
|
|
Handles SSR safety, error handling, JSON serialization - significant logic.
|
|
|
|
---
|
|
|
|
### Category D: Potential Over-Engineering
|
|
|
|
#### 🤔 **CheckoutParamsService** - Could simplify
|
|
|
|
**Current** (`apps/portal/src/features/checkout/services/checkout-params.service.ts`):
|
|
- Static class with utility methods
|
|
- Pattern: `CheckoutParamsService.buildSnapshot(params)`
|
|
|
|
**Question**: Why a class? Could be plain functions:
|
|
```typescript
|
|
// Instead of:
|
|
CheckoutParamsService.buildSnapshot(params)
|
|
|
|
// Could be:
|
|
buildCheckoutSnapshot(params)
|
|
```
|
|
|
|
**Verdict**: KEEP for now - class provides namespace, not harmful enough to refactor.
|
|
|
|
---
|
|
|
|
## 🎯 Domain Layer Audit
|
|
|
|
### ✅ **Domain Layer is Clean!**
|
|
|
|
**Findings**:
|
|
- ✅ No `window`, `document`, `localStorage` references
|
|
- ✅ No React/Next.js dependencies
|
|
- ✅ No portal-specific logic
|
|
- ✅ Pure TypeScript + Zod
|
|
- ✅ Properly separated providers (Salesforce, WHMCS, Freebit)
|
|
|
|
**Only "next" references are in README examples - not actual code.**
|
|
|
|
### Domain Layer Best Practices (Already Following):
|
|
|
|
1. **Provider Pattern** ✅
|
|
- `packages/domain/*/providers/` - Clean separation
|
|
- Mappers transform external APIs to domain types
|
|
- Example: `transformWhmcsInvoice()`, `transformSalesforceOrder()`
|
|
|
|
2. **Schema-First Design** ✅
|
|
- All types derived from Zod schemas
|
|
- Runtime validation at boundaries
|
|
- Example: `invoiceSchema`, `orderDetailsSchema`
|
|
|
|
3. **No Frontend Concerns** ✅
|
|
- No URL handling
|
|
- No localStorage
|
|
- No React hooks
|
|
|
|
---
|
|
|
|
## 📊 Summary Statistics
|
|
|
|
| Category | Status | Lines Removed | Impact |
|
|
|----------|--------|---------------|--------|
|
|
| Checkout normalizers | ✅ Removed | ~280 | High - Simplified flow |
|
|
| Catalog store refactor | ✅ Simplified | ~50 | Medium - Direct params |
|
|
| Checkout params service | ✅ Simplified | ~20 | Low - Removed coalesce |
|
|
| CurrencyService | ⚠️ Can remove | ~10 | Low - Minor improvement |
|
|
| Domain layer | ✅ Already clean | 0 | N/A |
|
|
|
|
**Total Cleanup**: ~350 lines removed, significant complexity reduction.
|
|
|
|
---
|
|
|
|
## 🎯 Recommendations
|
|
|
|
### Immediate Actions (Already Done ✅)
|
|
1. ✅ Remove `buildInternetCheckoutSelections` and friends
|
|
2. ✅ Simplify catalog store URL param building
|
|
3. ✅ Remove `coalescePlanSku` backward compat
|
|
4. ✅ Clean up `checkout.ts` domain file
|
|
|
|
### Optional Future Actions
|
|
1. **Simplify CurrencyService**: Remove class wrapper (~10 lines)
|
|
2. **Document anti-patterns**: Add to CONTRIBUTING.md
|
|
- Don't wrap library functions (like `cn()`)
|
|
- Avoid unnecessary normalizers
|
|
- Frontend handles URL serialization
|
|
|
|
### Best Practices Going Forward
|
|
|
|
#### ✅ DO:
|
|
- Keep services that centralize API endpoints
|
|
- Keep services that add validation/error handling
|
|
- Keep utilities that implement real logic
|
|
- Use domain layer for types and validation only
|
|
|
|
#### ❌ DON'T:
|
|
- Create normalizers that just trim strings
|
|
- Wrap simple library calls in custom functions
|
|
- Put frontend concerns in domain layer
|
|
- Create class wrappers for simple API calls
|
|
|
|
---
|
|
|
|
## 🏆 Domain/Portal Alignment
|
|
|
|
### Current State: **EXCELLENT** ✅
|
|
|
|
```
|
|
packages/domain/ # Pure business logic
|
|
├── */contract.ts # TypeScript interfaces
|
|
├── */schema.ts # Zod validation
|
|
├── */providers/ # External API adapters
|
|
└── */helpers.ts # Domain utilities
|
|
|
|
apps/portal/src/
|
|
├── features/*/services/ # API client wrappers (good!)
|
|
├── features/*/hooks/ # React hooks (frontend-specific)
|
|
├── features/*/components/ # UI components
|
|
└── lib/ # Portal utilities
|
|
```
|
|
|
|
**Key Separation**:
|
|
- Domain: Types, validation, transformations
|
|
- Portal: API calls, UI state, React hooks
|
|
|
|
**No violations found!** The architecture is properly layered.
|
|
|
|
---
|
|
|
|
## 📝 Conclusion
|
|
|
|
The codebase is **generally well-structured**. Main issues were:
|
|
1. ✅ **Fixed**: Checkout normalizers (unnecessary abstractions)
|
|
2. ⚠️ **Minor**: CurrencyService class wrapper (optional fix)
|
|
3. ✅ **Already Good**: Domain layer separation
|
|
|
|
**Overall Grade**: B+ → A- after cleanup
|
|
|
|
The cleanup removed ~350 lines of unnecessary abstraction while maintaining all valuable service layers. Domain and portal are properly aligned with no cross-contamination.
|
|
|