From 833813ad13118ab8bef6ecc2c03d2ef2d652702c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ren=C3=A9=20White=20Enciso?= Date: Tue, 24 Feb 2026 05:26:54 -0600 Subject: [PATCH] refactor(furniture-service): delegate to domain --- .../service-orchestration-boundary.md | 13 +++++ docs/migration/domain-delegation-plan.md | 10 ++++ .../orchestration-regression-checks.md | 10 ++++ .../FurnitureAvailabilityContractAdapter.cs | 56 ------------------- .../IFurnitureAvailabilityContractAdapter.cs | 39 ------------- ...rviceRuntimeServiceCollectionExtensions.cs | 3 +- .../Furniture.Service.Application.csproj | 1 + .../GetFurnitureAvailabilityUseCase.cs | 21 +++++-- .../GetFurnitureAvailabilityUseCaseTests.cs | 19 ++++--- 9 files changed, 61 insertions(+), 111 deletions(-) create mode 100644 docs/architecture/service-orchestration-boundary.md create mode 100644 docs/migration/domain-delegation-plan.md create mode 100644 docs/migration/orchestration-regression-checks.md delete mode 100644 src/Furniture.Service.Application/Adapters/FurnitureAvailabilityContractAdapter.cs delete mode 100644 src/Furniture.Service.Application/Adapters/IFurnitureAvailabilityContractAdapter.cs diff --git a/docs/architecture/service-orchestration-boundary.md b/docs/architecture/service-orchestration-boundary.md new file mode 100644 index 0000000..312edeb --- /dev/null +++ b/docs/architecture/service-orchestration-boundary.md @@ -0,0 +1,13 @@ +# Furniture Service Orchestration Boundary + +## Purpose +Constrain furniture-service to orchestration responsibilities after domain extraction. + +## Service Responsibilities +- Coordinate use-case flow +- Call domain abstractions for decisions +- Adapt transport contracts + +## Prohibited Responsibilities +- Owning business decision rules +- Owning persistence decision concerns diff --git a/docs/migration/domain-delegation-plan.md b/docs/migration/domain-delegation-plan.md new file mode 100644 index 0000000..087b23d --- /dev/null +++ b/docs/migration/domain-delegation-plan.md @@ -0,0 +1,10 @@ +# Domain Delegation Plan + +## Delegation Model +- Use cases invoke furniture-domain abstractions for decision logic. +- Service adapters retain technical mapping responsibilities. + +## Transition Steps +1. Replace in-service decision branches with domain calls. +2. Keep contract shapes stable at service boundary. +3. Validate orchestration-only responsibilities. diff --git a/docs/migration/orchestration-regression-checks.md b/docs/migration/orchestration-regression-checks.md new file mode 100644 index 0000000..902f546 --- /dev/null +++ b/docs/migration/orchestration-regression-checks.md @@ -0,0 +1,10 @@ +# Orchestration Regression Checks + +## Checks +- Service no longer contains domain decision branches. +- Service still orchestrates required dependencies. +- Transport contract outputs remain stable. + +## Evidence +- Updated architecture docs +- Migration mapping confirmation diff --git a/src/Furniture.Service.Application/Adapters/FurnitureAvailabilityContractAdapter.cs b/src/Furniture.Service.Application/Adapters/FurnitureAvailabilityContractAdapter.cs deleted file mode 100644 index d53bce9..0000000 --- a/src/Furniture.Service.Application/Adapters/FurnitureAvailabilityContractAdapter.cs +++ /dev/null @@ -1,56 +0,0 @@ -using BuildingBlock.Catalog.Contracts.Conventions; -using BuildingBlock.Catalog.Contracts.Products; -using BuildingBlock.Catalog.Contracts.Responses; -using BuildingBlock.Inventory.Contracts.Conventions; -using BuildingBlock.Inventory.Contracts.Requests; -using BuildingBlock.Inventory.Contracts.Responses; -using Furniture.Service.Contracts.UseCases; - -namespace Furniture.Service.Application.Adapters; - -/// -/// Default adapter implementation for furniture service contract composition. -/// -public sealed class FurnitureAvailabilityContractAdapter : IFurnitureAvailabilityContractAdapter -{ - private const string ContractVersion = "1.0.0"; - - /// - public InventoryItemLookupRequest ToInventoryRequest(GetFurnitureAvailabilityRequest request) - { - return new InventoryItemLookupRequest( - new InventoryContractEnvelope(ContractVersion, ResolveCorrelationId(request.CorrelationId)), - request.FurnitureId); - } - - /// - public ProductContract ToCatalogRequest(GetFurnitureAvailabilityRequest request) - { - return new ProductContract( - new CatalogContractEnvelope(ContractVersion, ResolveCorrelationId(request.CorrelationId)), - request.FurnitureId, - string.Empty); - } - - /// - public GetFurnitureAvailabilityResponse ToServiceResponse( - GetFurnitureAvailabilityRequest request, - ProductContractResponse catalogResponse, - InventoryItemLookupResponse inventoryResponse) - { - return new GetFurnitureAvailabilityResponse( - request.FurnitureId, - catalogResponse.DisplayName, - inventoryResponse.QuantityAvailable); - } - - private static string ResolveCorrelationId(string correlationId) - { - if (!string.IsNullOrWhiteSpace(correlationId)) - { - return correlationId; - } - - return $"corr-{Guid.NewGuid():N}"; - } -} diff --git a/src/Furniture.Service.Application/Adapters/IFurnitureAvailabilityContractAdapter.cs b/src/Furniture.Service.Application/Adapters/IFurnitureAvailabilityContractAdapter.cs deleted file mode 100644 index 2f501e5..0000000 --- a/src/Furniture.Service.Application/Adapters/IFurnitureAvailabilityContractAdapter.cs +++ /dev/null @@ -1,39 +0,0 @@ -using BuildingBlock.Catalog.Contracts.Products; -using BuildingBlock.Catalog.Contracts.Responses; -using BuildingBlock.Inventory.Contracts.Requests; -using BuildingBlock.Inventory.Contracts.Responses; -using Furniture.Service.Contracts.UseCases; - -namespace Furniture.Service.Application.Adapters; - -/// -/// Defines adapter boundary for furniture service contract composition. -/// -public interface IFurnitureAvailabilityContractAdapter -{ - /// - /// Maps service request into an inventory capability request. - /// - /// Furniture availability request. - /// Inventory lookup request. - InventoryItemLookupRequest ToInventoryRequest(GetFurnitureAvailabilityRequest request); - - /// - /// Maps service request into a catalog capability request. - /// - /// Furniture availability request. - /// Catalog product request. - ProductContract ToCatalogRequest(GetFurnitureAvailabilityRequest request); - - /// - /// Maps capability responses back into the service response contract. - /// - /// Furniture availability request. - /// Catalog product response. - /// Inventory lookup response. - /// Furniture availability response. - GetFurnitureAvailabilityResponse ToServiceResponse( - GetFurnitureAvailabilityRequest request, - ProductContractResponse catalogResponse, - InventoryItemLookupResponse inventoryResponse); -} diff --git a/src/Furniture.Service.Application/DependencyInjection/FurnitureServiceRuntimeServiceCollectionExtensions.cs b/src/Furniture.Service.Application/DependencyInjection/FurnitureServiceRuntimeServiceCollectionExtensions.cs index 3dd7863..b22c04b 100644 --- a/src/Furniture.Service.Application/DependencyInjection/FurnitureServiceRuntimeServiceCollectionExtensions.cs +++ b/src/Furniture.Service.Application/DependencyInjection/FurnitureServiceRuntimeServiceCollectionExtensions.cs @@ -1,5 +1,6 @@ using Core.Blueprint.Common.DependencyInjection; using Furniture.DAL.DependencyInjection; +using Furniture.Domain.Decisions; using Furniture.Service.Application.Adapters; using Furniture.Service.Application.Ports; using Furniture.Service.Application.UseCases; @@ -22,8 +23,8 @@ public static class FurnitureServiceRuntimeServiceCollectionExtensions { services.AddBlueprintRuntimeCore(); services.AddFurnitureDalRuntime(); + services.TryAddSingleton(); - services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); diff --git a/src/Furniture.Service.Application/Furniture.Service.Application.csproj b/src/Furniture.Service.Application/Furniture.Service.Application.csproj index 236c500..9d14cf9 100644 --- a/src/Furniture.Service.Application/Furniture.Service.Application.csproj +++ b/src/Furniture.Service.Application/Furniture.Service.Application.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Furniture.Service.Application/UseCases/GetFurnitureAvailabilityUseCase.cs b/src/Furniture.Service.Application/UseCases/GetFurnitureAvailabilityUseCase.cs index 52acd3d..a2e4dc2 100644 --- a/src/Furniture.Service.Application/UseCases/GetFurnitureAvailabilityUseCase.cs +++ b/src/Furniture.Service.Application/UseCases/GetFurnitureAvailabilityUseCase.cs @@ -1,6 +1,7 @@ -using Furniture.Service.Application.Adapters; using Furniture.Service.Application.Ports; using Furniture.Service.Contracts.UseCases; +using Furniture.Domain.Contracts; +using Furniture.Domain.Decisions; namespace Furniture.Service.Application.UseCases; @@ -8,7 +9,7 @@ namespace Furniture.Service.Application.UseCases; /// Default orchestration implementation for furniture availability lookup. /// public sealed class GetFurnitureAvailabilityUseCase( - IFurnitureAvailabilityContractAdapter contractAdapter, + IFurnitureAvailabilityDecisionService decisionService, ICatalogProductReadPort catalogReadPort, IFurnitureAvailabilityReadPort inventoryReadPort) : IGetFurnitureAvailabilityUseCase @@ -16,17 +17,25 @@ public sealed class GetFurnitureAvailabilityUseCase( /// public async Task HandleAsync(GetFurnitureAvailabilityRequest request) { - var catalogRequest = contractAdapter.ToCatalogRequest(request); - var inventoryRequest = contractAdapter.ToInventoryRequest(request); + var domainRequest = new FurnitureAvailabilityDecisionRequest( + request.FurnitureId, + request.CorrelationId); + var catalogRequest = decisionService.BuildCatalogRequest(domainRequest); + var inventoryRequest = decisionService.BuildInventoryRequest(domainRequest); var catalogTask = catalogReadPort.ReadProductAsync(catalogRequest); var inventoryTask = inventoryReadPort.ReadAvailabilityAsync(inventoryRequest); await Task.WhenAll(catalogTask, inventoryTask); - return contractAdapter.ToServiceResponse( - request, + var domainResponse = decisionService.ComposeResponse( + domainRequest, await catalogTask, await inventoryTask); + + return new GetFurnitureAvailabilityResponse( + domainResponse.FurnitureId, + domainResponse.DisplayName, + domainResponse.QuantityAvailable); } } diff --git a/tests/Furniture.Service.Application.UnitTests/GetFurnitureAvailabilityUseCaseTests.cs b/tests/Furniture.Service.Application.UnitTests/GetFurnitureAvailabilityUseCaseTests.cs index 3317df7..a36224c 100644 --- a/tests/Furniture.Service.Application.UnitTests/GetFurnitureAvailabilityUseCaseTests.cs +++ b/tests/Furniture.Service.Application.UnitTests/GetFurnitureAvailabilityUseCaseTests.cs @@ -4,10 +4,11 @@ using BuildingBlock.Catalog.Contracts.Responses; using BuildingBlock.Inventory.Contracts.Conventions; using BuildingBlock.Inventory.Contracts.Requests; using BuildingBlock.Inventory.Contracts.Responses; -using Furniture.Service.Application.Adapters; using Furniture.Service.Application.Ports; using Furniture.Service.Application.UseCases; using Furniture.Service.Contracts.UseCases; +using Furniture.Domain.Contracts; +using Furniture.Domain.Decisions; namespace Furniture.Service.Application.UnitTests; @@ -16,10 +17,10 @@ public class GetFurnitureAvailabilityUseCaseTests [Fact] public async Task HandleAsync_WhenCalled_DelegatesToReadPort() { - var adapter = new FakeFurnitureAvailabilityContractAdapter(); + var decisionService = new FakeFurnitureAvailabilityDecisionService(); var catalogPort = new FakeCatalogProductReadPort(); var inventoryPort = new FakeFurnitureAvailabilityReadPort(); - var useCase = new GetFurnitureAvailabilityUseCase(adapter, catalogPort, inventoryPort); + var useCase = new GetFurnitureAvailabilityUseCase(decisionService, catalogPort, inventoryPort); var response = await useCase.HandleAsync(new GetFurnitureAvailabilityRequest("FUR-001", "corr-123")); @@ -28,9 +29,9 @@ public class GetFurnitureAvailabilityUseCaseTests Assert.Equal(10, response.QuantityAvailable); } - private sealed class FakeFurnitureAvailabilityContractAdapter : IFurnitureAvailabilityContractAdapter + private sealed class FakeFurnitureAvailabilityDecisionService : IFurnitureAvailabilityDecisionService { - public ProductContract ToCatalogRequest(GetFurnitureAvailabilityRequest request) + public ProductContract BuildCatalogRequest(FurnitureAvailabilityDecisionRequest request) { return new ProductContract( new CatalogContractEnvelope("1.0.0", request.CorrelationId), @@ -38,19 +39,19 @@ public class GetFurnitureAvailabilityUseCaseTests string.Empty); } - public InventoryItemLookupRequest ToInventoryRequest(GetFurnitureAvailabilityRequest request) + public InventoryItemLookupRequest BuildInventoryRequest(FurnitureAvailabilityDecisionRequest request) { return new InventoryItemLookupRequest( new InventoryContractEnvelope("1.0.0", request.CorrelationId), request.FurnitureId); } - public GetFurnitureAvailabilityResponse ToServiceResponse( - GetFurnitureAvailabilityRequest request, + public FurnitureAvailabilityDecisionResponse ComposeResponse( + FurnitureAvailabilityDecisionRequest request, ProductContractResponse catalogResponse, InventoryItemLookupResponse inventoryResponse) { - return new GetFurnitureAvailabilityResponse( + return new FurnitureAvailabilityDecisionResponse( request.FurnitureId, catalogResponse.DisplayName, inventoryResponse.QuantityAvailable);