Por que as estruturas de guarda-chuva são desencorajadas?

Desejo distribuir o Framework A. O Framework A depende do Framework B. Eu quero que um usuário do meu framework precise apenas include o Framework A, mas ainda tenha access programático ao Framework B.

A Apple faz isso o tempo todo usando o conceito de “Umbrella Frameworks”, mas há este tópico nos documentos:

Não crie estruturas de guarda-chuva

Embora seja possível criar frameworks guarda-chuva usando o Xcode, isso é desnecessário para a maioria dos desenvolvedores e não é recomendado. A Apple usa frameworks guarda-chuva para mascarar algumas das interdependencies entre bibliotecas no sistema operacional. Em quase todos os casos, você deve poder include seu código em um único pacote de framework padrão. Alternativamente, se seu código fosse suficientemente modular, você poderia criar múltiplos frameworks, mas, nesse caso, as dependencies entre os módulos seriam mínimas ou inexistentes e não deveriam garantir a criação de um guarda-chuva para elas.

Por que essa abordagem é desencorajada? O que torna uma boa solução para o problema de estruturas interdependentes da Apple, mas não para o meu?

As estruturas da Umbrella só farão sentido se você for o único distribuidor de todas as estruturas envolvidas, e você estará empacotando todas as estruturas juntas como um único pacote versionado que será atualizado em conjunto. Se esta é a sua situação, tudo bem, mas esta é uma situação muito incomum. No mundo do desenvolvimento do cacau, é extremamente incomum para qualquer um, exceto a Apple, estar nessa situação.

Para o primeiro ponto, os frameworks guarda-chuva só fazem sentido se você for o único distribuidor dos frameworks fornecidos. Por exemplo, digamos que você queira include o libcurl como parte de sua estrutura guarda-chuva. Agora algum outro empacotador também quer include o libcurl como parte de sua estrutura de guarda-chuva. Agora temos uma colisão de tempo de link que pode levar a erros de link ou pior, comportamento de tempo de execução indefinido. Eu mesmo os persegui. Eles são extremamente desagradáveis. A única maneira de evitar isso é que haja apenas uma versão de cada estrutura / biblioteca. Estruturas de guarda-chuva encorajam o oposto.

Mesmo que você esteja apenas dividindo seu próprio código em subpecas, isso significa que outros fornecedores podem usar seus subframeworks em seus próprios frameworks guarda-chuva, levando de volta ao mesmo problema. Lembre-se, se você disser que está tudo bem para você, como terceiro, usar frameworks de guarda-chuva, então tudo bem para outros fornecedores também.

Para o segundo ponto, os frameworks guarda-chuva só farão sentido se você controlar o versionamento de todos os subframeworks. Tentar consertar uma parte de um conjunto interdependente de estruturas é quase sempre um desastre na minha experiência.

O fornecedor do sistema operacional tem uma situação incomum devido ao tamanho e à onipresença de seu sistema. Coisas que fazem sentido em uma escala geralmente não fazem sentido em outra. O NSResponder está completamente correto sobre isso. Os trade-offs são diferentes quando você está fornecendo um ambiente de pacote completo, que é a base de todo programa escrito para a plataforma. Mas mesmo a Apple tem apenas um punhado de frameworks grandes, e eles são sempre wrappers em torno de bibliotecas que eles fornecem e controlam a versão do. Isso é principalmente para simplificar o trabalho de desenvolvedores que, de outra forma, teriam que perseguir dezenas de bibliotecas e estruturas para obter algo para compilar. Nenhum terceiro tem essa situação e, portanto, é muito raro que um terceiro precise dessa solução. Pedir ao seu cliente para vincular duas bibliotecas é completamente diferente, em seguida, pedir-lhes para vincular 20. Se você está fornecendo 20 frameworks que trabalham juntos e você controla, então talvez você deva usar um guarda-chuva, mas talvez você tenha muitos frameworks para um terceiro.

A maior parte da minha discussão aqui é em termos de OS X. No iOS, não é problema para terceiros. Bibliotecas estáticas nunca devem vincular outras bibliotecas estáticas devido às colisões que certamente ocorrerão.

Em teoria, a maioria dos problemas que discuti aqui são limitações fundamentalmente técnicas do vinculador. O vinculador não tem uma boa maneira de gerenciar várias versões de bibliotecas e, portanto, as colisões são um problema sério. Os conjuntos .NET tentam fornecer mais flexibilidade em torno disso. Eu não estou familiarizado o suficiente com o desenvolvimento .NET para dizer se isso foi bem-sucedido ou não. Minha experiência com grandes sistemas multi-componentes é que soluções mais simples e menos flexíveis são as melhores para a maioria dos problemas. (Mas a grama é sempre mais verde …)

Um problema é que a versão do framework B está agora vinculada à versão do framework A. Isso pode ser o que você quer em alguns casos e não em outros. Se a estrutura B provavelmente será usada independentemente por um aplicativo que também queira usar a estrutura A, esse aplicativo pode se encontrar em uma situação em que a versão de B incluída em A não é a versão que ela precisa ou deseja.

A estrutura B é uma estrutura que um aplicativo poderia usar independentemente de A? Se sim, você pode se deparar com esse cenário. Se B é uma estrutura que não está disponível fora de A, então você não deve se deparar com este cenário.

No caso da Apple, eles estão entregando uma enorme quantidade de código, e esses sub-frameworks são freqüentemente revisados ​​separadamente. Se você está entregando vários shows de frameworks, então você pode querer ir em frente e fazer um framework guarda-chuva. Se não, você provavelmente não precisa do incômodo.