{"id":25972282,"url":"https://github.com/peteraritchie/ddd-webapi-vs-template","last_synced_at":"2025-08-27T03:06:25.977Z","repository":{"id":139142731,"uuid":"605412891","full_name":"peteraritchie/ddd-webapi-vs-template","owner":"peteraritchie","description":null,"archived":false,"fork":false,"pushed_at":"2023-03-13T19:12:57.000Z","size":300,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-20T02:44:50.797Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/peteraritchie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-02-23T05:06:48.000Z","updated_at":"2023-02-23T05:08:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"8d18140f-2615-41ac-9a2c-41e693a9a9bf","html_url":"https://github.com/peteraritchie/ddd-webapi-vs-template","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/peteraritchie/ddd-webapi-vs-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2Fddd-webapi-vs-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2Fddd-webapi-vs-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2Fddd-webapi-vs-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2Fddd-webapi-vs-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/peteraritchie","download_url":"https://codeload.github.com/peteraritchie/ddd-webapi-vs-template/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2Fddd-webapi-vs-template/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272283307,"owners_count":24906653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-27T02:00:09.397Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-05T00:32:57.043Z","updated_at":"2025-08-27T03:06:25.969Z","avatar_url":"https://github.com/peteraritchie.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Readme\n\n## Contents\n\n- [Basic Request Flow Through Domain-Driven Architectural Layers](#basic-flow)\n- [More-detailed Request Flow Through Domain-Driven Architectural Layers](#more-detailed-flow)\n- [Solution Structure](#structure)\n\u003c!--\nTenets:\n\n- Messages are DTOs [Dahan]\n- MVC models are messages [Ritchie]\n- DTOs require adaptation to to domain objects (aggregates, entities, value objects). [Ritchie]\n- \"Application service are responsible for task coordination of use case flows, one service method per flow\". [Vernon]\n- [An application service is a command handler for a specific aggregate. One aggregate has one application service whose purpose is to orchestrate how commands will be fulfilled.](https://github.com/Elders/Cronus/blob/master/docs/cronus-framework/domain-modeling/handlers/application-services.md#:~:text=an%20application%20service%20is%20a%20command%20handler%20for%20a%20specific%20aggregate.%20one%20aggregate%20has%20one%20application%20service%20whose%20purpose%20is%20to%20orchestrate%20how%20commands%20will%20be%20fulfilled)\n- \"Command Handler (semantically an Application Service)\" [Vernon]\n- Application Services are command handlers that handle a use case. --\u003e \u003c!--\"Application Services are command handlers ... [that handle a use case]\"--\u003e\n\u003c!--\n  - A application service has a one-to-one relationship with an aggregate as an application-level aggregate facade. [Ritchie, paraphrasing Evans?]\n- \"Integration across the boundaries necessarily will involve some translation, which you can analyze explicitly.\" [Evans]\n- \"Integration of functionality and data [across bounded contexts] must go through a translation. \n  - An Anti-corruption layer is composed of an adapter and a translator.\n\n- \"[Two bounded contexts ] are not in the same CONTEXT and should stop trying to share code until some changes are made.\" [Evans]\n- \"Code reuse between BOUNDED CONTEXTS is a hazard to be avoided.\" [Evans]\n- [A Context Map Describes] the points of contact between the models, outlining explicit translation for any communication and highlighting any sharing. \n- Upstream and downstream subsystems separate naturally into two BOUNDED CONTEXTS. \n\n**\nA message, or anything arriving over-the-wire (transport) is modeled as a DTO to the receiver.  The message data has transport-level constraints that are often at odds with the application/domain constraints and must be validated and translated before being \"executed.\"\n**\n\nSmells:\n\n - There isn't a one-to-one relationship between application services and aggregates. [Ritchie]\n\nPractices:\n\n- Command always through web API. [Ritchie]\n- Web API Validates, Domain Validates, Adapters Validate\n- Adapters always involve translation or a translator. [Ritchie] or [Martin]\n--\u003e\n\n## Structure\n\n- `Domain`\n  - _References only generic base-class libraries_\n  - Contains entities and value objects in the root, with sub-folders for concepts like Commands, Events, and Domain Services.\n  - `Services`\n    - Domain Services: stateless containers of domain-level interaction between domain objects.\n  - `Commands`\n    - A abstraction of a request for a change in state.  Usually involves one or more events being published.\n  - `Events`\n    - A abstraction of a record of a past state change.\n  - `Builders`\n    - Used to build instances of domain objects (Aggregates, Entities, Commands, Events, etc.), enforcing and validating (via validators) invariants.  Like factories, but present a domain-specific fluent interface that .\n    - `Validators`\n      - Encapsulates some of the critical business logic relating to invariants relating to instantiating domain objects. \n  - `Exceptions`\n    - Domain-specific exceptions (e.g. `EntityNotFoundException`, `EntityAlreadyExistsException`, etc.)\n  - `Abstractions`\n    - interfaces, repositories, etc.\n- `Application`\n  - _References Domain_\n  - `Services`\n    - Application services; responsible for task coordination of use case flows, one service method per flow. \\[Vernon, _Implementing Domain-Driven Design_ p. 521\\]\n  - `Commands`\n    - Application commands that cross aggregate boundaries; referencing domain objects\n  - `Events`\n    - Application events that cross aggregate boundaries; referencing domain objects\n  - `Translators`\n    - Used within adapters to translate the data from one interface to another, leveraging builders and validators from the Domain\n    - `Builders`\n      - Used to build instances of application objects, making use of validators to enforce application-level invariants.\n    - `Validators`\n      - Used when translating between domain events/commands and application events/commands\n  - `Exceptions`\n    - Domain exceptions that are not specific to an particular aggregate.\n  - `Abstractions`\n- `Infrastructure`\n  - _References Domain and Application, and frameworks_\n  - The infrastructure-level implementation details of the Application and Domain Layers.\n  - `Services`\n    - Infrastructure Services\n  - `Abstractions`\n    - Interfaces and base classes relating to infrastructure\n  - `Persistence`\n    - Infrastructure Services and generic base classes implementing data persistence.\n  - `Dtos`\n    - Objects representing the shape of data required to communicate to external services.\n    - `Translators`\n      - Translates DTOs to domain-objects (and vice-versa), making use of Builders and Validators to enforce invariants relating to instantiation of domain objects.\n    - `Builders`\n      - Encapsulates the rules for instantiating domain objects, making use of Validators\n    - `Validators`\n      - Validation code that enforces invariants relating to infrastructure DTOs. _May mirror Domain-level invariants_.\n  - `Exceptions`\n    - Infrastructure-specific exceptions.\n  - Implementations?\n    - Persistence? (repository implementations, specifications, etc.)\n- `WebAPI`\n  - _References both Domain and Infrastructure_(?).\n  - `Dtos`?\n    - `Validators`\n      - Validation code that enforces invariants relating to WebAPI DTOs.  _May mirror Domain-Level invariants_.\n    - `ApplicationCommandDtos`?\n      - `Translators`\n      - `Validators`\n    - `ApplicationEventDtos`?\n      - `Translators`\n      - `Validators`\n  - `Controllers`\n    - Obvious\n  - `Infrastructure`\n    - TODO:\n- `Endpoint`\n  - References both Domain and Infrastructure?\n  - **todo**:\n- `Tests`\n\n## Details\n\n### The difference between Application Services and Infrastructure Services.\n\nThe Application Layer contain use cases (that are collaborations of application services and domain objects).  Concepts in the Application Layer are _Domain focused_.  For example, in a domain there may be an abstract concept like _notification_: something in the domain may need to notify something else in the domain.  Kow that notification is realized needs to be implemented _in the real world_.  So, within the scope of the application there may be a Notification Service.  The implementation (i.e. the infrastructure behind the notification service) may be to send an email, so it ends up being a wrapper to an Infrastructure Service (Email Sender).\n\n## Flow Relationships\n\n### Basic Flow\n\n![generic](docs/generic-ddd-sequence.svg)\n\n### More Detailed Flow\n\n![specific](docs/specific-ddd-sequence.svg)\n\n## WebAPI\n\nDTO are anemic data containers. Validation, serialization, etc. requirements use asp.net specific attributes. \n\n### Infrastructure\n\n### Application\nIs this just application services?  Be clear about the distinction of application services.\n\n## Core (Domain)\n\nCore shouldn't know about front-ends, so translation to/from domain happens in front-end.\n\nDomain classes have all read-only properties, mutation is done through methods (ala Command Query Separation.)\n\n## Infrastructure\n\n## Tests\n\nTest names detail the expectation, no need for assert text.\n\nTests verify controllers via test server.\n\n[Vernon]: https://todo\n[Dahan]: https://todo\n\u003c!--\nJohn: places for EDA to fit... \n--\u003e\n\u003c!--\nEvans' services:\n- routing service\n- NetworkTraversalService\n- NetListImportService\n- QueryService\n\nVernon's Services:\n- DiscussionService (domain)\n- SchedulingService (domain)\n- TenantIdentityService (application)\n- tenantProvisioningService\n- CustomerApplicationService (application)\n- pricingService (domain)\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeteraritchie%2Fddd-webapi-vs-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeteraritchie%2Fddd-webapi-vs-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeteraritchie%2Fddd-webapi-vs-template/lists"}