<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Architecture on Benny Simmonds</title>
    <link>https://www.bencode.io/categories/architecture/</link>
    <description>Recent content in Architecture on Benny Simmonds</description>
    <generator>Hugo -- 0.149.1</generator>
    <language>en-us</language>
    <lastBuildDate>Sun, 26 Oct 2025 13:13:01 +1000</lastBuildDate>
    <atom:link href="https://www.bencode.io/categories/architecture/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>.NET Clean Architecture</title>
      <link>https://www.bencode.io/posts/cleanarch/</link>
      <pubDate>Thu, 29 May 2025 20:14:01 +1000</pubDate>
      <guid>https://www.bencode.io/posts/cleanarch/</guid>
      <description>&lt;p&gt;Domain centric architectures, like clean architecture, have inner architectural cores that model the domain. Dependency inversion is king, with inner layers defining abstractions and interfaces and outer layers implementing them. Clean architecture is a good fit when aligning to Domain Driven Design (DDD), dealing with complex business logic, high testability is desirable and/or working in a large team, as the architecture can enforce design policies.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#guiding-principles&#34;&gt;Guiding Principles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#clean-architecture-layers&#34;&gt;Clean Architecture Layers&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#domain-layer&#34;&gt;Domain layer&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#entities&#34;&gt;Entities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#value-objects&#34;&gt;Value Objects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#domain-events&#34;&gt;Domain Events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#domain-services&#34;&gt;Domain Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#interfaces&#34;&gt;Interfaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#results-and-exceptions&#34;&gt;Results and Exceptions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#application-layer-the-use-case-orchestrator&#34;&gt;Application layer: The Use Case Orchestrator&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#application-layer-key-responsibilities&#34;&gt;Application Layer Key Responsibilities&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#use-case-orchestration&#34;&gt;Use Case Orchestration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#higher-order-business-logic&#34;&gt;Higher Order Business Logic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#cross-cutting-concerns&#34;&gt;Cross Cutting Concerns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#exception-translation--handling&#34;&gt;Exception Translation &amp;amp; Handling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#dependency-injection-hub&#34;&gt;Dependency Injection Hub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#what-the-application-layer-does-not-do&#34;&gt;What the Application Layer Does NOT Do&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#example-application-service&#34;&gt;Example Application Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#dependency-injection-and-mediatr-bootstrapping&#34;&gt;Dependency Injection and MediatR Bootstrapping&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#cqrs-abstractions&#34;&gt;CQRS Abstractions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#handling-domain-events&#34;&gt;Handling Domain Events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#cross-cutting-concerns-with-mediatr-pipelines&#34;&gt;Cross Cutting Concerns with MediatR Pipelines&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#logging-pipeline&#34;&gt;Logging Pipeline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#validation-pipeline-with-fluentvalidation&#34;&gt;Validation Pipeline with FluentValidation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#infrastructure-layer&#34;&gt;Infrastructure layer&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#infrastructure-layer-key-responsibilities&#34;&gt;Infrastructure Layer Key Responsibilities&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#data-persistence-and-access&#34;&gt;Data Persistence and Access&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#external-service-integration&#34;&gt;External Service Integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#cross-cutting-concerns-implementation&#34;&gt;Cross Cutting Concerns Implementation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#event-handling-infrastructure&#34;&gt;Event Handling Infrastructure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#what-the-infrastructure-layer-does-not-do&#34;&gt;What the Infrastructure Layer Does NOT Do&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#example-concrete-provider-for-idatetimeprovider&#34;&gt;Example Concrete Provider for IDateTimeProvider&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#ef-core-setup&#34;&gt;EF Core Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#integrating-domain-entities-with-ef-core&#34;&gt;Integrating Domain Entities with EF Core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#publishing-domain-events-in-the-unit-of-work&#34;&gt;Publishing Domain Events in the Unit of Work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#handling-race-conditions-with-optimistic-concurrency&#34;&gt;Handling Race Conditions with Optimistic Concurrency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#distributed-cache-service&#34;&gt;Distributed Cache Service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#presentation-layer&#34;&gt;Presentation layer&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#presentation-layer-key-responsibilities&#34;&gt;Presentation Layer Key Responsibilities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#what-the-presentation-layer-does-not-do&#34;&gt;What the Presentation Layer Does NOT Do&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#api-controllers-and-endpoints&#34;&gt;API Controllers and Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#seed-data-and-ef-migrations&#34;&gt;Seed Data and EF Migrations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#authentication-authn-with-keycloak&#34;&gt;Authentication (authn) with Keycloak&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#authorization-authz&#34;&gt;Authorization (authz)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#role-based-authorization&#34;&gt;Role-based Authorization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#permission-based-policy-authorization&#34;&gt;Permission-based (Policy) Authorization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#resource-based-authorization&#34;&gt;Resource-based Authorization&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#structured-logging&#34;&gt;Structured Logging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#health-checks&#34;&gt;Health Checks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#net-implementation-tips&#34;&gt;.NET Implementation Tips&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#general-net-tips&#34;&gt;General .NET Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#domain-layer-net-tips&#34;&gt;Domain Layer .NET Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#application-layer-net-tips&#34;&gt;Application Layer .NET Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#infrastructure-layer-net-tips&#34;&gt;Infrastructure Layer .NET Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#presentation-layer-net-tips&#34;&gt;Presentation Layer .NET Tips&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#structured-logging-1&#34;&gt;Structured Logging&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#serilog&#34;&gt;Serilog&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#serilog-and-seq-setup-guide&#34;&gt;Serilog and Seq Setup Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#outbox-pattern&#34;&gt;Outbox Pattern&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#the-problem&#34;&gt;The Problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-solution&#34;&gt;The Solution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#key-benefits&#34;&gt;Key Benefits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#outbox-net-implementation&#34;&gt;Outbox .NET Implementation&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#outbox-message-definition&#34;&gt;Outbox Message Definition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#transactionally-publish-domain-events-as-outbox-messages&#34;&gt;Transactionally Publish Domain Events as Outbox Messages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#background-worker-job-with-quartznet&#34;&gt;Background Worker Job with Quartz.NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#hookup-dependency-injection&#34;&gt;Hookup Dependency Injection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#aspnet-core-minimal-apis&#34;&gt;ASP.NET Core Minimal APIs&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#controller-to-minimal-api-conversion-cookbook&#34;&gt;Controller to Minimal API Conversion Cookbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#centralising-route-opinions-with-route-groups&#34;&gt;Centralising Route Opinions with Route Groups&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#testing&#34;&gt;Testing&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#domain-layer-unit-testing&#34;&gt;Domain Layer Unit Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#application-layer-unit-testing&#34;&gt;Application Layer Unit Testing&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#mocking-with-nsubstitute&#34;&gt;Mocking with NSubstitute&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#application-layer-integration-testing-with-testcontainers&#34;&gt;Application Layer Integration Testing with TestContainers&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#troubleshooting&#34;&gt;Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#accessing-internal-symbols&#34;&gt;Accessing Internal Symbols&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#bonus-contemporary-net-gems&#34;&gt;Bonus: Contemporary .NET gems&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#primary-constructors&#34;&gt;Primary Constructors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#switch-expressions&#34;&gt;Switch Expressions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#records&#34;&gt;Records&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#async-tips&#34;&gt;Async Tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#mediatr&#34;&gt;MediatR&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#irequest-and-irequesthandler---requestresponse&#34;&gt;IRequest and IRequestHandler - Request/Response&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#publishing&#34;&gt;Publishing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#inotification-and-inotificationhandler---pubsub&#34;&gt;INotification and INotificationHandler - Pub/Sub&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#publishing-1&#34;&gt;Publishing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#mediatrcontracts-package&#34;&gt;MediatR.Contracts Package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#visual-studio-and-roslyn-code-quality-level-ups&#34;&gt;Visual Studio and Roslyn Code Quality Level Ups&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#dotnet-cli-tips&#34;&gt;dotnet CLI Tips&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;guiding-principles&#34;&gt;Guiding Principles&lt;/h2&gt;
&lt;p&gt;High level qualities that a good software architecture should (and enforce) strive for; maintainability, testability and loose coupling.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
