Swift Package Manager Série 03|Principais conceitos em Package.swift
O que é realmente difícil é entender o que produtos, metas e dependências significam nos limites do projeto.
Ao abrir o Package.swift pela primeira vez, sua primeira impressão será: o arquivo não é longo e a sintaxe não é complicada.
Mas é fácil ficar confuso quando você realmente inicia o projeto, porque a dificuldade não está em “a sintaxe se parece com o Swift”, mas no fato de que vários conceitos centrais nele realmente correspondem à estrutura do projeto, e não a itens de configuração comuns.
Se você pensar nisso apenas como uma “lista para preencher alguns campos”, muitas vezes sentirá que conhece cada palavra, mas ficará facilmente confuso ao alterá-la. O que realmente precisa ser entendido é quais questões esses conceitos respondem.
O mais importante é capturar primeiro estas funções principais:
- pacote
- produtos
- dependências
- alvos
1. Package.swift descreve relacionamentos de módulo
Este é o primeiro passo para entendê-lo.
Uma situação comum é que você subconscientemente pensa nisso como:
-Arquivo de configuração do projeto
- Depende dos arquivos de instalação
- ou “Podspec para Swift”
Mas do ponto de vista da engenharia, Package.swift é mais como uma especificação de relacionamento de módulo.
Está dizendo ao conjunto de ferramentas:
- O que este pacote proporciona ao mundo exterior?
- De quais pacotes externos depende?
- Quais metas são compostas internamente?
- Como essas metas estão relacionadas entre si
Portanto, ele se concentra em “como esse código deve ser organizado em módulos e usado por outros”.
2. products responde: Que capacidades este pacote deseja oferecer ao mundo exterior?
Este é o ponto mais facilmente esquecido quando se lida inicialmente com este tipo de problema.
target é a unidade de construção interna e product é o resultado consumível externamente.
Em outras palavras, a pergunta respondida por product é:
O que este pacote pretende expor aos seus usuários?
Há um sinal de design muito importante por trás disso.
Se você não tem ideia sobre o product, é fácil confundir a estrutura interna do pacote com seu uso externo.
É claro que pode haver vários alvos dentro de um pacote, mas o exterior não precisa necessariamente conhecer todas essas divisões internas.
Portanto, product está essencialmente empacotando a interface externa.
Se você entender dessa perspectiva, pensará com mais naturalidade:
- Quais metas internas são detalhes de implementação
- Quais habilidades realmente precisam ser expostas?
- Qual o nível que os dependentes externos devem ver?
3. dependencies responde: Quais recursos este pacote empresta do mundo exterior?
Quando vi esta situação dependencies, pensei apenas em “instalar uma biblioteca de terceiros”.
Mas do ponto de vista da engenharia, seu significado mais importante é:
Fora dos limites deste módulo, de que mundo externo depende.
Isso afetará diretamente:
- O módulo é leve o suficiente?
- É caro compilar?
- É fácil reutilizar no futuro?
- Também vinculará o projeto host a algumas dependências externas?
Se um módulo tiver muitas dependências externas, geralmente causará dois problemas:
- Não é mais leve
- Seus limites também estão começando a ficar obscuros
Portanto, ao olhar para o dependencies, não pense apenas em “ele pode ser instalado”, mas também em “por que este módulo precisa depender dessas coisas”.
4. targets responde: Como o código interno deve ser organizado e compilado?
Esta é a parte do Package.swift que é mais facilmente considerada como “mapeamento de pasta”, mas na verdade é muito mais do que isso.
target realmente corresponde a:
- Um grupo de códigos compilados juntos
- Uma unidade de dependência explícita
- um limite de módulo interno
Ao definir a meta, você está decidindo:
- Quais códigos devem evoluir juntos
- Quais implementações devem ser colocadas na mesma unidade de compilação
- Quais testes devem corresponder a este limite
Portanto, o alvo é uma das menores unidades de modularidade interna.
Se você quebrar o alvo em muitos pedaços, o projeto ficará mais pesado. Se o alvo for muito grande, os limites ficarão desfocados. Isso também mostra que Package.swift parece ser apenas uma configuração, mas na verdade carrega muitos julgamentos arquitetônicos.
5. Confunda product com target
Porque em pacotes simples, eles geralmente correspondem um a um.
Por exemplo:
- um alvo
- um produto de biblioteca
Neste momento, é fácil pensar erroneamente que os dois conceitos são semelhantes. Mas quando o projeto ficar um pouco mais complicado, você encontrará:
- Um pacote pode ter vários alvos
- Vários alvos podem servir um produto
- Alguns alvos são apenas implementações internas e não devem ser expostos diretamente
Então minha experiência é: **Entenda o alvo como a estrutura interna e o produto como a saída externa. **
Dessa forma, o pensamento ficará muito mais claro de uma só vez.
6. O alvo do teste também é muito importante
Ao ver o Package.swift pela primeira vez, você considerará o alvo de teste como uma configuração de acessório.
Mas do ponto de vista do pensamento modular, é na verdade muito importante.
Como o valor de um módulo não é digno de existência independente, ele também se reflete em grande medida em:
- Pode ser testado de forma independente
- Se os seus limites de dependência são suficientemente claros
- Se é possível verificar o comportamento principal sem depender do aplicativo host
Se um módulo tiver que contar com metade do projeto host para cada teste, embora seja um pacote no nome, os limites podem não ser independentes de fato.
7. Uma ordem de leitura mais prática
Se eu abrir o Package.swift para um projeto desconhecido pela primeira vez, geralmente o vejo nesta ordem:
1.products
Vejamos primeiro o que ele expõe ao mundo exterior.
2. dependencies
Vejamos o que ele pegou emprestado do mundo exterior
3. targets
Por fim, vamos ver como o interior é desmontado.
Os benefícios desta sequência são: Olhe primeiro para os limites e depois olhe para dentro, em vez de se prender aos detalhes da implementação.
8. Conclusão: A dificuldade do Package.swift não está na sintaxe, mas sim no fato de ele realmente descrever os limites do projeto.
Para resumir, eu diria:
Package.swiftO mais importante é se você consegue entender o relacionamento limite por trás deproduct,dependencyetarget.
Uma vez compreendido sob esta perspectiva, este arquivo não é mais apenas uma configuração, mas uma expressão condensada do design do módulo.
What to read next
Want more posts about Swift Package Manager?
Posts in the same category are usually the best next step for reading more on this topic.
View same categoryWant to keep following #Swift?
Tags are useful for related tools, specific problems, and similar troubleshooting notes.
View same tagWant to explore another direction?
If you are not sure what to read next, return to the homepage and start from categories, topics, or latest updates.
Back home