refactor: address code review findings across all projects
Apply comprehensive fixes from code reviews including: - Extract shared utilities (SqlFormatHelper, CellValueConverter, DbDestinationBase) - Add interface abstractions (IAuthenticationService, IDatabaseMigrator, IMisQueryBuilder) - Implement SecureStore for encrypted secrets storage - Fix error handling with proper HTTP status codes and logging - Optimize double enumeration in DevEtlRegistry - Add DataSync.Dev README for developer onboarding - Extract filter panel base classes to reduce duplication - Update code review docs to mark all issues as fixed
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
# Code Review: JdeScoping.Core
|
||||
|
||||
**Project Path:** `NEW/src/JdeScoping.Core`
|
||||
**Layer:** Domain
|
||||
**Purpose:** Core models, DTOs, interfaces
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The JdeScoping.Core project is the domain layer containing core models, DTOs, interfaces, and shared contracts. The codebase demonstrates **good architectural practices** with clear separation of concerns, proper use of nullable reference types, and consistent documentation.
|
||||
|
||||
**Overall Grade: B+**
|
||||
|
||||
| Category | Rating | Notes |
|
||||
|----------|--------|-------|
|
||||
| SOLID Principles | Good | Minor ISP violation |
|
||||
| Clean Architecture | Excellent | No inappropriate dependencies |
|
||||
| Code Organization | Excellent | Well-organized structure |
|
||||
| Error Handling | Good | `TryGetCriteria` method with logging support |
|
||||
| Testability | Excellent | Interface-based design |
|
||||
| Code Duplication | Fair | Repeated JDE date conversion pattern |
|
||||
| Async Patterns | Good | Consistent naming, CancellationToken support |
|
||||
| Null Safety | Good | Nullable enabled with proper annotations |
|
||||
| Documentation | Excellent | Comprehensive XML documentation |
|
||||
|
||||
---
|
||||
|
||||
## 1. SOLID Principles
|
||||
|
||||
### Single Responsibility Principle (SRP)
|
||||
|
||||
**Positive:** Most classes adhere well to SRP - each model represents a single domain concept.
|
||||
|
||||
### Interface Segregation Principle (ISP)
|
||||
|
||||
~~**Issue: IExcelExportService uses `object` parameter**~~ ✅ FIXED
|
||||
|
||||
~~```csharp
|
||||
public interface IExcelExportService
|
||||
{
|
||||
Task<byte[]> GenerateAsync(object search, CancellationToken cancellationToken = default);
|
||||
}
|
||||
```~~
|
||||
|
||||
~~**Recommendation:** Change to use strongly-typed `SearchModel` parameter.~~
|
||||
|
||||
**Resolution:** Changed `IExcelExportService.GenerateAsync` to accept `Core.Models.SearchResults.SearchModel` instead of `object`. The `ExcelExportService` implementation maps to its internal `ExcelIO.Models.Reporting.SearchModel` for Excel generation.
|
||||
|
||||
### Dependency Inversion Principle (DIP)
|
||||
|
||||
**Positive:** Service interfaces properly defined in Core layer with clean abstractions.
|
||||
|
||||
---
|
||||
|
||||
## 2. Clean Architecture
|
||||
|
||||
### Layer Separation
|
||||
|
||||
**Excellent:** Core project maintains proper architectural boundaries:
|
||||
- No references to infrastructure concerns
|
||||
- Only depends on abstraction packages
|
||||
- Defines contracts that outer layers implement
|
||||
|
||||
### ApiContracts Placement
|
||||
|
||||
The `ApiContracts` folder containing API client interfaces is appropriately placed in Core.
|
||||
|
||||
---
|
||||
|
||||
## 3. Code Organization
|
||||
|
||||
### Folder Structure
|
||||
|
||||
**Excellent:**
|
||||
```
|
||||
JdeScoping.Core/
|
||||
├── ApiContracts/Results/
|
||||
├── Helpers/
|
||||
├── Interfaces/
|
||||
├── Models/
|
||||
│ ├── Auth/, Enums/, Infrastructure/
|
||||
│ ├── Inventory/, Lookup/, Organization/
|
||||
│ ├── Pipelines/, Quality/, Search/
|
||||
│ ├── SearchResults/, WorkOrders/
|
||||
├── Options/
|
||||
└── ViewModels/
|
||||
```
|
||||
|
||||
### Partial Classes for Repository
|
||||
|
||||
Using partial classes to split `ILotFinderRepository` by functional area is a good organizational choice.
|
||||
|
||||
### Issues
|
||||
|
||||
**Issue: Inconsistent Record/Class Usage**
|
||||
|
||||
The codebase mixes classes and records inconsistently for DTOs.
|
||||
|
||||
**Recommendation:** Establish consistent pattern - use records for immutable DTOs.
|
||||
|
||||
---
|
||||
|
||||
## 4. Error Handling
|
||||
|
||||
~~**Issue: Silent Deserialization Failure**~~ ✅ FIXED
|
||||
|
||||
**Resolution:** Added `TryGetCriteria(out SearchCriteria? criteria, ILogger? logger = null)` method that:
|
||||
- Returns `true` if deserialization succeeded or JSON was empty
|
||||
- Returns `false` if deserialization failed
|
||||
- Logs at Warning level when logger is provided
|
||||
- Property getter uses the method without logging for backwards compatibility
|
||||
- Services that need logging can call `TryGetCriteria` directly with their logger
|
||||
|
||||
---
|
||||
|
||||
## 5. Testability
|
||||
|
||||
**Excellent:** Interface-based design with all services defined as interfaces, enabling easy mocking.
|
||||
|
||||
---
|
||||
|
||||
## 6. Code Duplication
|
||||
|
||||
### DRY Violation in Domain Models
|
||||
|
||||
Multiple domain models contain identical patterns for JDE date/time conversion:
|
||||
|
||||
```csharp
|
||||
private int LastUpdateDate { get; set; }
|
||||
private int LastUpdateTime { get; set; }
|
||||
public DateTime? LastUpdateDt => JdeDateConverter.ToDateTime(LastUpdateDate, LastUpdateTime);
|
||||
```
|
||||
|
||||
Pattern repeated in 13+ files.
|
||||
|
||||
**Recommendation:** Document why this pattern is intentionally repeated (e.g., for Dapper mapping compatibility).
|
||||
|
||||
### Duplicate ViewModel Classes
|
||||
|
||||
`LotViewModel` and `ComponentLotViewModel` have identical properties.
|
||||
|
||||
**Recommendation:** Consolidate or have `ComponentLotViewModel` inherit from `LotViewModel`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Async Patterns
|
||||
|
||||
**Good:** Consistent `Async` suffix naming, all async interface methods include `CancellationToken` parameters with defaults.
|
||||
|
||||
---
|
||||
|
||||
## 8. Null Safety
|
||||
|
||||
**Good:** Nullable reference types enabled with proper annotations.
|
||||
|
||||
**Issue: Inconsistent Null Guard in Constructor**
|
||||
|
||||
```csharp
|
||||
public SearchViewModel(Search search)
|
||||
{
|
||||
if (search == null) return; // Silent return on null
|
||||
}
|
||||
```
|
||||
|
||||
**Recommendation:** Throw `ArgumentNullException` or use factory method pattern.
|
||||
|
||||
---
|
||||
|
||||
## 9. Documentation
|
||||
|
||||
**Excellent:** Nearly all public members have XML documentation with `<summary>`, `<param>`, and `<returns>` tags.
|
||||
|
||||
---
|
||||
|
||||
## 10. Additional Observations
|
||||
|
||||
### Well-Designed API Result Pattern
|
||||
|
||||
The `ApiResult<T>` discriminated union using OneOf provides compile-time safety for error handling.
|
||||
|
||||
### Data Type Mismatch
|
||||
|
||||
`AddressNumber` is `long` in `JdeUser` but `int` in `OperatorViewModel` - potential data loss.
|
||||
|
||||
**Recommendation:** Change `OperatorViewModel.AddressNumber` to `long`.
|
||||
|
||||
---
|
||||
|
||||
## Recommendations Summary
|
||||
|
||||
### Important
|
||||
1. ~~Fix `IExcelExportService` interface to use strongly-typed parameter~~ ✅ FIXED
|
||||
2. Consolidate duplicate ViewModels
|
||||
3. Fix `AddressNumber` type mismatch
|
||||
4. ~~Add logging to `Search.Criteria` deserialization~~ ✅ FIXED - Added `TryGetCriteria` method with logging support
|
||||
|
||||
### Suggestions
|
||||
1. Document JDE date pattern rationale
|
||||
2. Establish guideline for records vs classes for DTOs
|
||||
3. Fix null guard in `SearchViewModel` constructor
|
||||
Reference in New Issue
Block a user