Um ponto de partida para a arquitetura limpa com o ASP.NET CORE. A arquitetura limpa é apenas a mais recente de uma série de nomes para a mesma arquitetura invertida de dependência e dependência. Você também o encontrará chamado Hexagonal, Ports-And-Adapters ou Cenion Architecture.
Saiba mais sobre a arquitetura limpa e este modelo no curso de arquitetura limpa da Nimblepros. Use o código Ardalis para economizar 20%.
Esta arquitetura é usada no curso de Fundamentos DDD por Steve Smith e Julie Lerman.
? Entre em contato com a empresa de Steve, Nimblepros, para obter arquitetura limpa ou treinamento de treinamento e/ou implementação de DDD para sua equipe.
Aprenda sobre como implementar a arquitetura limpa dos treinadores de Nimblepros, Sarah "Sadukie" Dutkiewicz e Steve "Ardalis" Smith.
Se você gosta ou está usando este projeto para aprender ou iniciar sua solução, dê uma estrela. Obrigado!
Ou se você estiver se sentindo realmente generoso, agora apoiamos os patrocínios do GitHub - veja o botão acima.
Por favor, anuncie que o Foss Fund da Amazon Aws optou por conceder um patrocínio de 12 meses a este projeto. Obrigado e obrigado a todos os meus outros patrocinadores do passado e dos atuais!
Por padrão, o site usa HTTPS e espera que você tenha um certificado de desenvolvedor autoassinado para uso de localhost. Se você receber um erro com o Chrome, consulte esta resposta para obter instruções de mitigação.
O ramo principal está agora usando .NET 9 . Isso corresponde ao pacote NUGET versão 10.x. Versões anteriores estão disponíveis - consulte nossos lançamentos.
Para usar este modelo, existem algumas opções:
dotnet new (recomendado)Primeiro, instale o modelo da NuGet (https://www.nuget.org/packages/ardalis.cleanarchitecture.template/):
dotnet new install Ardalis.CleanArchitecture.Template Você pode ver as opções disponíveis executando o comando com o -? opção:
dotnet new clean - arch - ?
ASP.NET Clean Architecture Solution (C # )
Author: Steve Smith @ardalis , Erik Dahl
Usage:
dotnet new clean - arch [ options ] [ template options ]
Options:
- n , -- name < name > The name for the output being created. If no name is specified , the name of the output
directory is used.
- o , -- output < output > Location to place the generated output.
-- dry - run Displays a summary of what would happen if the given command line were run if it would result
in a template creation.
-- force Forces content to be generated even if it would change existing files.
-- no - update-check Disables checking for the template package updates when instantiating a template.
-- project < project > The project that should be used for context evaluation.
- lang , -- language < C # > Specifies the template language to instantiate.
-- type < project > Specifies the template type to instantiate.
Template options:
-as , -- aspire Include .NET Aspire.
Type: bool
Default : false Você deve ver o modelo na lista de modelos da dotnet new list depois que isso é instalado com sucesso. Procure "Solução de arquitetura limpa do ASP.NET" com o nome curto de "Clean-Arch".
Navegue até o diretório pai em que você gostaria que a pasta da solução fosse criada.
Execute este comando para criar a estrutura da solução em um nome da subpasta Your.ProjectName :
dotnet new clean-arch -o Your.ProjectName
O diretório Your.ProjectName e o arquivo de solução será criado e, dentro, que será todo o seu novo conteúdo da solução, adequadamente nomeado e pronto para executar/testar!
Exemplo: 
Obrigado @dahlsailrunner por sua ajuda para fazer isso funcionando!
Questões conhecidas :
A partir da versão 9, este modelo de solução inclui apenas suporte para pontos de extremidade da API usando a biblioteca FastEndPoints. Se você deseja usar minha biblioteca Apiendpoints, páginas de barbear e/ou controladores, você pode usar o último modelo que as incluía, versão 7.1. Como alternativa, eles são facilmente adicionados a este modelo após a instalação.
Para usar o Ardalis.APIDIENSPOints em vez de (ou além de) FastEnsPoints, basta adicionar a referência e usar as classes base da documentação.
dotnet add package Ardalis.ApiEndpointsVocê precisará adicionar suporte para controladores ao arquivo do programa.cs. Você precisa:
builder . Services . AddControllers ( ) ; // ControllersWithView if you need Views
// and
app . MapControllers ( ) ;Quando estes estiverem no lugar, você poderá criar uma pasta controladores e (opcionalmente) uma pasta de visualizações e tudo deve funcionar conforme o esperado. Pessoalmente, acho que as páginas de barbear são muito melhores que os controladores e visualizações, por isso, se você não investigar totalmente as páginas de barbear, poderá fazê -lo agora antes de escolher as visualizações.
Você precisará adicionar suporte para páginas de barbear ao arquivo program.cs. Você precisa:
builder . Services . AddRazorPages ( ) ;
// and
app . MapRazorPages ( ) ;Em seguida, basta adicionar uma pasta de páginas na raiz do projeto e partir daí.
Para começar com base neste repositório, você precisa obter uma cópia localmente. Você tem três opções: garfo, clone ou download. Na maioria das vezes, você provavelmente só quer baixar.
Você deve baixar o repositório , desbloquear o arquivo ZIP e extraí -lo para uma nova pasta se quiser apenas jogar com o projeto ou desejar usá -lo como ponto de partida para um aplicativo.
Você deve gastar este repositório apenas se planeja enviar uma solicitação de tração. Ou se você quiser manter uma cópia de um instantâneo do repositório em sua própria conta do Github.
Você deve clonar esse repositório se você for um dos colaboradores e cometer acesso a ele. Caso contrário, você provavelmente deseja uma das outras opções.
Você não precisa fazer isso para usar esse modelo, mas se você deseja que as migrações sejam configuradas corretamente no projeto de infraestrutura, precisará especificar o nome do projeto ao executar o comando migração.
No Visual Studio, abra o console do gerenciador de pacotes e execute Add-Migration InitialMigrationName -StartupProject Your.ProjectName.Web -Context AppDbContext -Project Your.ProjectName.Infrastructure .
Em um terminal com a CLI, o comando é semelhante. Execute isso no diretório do projeto da web:
dotnet ef migrations add MIGRATIONNAME - c AppDbContext - p .. / Your.ProjectName.Infrastructure / Your.ProjectName.Infrastructure.csproj - s Your.ProjectName.Web.csproj - o Data / Migrations Para usar o SQLServer, altere options.UseSqlite(connectionString)); para options.UseSqlServer(connectionString)); no arquivo Your.ProjectName.Infrastructure.StartupSetup . Lembre -se também de substituir a SqliteConnection pela DefaultConnection no arquivo Your.ProjectName.Web.Program , que aponta para o seu servidor de banco de dados.
Para atualizar o banco de dados, use este comando na pasta Web Project (substitua Clean.Architecture pelo nome do seu projeto):
dotnet ef database update - c AppDbContext - p .. / Clean .Architecture.Infrastructure / Clean .Architecture.Infrastructure.csproj - s Clean .Architecture.Web.csprojO objetivo deste repositório é fornecer uma estrutura básica de solução que possa ser usada para criar aplicativos sólidos, baseados em design orientado a domínios (DDD) ou simplesmente bem-formados, usando o núcleo .NET. Saiba mais sobre esses tópicos aqui:
Se você está acostumado a criar aplicativos como projeto único ou como um conjunto de projetos que seguem a interface do usuário tradicional -> Camada de negócios -> Arquitetura "N -Tier" de acesso a dados, recomendo que você confira esses dois cursos (idealmente antes dos fundamentos do DDD):
Steve Smith também mantém o aplicativo de referência da Microsoft, EShoponweb, e seu e -book livre associado. Confira aqui:
Observe que o objetivo deste projeto e do repositório não é fornecer uma amostra ou aplicação de referência. É apenas um modelo, mas com peças suficientes para mostrar onde as coisas pertencem à medida que você configura sua solução real. Em vez de inúteis "Class1.cs", existem algumas classes reais. Exclua -os assim que você entender por que eles estão lá e onde você deve colocar seus próprios arquivos semelhantes. Existe um aplicativo de amostra na pasta /sample , se você estiver procurando por isso.
Eu usei este kit inicial para ensinar o básico do CORE ASP.NET usando conceitos e padrões de design orientados a domínios há algum tempo (começando quando o núcleo do ASP.NET ainda estava em pré-lançamento). Normalmente, ensino um workshop prático de um ou dois dias antes de eventos como DevinterSection, ou workshops privados no local para empresas que desejam atualizar suas equipes com as mais recentes tecnologias e técnicas de desenvolvimento. Sinta -se à vontade para entrar em contato comigo se desejar informações sobre os próximos workshops.
O objetivo deste modelo de solução é fornecer um kit de partida bastante nua para novos projetos. Ele não inclui todas as estruturas, ferramentas ou recursos possíveis da qual um aplicativo corporativo específico pode se beneficiar. Suas opções de tecnologia para coisas como acesso a dados estão enraizadas na tecnologia mais comum e acessível para a maioria dos desenvolvedores de software de negócios que usam a pilha de tecnologia da Microsoft. Não inclui (atualmente) um suporte extensivo para coisas como registro, monitoramento ou análise, embora todos possam ser adicionados facilmente. Abaixo está uma lista das dependências tecnológicas que ela inclui e por que elas foram escolhidas. A maioria deles pode ser facilmente trocada por sua tecnologia de escolha, pois a natureza dessa arquitetura é apoiar a modularidade e o encapsulamento.
A validação da entrada do usuário é um requisito de todos os aplicativos de software. A questão é: onde faz sentido implementá -lo de maneira concisa e elegante? Este modelo de solução inclui 4 projetos separados, cada um dos quais pode ser responsável por realizar a validação e a aplicação de invariantes de negócios (que, dada a validação já deveriam ter ocorrido, são geralmente modelados como exceções).
O modelo de domínio em si geralmente deve depender do design orientado a objetos para garantir que ele esteja sempre em um estado consistente. Ele aproveita o encapsulamento e limita o acesso à mutação do Estado Público para conseguir isso, e assume que quaisquer argumentos transmitidos a ele já foram validados; portanto, valores nulos ou outros valores impróprios produzem exceções, não resultados de validação, na maioria dos casos.
Os casos de uso / projeto de aplicação incluem o conjunto de todos os comandos e consultas que o sistema suporta. É frequentemente responsável por validar seus próprios objetos de comando e consulta. Isso é feito mais facilmente usando uma cadeia de padrão de responsabilidade por meio de comportamentos mediatr ou algum outro pipeline.
O projeto da Web inclui todos os pontos de extremidade da API, que incluem seus próprios tipos de solicitação e resposta, seguindo o padrão REPR. A biblioteca FastEnSpoints inclui suporte interno para validação usando o fluentValidação nos tipos de solicitação. Este é um local natural para realizar a validação de entrada também.
Ter validação ocorre tanto dentro dos pontos de extremidade da API quanto novamente no nível do caso de uso pode ser considerado redundante. Existem trocas para adicionar essencialmente a mesma validação em dois lugares, uma para solicitações de API e outra para mensagens enviadas para usar os manipuladores de casos. Após a codificação defensiva, muitas vezes faz sentido adicionar validação em ambos os lugares, pois a sobrecarga é mínima e a paz de espírito e uma maior robustez de aplicação geralmente vale a pena.
O projeto principal é o centro do design da arquitetura limpa e todas as outras dependências do projeto devem apontar para ele. Como tal, possui muito poucas dependências externas. O projeto principal deve incluir o modelo de domínio, incluindo coisas como:
Você pode aprender mais sobre esses padrões e como aplicá -los aqui:
Um projeto opcional, eu o incluí porque muitas pessoas estavam exigindo e é mais fácil remover do que adicionar mais tarde. Isso também é frequentemente chamado de camada de serviços de aplicativo ou aplicativo . O projeto de casos de uso é organizado seguindo o CQRS em comandos e consultas (eu considerei ter pastas para Commands e Queries , mas achei pouco adicionado - as pastas por comando ou consulta real são suficientes sem aninhamento extra). Os comandos sofrem o modelo de domínio e, portanto, sempre devem usar abstrações de repositório para o acesso a dados (os repositórios são como se busca e persiste tipos de modelos de domínio). As consultas são reado e, portanto, não precisam usar o padrão do repositório , mas podem usar qualquer serviço ou abordagem de consulta mais conveniente.
Como o projeto de casos de uso é configurado para depender do núcleo e não depende da infraestrutura, ainda precisará haver abstrações definidas para o acesso a dados. E pode usar coisas como especificações, que às vezes podem ajudar a encapsular a lógica da consulta, bem como o mapeamento do tipo de resultado. Mas ele não precisa usar o repositório/especificação - pode apenas emitir uma consulta SQL ou chamar um procedimento armazenado se essa for a maneira mais eficiente de obter os dados.
Embora este seja um projeto opcional para incluir (sem ele, seus pontos de extremidade da API funcionariam diretamente com o modelo de domínio ou os serviços de consulta), ele fornece um bom local de I-I-Ignorante para adicionar testes automatizados e se presta à aplicação de políticas) para que as preocupações de corte cruzado, usando uma cadeia de padrões de responsabilidade em torno dos manipuladores de mensagens, como validação, times, times, traslados, login, login, login, login, login, atualização de uma cadeia de padrão de manipuladores de mensagens, como validação. O modelo inclui um exemplo disso para o log, localizado no pacote Sharedkernel Nuget.
A maioria das dependências do seu aplicativo em recursos externos deve ser implementada nas classes definidas no projeto de infraestrutura. Essas classes devem implementar interfaces definidas no núcleo. Se você possui um projeto muito grande com muitas dependências, pode fazer sentido ter vários projetos de infraestrutura (por exemplo, infraestrutura.data), mas para a maioria dos projetos um projeto de infraestrutura com pastas funciona bem. O modelo inclui o acesso a dados e implementações de eventos de domínio, mas você também adicionaria coisas como provedores de email, acesso a arquivos, clientes da API da Web etc. a este projeto, para que eles não estejam adicionando acoplamento aos seus projetos de núcleo ou interface do usuário.
O ponto de entrada do aplicativo é o projeto da Web ASP.NET Core (ou possivelmente o projeto AspireHost, que por sua vez carrega o projeto da Web). Na verdade, este é um aplicativo de console, com um método public static void Main no Program.cs . Ele aproveita os FastEnsPoints e o padrão REP para organizar seus pontos de extremidade da API.
Um kernel compartilhado é usado para compartilhar elementos comuns entre contextos limitados. É um termo DDD, mas muitas organizações aproveitam projetos ou pacotes "comuns" para coisas que são úteis para compartilhar entre vários aplicativos.
Eu recomendo a criação de um projeto e solução Sharedkernel separados, se você precisar de compartilhamento de código entre vários contextos limitados (consulte os fundamentos do DDD). Eu recomendo ainda que isso seja publicado como um pacote NUGET (provavelmente em particular em sua organização) e referenciado como uma dependência do NUGET por esses projetos que o exigem.
Anteriormente, um projeto para Sharedkernel era incluído neste projeto. No entanto, pelas razões acima, eu o fiz um pacote separado, Ardalis.Sharedkernel, que você deve substituir por seu próprio quando usar esse modelo .
Se você deseja ver outro exemplo de um pacote Sharedkernel, o que eu uso no meu curso atualizado do Pluralsight DDD está no NUGET aqui.
Os projetos de teste podem ser organizados com base no tipo de teste (unidade, funcional, integração, desempenho etc.) ou pelo projeto que eles estão testando (núcleo, infraestrutura, web) ou ambos. Para este kit inicial simples, os projetos de teste são organizados com base no tipo de teste, com projetos de teste de unidade, funcional e integração existentes nesta solução. Os testes funcionais são um tipo especial de teste de integração que realiza testes subcutâneos das APIs do projeto da Web, sem realmente hospedar um site real ou analisar a rede. Criei um monte de ajudantes de teste para tornar esses tipos de testes mais curtos e fáceis de manter.
Este modelo de solução possui código incorporado para suportar alguns padrões comuns, especialmente os padrões de design orientados a domínios. Aqui está uma breve visão geral de como alguns deles funcionam.
Os eventos de domínio são um ótimo padrão para dissociar um gatilho para uma operação de sua implementação. Isso é especialmente útil nas entidades de domínio, pois os manipuladores dos eventos podem ter dependências, enquanto as próprias entidades normalmente não. Na amostra, você pode ver isso em ação com o método ToDoItem.MarkComplete() . O diagrama de sequência a seguir demonstra como o evento e seu manipulador são usados quando um item é marcado completo através de um terminal da API da Web.
