Ruby on Rails modularização com Packwerk Episode II
Nicolas Nisoria
No segundo episódio da nossa modularização Ruby on Rails com Packwerk, vamos analisar de perto o conceito de aplicação como um pacote.
Aplicação como um pacote
A abordagem para modularizar a nossa aplicação consiste em converter toda a aplicação num pacote.
Criar a estrutura
Primeiro, precisamos de criar app/pacotes onde colocaremos todos os nossos pacotes. Para isolar os nossos pacotes, temos de separar cada Conceito MVC numa pasta. Pegar no CodeTriage projeto como exemplo, teremos algo parecido com a seguinte imagem.
Se tentarmos executar o servidor, ele não conseguirá encontrar as constantes. É por isso que precisamos adicionar uma linha de configuração ao nosso aplicação.rb
Agora a aplicação funciona mas não consegue encontrar as vistas, por isso precisamos de adicionar outra linha de configuração ao nosso application_controller.rb
A nossa estrutura está pronta, por isso agora podemos começar a criar os pacotes. Para isso, só precisamos de adicionar umpackage.yml para cada pasta com a seguinte configuração:
enforce_privacy: false
enforce_dependencies: true
impor_privacidadedá nós a possibilidade de isolar todas as constantes do pacote e trabalhar com uma API pública. Para expor as constantes públicas, precisamos de adicionar as constantes em, por exemplo packages/users/app/public.Para já, vamos definir esta configuração para falso.
impor_dependências irá impor a dependência de um pacote e verificar todas as referências constantes. Se uma dependência não for explicitamente definida, será uma violação do limite.
Validação do sistema de pacotes
Packwerk estabeleceu um critério que temos de seguir para termos um sistema de pacotes válido. Podemos começar a executar packwerk validado na nossa consola.
Isto irá verificar a nossa estrutura de pastas, configuração do pacotee cache de caminho de carregamento automático.
Neste momento, a nossa aplicação não é válida e temos de corrigir os caminhos de carregamento empackwerk.yml. Para o fazer, só temos de acrescentar os caminhos em falta.
Nesta altura, estamos prontos para verificar as violações de limites na nossa aplicação. Para verificar as violações, podemos executarpackwerk update-deprecations , este comando irá gerar deprecated_references.yml para cada pacote. Em cada ficheiro, encontraremos o nome do pacote, o tipo de violação e o caminho do ficheiro. Com todas estas informações, sabemos onde está a ocorrer a violação e podemos tomar uma decisão para a resolver.
Tomando o exemplo, vamos descrever cada parte da informação gerada por Packwerk.
– app/pacotes/repos - pacote onde a violação constante é encontrado.
– ::Repo - caminho para o ficheiro que contém a constante violada.
– dependência - um tipo de violação, seja de dependência ou de privacidade.
– app/packages/users/models/user.rb - caminho para o ficheiro que contém a constante violada.
Como passo final nesta secção, não se esqueça de adicionar os novos caminhos de ficheiros gerados ao packwerk.yml e executar novamente as validações.
Visualização de dependências
Com todas as informações em package.yml e deprecated_references.ymlpodemos então visualizar um gráfico de dependências. Para isso, precisamos de adicionar outra gem, neste caso vamos usar Pocky.
Ancinho de corrida pocky:gerar vamos gerar um ficheiro chamado packwerk.png onde podemos visualizar o nosso primeiro gráfico de dependências.
Com todos os pacotes definidos, o nosso gráfico terá o seguinte aspeto.
as dependências já existem, mas isso não significa que sejam aceites pelo Packwerk. Para aceitar uma dependência, precisamos de adicionar a configuração das dependências ao package.yml em cada pacote. Concentrar-nos-emos em criadores de correio uma vez que se trata de um pacote sem dependência circular. Vale a pena mencionar que Packwerk não nos deixa aceitar dependências circulares.
Depois de adicionar esta configuração, Pocky irá colorir de verde as dependências aceites.
Podemos apagar deprecated_references.yml de app/packages/mail_builders e executar packwerk update-deprecations novamente. O ficheiro não será gerado novamente, uma vez que todos os foram corrigidas para este pacote. É importante mencionar que mesmo que não façamos o Graph com dependências aceites
Rubi modularização em Rails com Packwerk aceitar dependências, a nossa aplicação continuará a funcionar como antes, mas agora temos mais informações para tomar decisões e refactorizar.
Remover dependências circulares
No nosso gráfico anterior, tínhamos muitas dependências circulares que precisavam de ser resolvidas de alguma forma. Temos diferentes estratégias para o fazer:
- Executar injeção de dependência ou injeção de dependência com tipagem.
Uma questão aqui é que, para fazer uma refacção adequada, precisamos de conhecer a base de código. Não estou muito familiarizado com a base de código deste projeto, uma vez que o tomei como exemplo, por isso, por razões práticas, vamos optar pela primeira estratégia, não fazer nada. Mesmo que evitemos a maior parte da refatoração, queremos trabalhar nas dependências do raiz pacote.
O pacote raiz contém toda a cola do pacote Estrutura RailsTodas as classes de que herdamos e fazemos com que todas trabalhem em conjunto. Assim, para resolver as dependências circulares, vamos criar um novo pacote chamado rails nos seguintes passos:
Mover todos os ficheiros e pastas da aplicação_ da aplicação para app/pacotes/rails.
Criar umpackage.yml para o pacote com a mesma configuração que os pacotes anteriores.
Adicione todos os novos caminhos de ficheiro a packwerk.yml.
Adicionar app/pacotes/rails como uma dependência do resto dos pacotes.
Assim que criarmos o pacote, começaremos a reparar em muitos ficheiros que podem ser reestruturados. Depois de mover tudo para o pacote correspondente e aceitar o teremos uma nova estrutura e um gráfico mais limpo.
Remover dependências do pacote raiz
Agora nosso gráfico parece muito melhor, seria ótimo se pudéssemos remover todas as dependências do pacote raiz. Se verificarmos o deprecated_references.yml no pacote raiz, notaremos que a maioria delas são do teste , lib/tasks , db e configuração pasta. Para resolver estas dependências, vamos criar uma pasta de teste dentro de cada pacote. Ter algo como app/pacotes/utilizadores/teste. De seguida, vamos excluir lib/tasks , db e configuraçãoentre outras pastas de Packwerk uma vez que essas dependências não são realmente importantes na nossa análise e não temos uma forma fácil de as resolver. Vamos adicionar o seguinte ao nosso packwerk.yml.
Depois de mover todos os testes do pacote raiz e excluir as pastas da análise, teremos um novo gráfico sem as dependências raiz.
Como podemos ver, continuamos a ter dependências circulares emutilizadores , repositórios e documentos . Embora não as tenhamos resolvido, temos informações importantes para transmitir agora. Sabemos que todos os equipa que realiza mudanças em um desses pacotes provavelmente terá que realizar mudanças nos pacotes com a dependência circular. Por outro lado, sabemos que uma equipa pode trabalhar em github_fetchers apenas, saber quais são os pacotes sendo afetado pelas mudanças em cada momento.
Como próximo passo, pode impor uma privacidade constante em cada pacote e expor apenas a API pública que será acessível a partir de outros pacotes. Você pode facilmente configurar onde sua API será colocada em package.yml.
Packwerk dá-nos muitas informações sobre a nossa aplicação e, com essas informações, podemos tomar decisões para melhorar o fluxo de trabalho das nossas equipas. Embora o processo pareça ser longo e com muitas configurações, não precisa de ser sempre assim. Podemos começar a criar pacotes apenas para o novo código adicionado à nossa aplicação e depois modularizar gradualmente. Então agora podemos começar a falar sobre Modularização Gradual, este é o conceito introduzido por Stephan Hagemann "Podemos, pela primeira vez, decidir começar a modularizar uma parte do código de uma forma aspiracional... Isto permite-nos criar um sistema de apoio que se expande gradualmente em direção a uma melhor estrutura de aplicação".