Software Architecture Patterns

All new development undertaken should follow the principles of Clean Architecture.
In short, this means that the business logic of the application (use cases and entities) should have `NO EXTERNAL DEPENDENCIES. Whether that be a local file store, a database or a 3rd party library.
The main reason for this is to allow the pure business logic to be written and tested without getting caught up in the underlying infrastructure which, for the most part, is completely irrelevant.
Following these practices, also conform well with Domain-Driven Design in that the business logic can be written in a way that makes discussion between the client and the development much more straightforward.
Without diving into too much detail regarding the code itself, an application following clean architecture principles should be split into two distinct parts.
Core (WFD.SampleApp.Core)
The core library contains all of the business entities and logic. Any external dependencies are modeled with interfaces and there are no implementations.
The vast majority of the unit test code should be related to the core library.
Infrastructure (WFD.SampleApp.Infrastructure)
The infrastructure library contains the actual implementations of the interfaces. An implementation of an IDatabaseRepository to use MS SQL and Entity Framework would live in this library.
The infrastructure library would be expected to contain very little business logic and a lot of infrastructure-based code (file management, persistence, etc.)
It's unlikely any unit tests would ever run on the infrastructure libraries, however, it's highly likely any integration tests will
Implementation (WFD.SampleApp.WebApi)
Implementation code is what we would consider the actual application. Whether that be a command -ine utility, a web API or a background worker service.
It's likely, that the infrastructure and implementation code will be condensed into the same project as in most cases the infrastructure implementation will be related directly to the way in which the code is used.
Debugging
The abstraction caused by writing software in this way can make debugging tricky.
However, following the rule that an external interface will always be implemented in the infrastructure folder/project makes tracing the code straightforward.
For example, the pseudo-code would have two classes in the infrastructure project. Named InvoiceRepositorySqlImpl **and **PhysicalFileStoreS3Impl
var invoices = IInvoiceRepository.GetAll();
foreach (var invoice in invoices) { IPhysicalFileStore.StoreInvoiceData(invoice); }