整洁架构下:不同类型实现接口的最佳实践与适配方案问询
解决方案
1. 遵循依赖倒置原则,调整接口与模型的归属
整洁架构的核心是抽象不依赖细节,细节依赖抽象,正确的做法是把接口放到领域层(抽象层),并使用领域层的通用模型作为参数,让API层和基础设施层都依赖这个抽象:
- 领域层定义接口和通用模型:
// 领域层接口(抽象) public interface ICurrencyStorage { Task<bool> StoreConvertedCurrenciesAsync(List<CurrencyConversionRecord> records); } // 领域层通用模型 public class CurrencyConversionRecord { public string QuoteId { get; set; } = default!; public string PaymentOptionId { get; set; } = default!; }
- API层接收
ApiLayerViewModel后,转换为领域模型再调用接口:
public async Task<IActionResult> SubmitConversion(List<ApiLayerViewModel> viewModels) { var domainRecords = viewModels.Select(vm => new CurrencyConversionRecord { QuoteId = vm.QuoteId, PaymentOptionId = vm.PaymentOptionId }).ToList(); await _currencyStorage.StoreConvertedCurrenciesAsync(domainRecords); return Ok(); }
- 基础设施层实现接口时,将领域模型转换为自身的
InfraLayerModel:
public class DatabaseCurrencyStorage : ICurrencyStorage { public async Task<bool> StoreConvertedCurrenciesAsync(List<CurrencyConversionRecord> records) { var infraModels = records.Select(r => new InfraLayerModel { QuoteId = r.QuoteId, PaymentOptionId = r.PaymentOptionId }).ToList(); // 执行基础设施层的存储逻辑(比如写入数据库) return await WriteToDatabase(infraModels); } private async Task<bool> WriteToDatabase(List<InfraLayerModel> models) { // 具体存储实现 return true; } }
2. 若需保留API层接口,添加模型转换逻辑
如果接口必须定义在API层,可在基础设施层实现接口时,先完成API模型到基础设施模型的转换:
public class CurrencyStorage : IApiCurrencyStorage { public async Task<bool> StoreConvertesCurrenciesAsync(List<ApiLayerViewModel> xyz) { // 转换API层模型到基础设施层模型 var infraModels = xyz.Select(vm => new InfraLayerModel { QuoteId = vm.QuoteId, PaymentOptionId = vm.PaymentOptionId }).ToList(); // 执行存储操作 return await SaveToStorage(infraModels); } private async Task<bool> SaveToStorage(List<InfraLayerModel> models) { // 具体存储实现 return true; } }
这种方式虽能解决问题,但违背了整洁架构的依赖原则(上层不应直接绑定下层细节),仅作为临时兼容方案。
核心总结
各层独立模型的本质是隔离关注点,避免层与层之间的强耦合。通过领域层的抽象接口和通用模型做中转,让API层负责"外部模型转领域模型",基础设施层负责"领域模型转内部存储模型",才能真正符合整洁架构的设计思想。
内容的提问来源于stack exchange,提问作者csharper
相关产品推荐
相关产品推荐

