Namespaces gerenciados

Resumo

Introdução

Os namespaces gerenciados são usados no SDK do Weave para fornecer aos desenvolvedores e integradores de SDK do Weave orientações e subtextos anunciados sobre a designação de conjuntos específicos de APIs no SDK. Assim, eles podem planejar e prever o caminho de migração entre versões do SDK do Weave e, potencialmente, gerenciar várias APIs do Weave simultâneas para um determinado módulo.

Designação

Os namespaces gerenciados podem ser gerenciados de acordo com uma das quatro designações:

Desenvolvimento

Qualquer namespace gerenciado com a designação "Desenvolvimento" é uma indicação para desenvolvedores e integradores de que as APIs contidas estão em desenvolvimento ativo, podem estar sujeitas a mudanças e não têm suporte oficial. Geralmente, não é recomendável que os integradores usem essas APIs, a menos que sejam direcionados especificamente para isso.

Próxima

Qualquer namespace gerenciado com a designação Next é uma indicação para desenvolvedores e integradores de que as APIs contidas nele, embora tenham concluído o desenvolvimento ativo em grande parte, ainda podem estar sujeitas a mudanças e ter suporte para fins de avaliação inicial. As APIs designadas dessa forma representam a próxima frente evolutiva em uma API Weave SDK e se tornarão as APIs padrão atuais em um grande ciclo de lançamento no futuro imediato ou próximo.

A compatibilidade com versões anteriores, tanto de uma perspectiva de API quanto do protocolo over-the-wire, pode existir, mas não é garantida nas APIs designadas assim.

A designação de namespace gerenciado do Next fornece aos desenvolvedores e integradores uma visão de onde o SDK do Weave será direcionado, sugerindo qual será a API padrão atual em uma versão futura.

A designação de namespace gerenciado é opcional para que um namespace gerenciado possa fazer a transição ao longo de um ciclo de vida sem usá-lo. Consulte Ciclo de vida do namespace gerenciado.

Atual

Qualquer namespace gerenciado com a designação atual ou qualquer namespace não gerenciado (ou seja, sem uma designação de namespace gerenciado) representa a API atual, padrão e oficial com suporte para essa parte ou módulo do SDK do Weave. Embora ainda possa haver melhorias em andamento nessas APIs, as alterações serão em grande parte incrementadas e compatíveis com versões anteriores, tanto a API quanto a transmissão, que precisam ser mantidas.

A designação atual do namespace gerenciado é opcional. Assim, ele pode fazer a transição ao longo de um ciclo de vida sem usá-lo. Consulte Ciclo de vida do namespace gerenciado. Na verdade, todos os namespaces não gerenciados são implicitamente atuais.

Legada

Qualquer namespace gerenciado com a designação Legado é uma indicação para desenvolvedores e integradores de que as APIs contidas foram descontinuadas e substituídas por uma nova API atual. Essas APIs representam o que era anteriormente a API atual.

As APIs designadas dessa forma vão desaparecer completamente na próxima grande versão do SDK do Weave. Consequentemente, os desenvolvedores e integradores devem definir planos de migração dessas APIs caso pretendam manter a vanguarda das versões do SDK do Weave.

Ciclo de vida do namespace gerenciado

A figura a seguir ilustra o ciclo de vida de um namespace gerenciado conforme ele faz a transição de desenvolvimento e, possivelmente, para legado:

.-------------.      .- - - .      .- - - - -.      .--------.
| Development | -.->   Next   -.->   Current   ---> | Legacy |
'-------------'  |   '- - - '  |   ' - - - - '      '--------'
                 |             |
                 '-------------'

Se empregado, o ciclo de vida do namespace gerenciado começa com a designação de Desenvolvimento.

Quando o desenvolvimento for concluído e o código estiver pronto para avaliação e integração, a designação migrará para "Next" ou "Current". Como alternativa, a designação pode ser descartada e o namespace gerenciado não é mais empregado, o que torna a designação implicitamente atual.

Se o código existir junto com o código atual, mas ainda não substituí-lo, a designação precisa migrar para "Próxima". Se o código for substituir o código atual, a designação precisará migrar para a atual.

Ao usar a designação Próxima, depois que o código passa pelo número desejado de ciclos de lançamento e avaliação, a designação migra para "Atual" ou, novamente, a Designação pode ser totalmente descartada.

Usando a designação atual, se o código for substituído por outro, mas ainda precisar de manutenção por vários ciclos de lançamento, a designação migrará para a versão legada.

Da designação Legado, o código é removido completamente do SDK do Weave.

Como usar namespaces gerenciados

Os usuários do SDK do Weave podem interagir com namespaces gerenciados como desenvolvedores, estendendo e mantendo o código existente, ou como integradores, integrando o Weave aos próprios aplicativos, plataformas e códigos de sistema. As duas seções a seguir detalham recomendações para lidar com namespaces gerenciados pelo Weave a partir dessas duas perspectivas.

Como usar namespaces gerenciados como desenvolvedor

Um foco principal do desenvolvedor do SDK do Weave é melhorar e desenvolver novas APIs e funcionalidades do SDK do Weave e, em muitos casos, oferecer suporte a implantações existentes de API e funcionalidade.

Quando não é possível atender a essas duas áreas de foco de maneira compatível com versões anteriores na mesma API, os namespaces gerenciados fornecem um mecanismo para gerenciar essas APIs em paralelo, sem interromper as implantações atuais de APIs e funcionalidades.

Como exemplo funcional, considere um perfil do Weave, Mercury, que atualmente existe na seguinte hierarquia de namespaces não gerenciados:

namespace nl {
namespace Weave {
namespace Profiles {
namespace Mercury {

// ...

}; // namespace Mercury
}; // namespace Profiles
}; // namespace Weave
}; // namespace nl

e os seguintes cabeçalhos públicos:

  • Weave/Profiles/Mercury/Mercury.hpp
  • Weave/Profiles/Mercury/Bar.hpp
  • Weave/Profiles/Mercury/Foo.hpp
  • Weave/Profiles/Mercury/Foobar.hpp

em que Mercury.hpp é o cabeçalho "umbrella" do módulo. A maioria dos integradores inclui o cabeçalho "umbrella" do módulo, conforme mostrado abaixo:

#include 

No entanto, o desenvolvedor do Mercury chegou a um ponto em que há a necessidade de desenvolver uma próxima geração de APIs e, potencialmente, o protocolo over-the-wire, que não são compatíveis com versões anteriores das implantações existentes. O uso de namespaces gerenciados pode ajudar a fazer isso sem interromper essas implantações atuais.

Mover o namespace existente para o atual

Para continuar oferecendo suporte à versão atual da API e da funcionalidade das integrações implantadas, a primeira tarefa é mover o código atual:

% cd src/lib/profiles/mercury
% mkdir Current
% mv Mercury.hpp Bar.hpp Foo.hpp Foobar.hpp *.cpp Current/

Além de mover os arquivos, o cabeçalho inclui proteções para os arquivos movidos, que também podem ser renomeados com "_CURRENT", já que novos arquivos com nomes semelhantes serão criados no lugar deles abaixo.

Com o código movido, a próxima etapa é gerenciar o namespace com a designação apropriada, aqui "Current". Primeiro, crie um cabeçalho que defina o namespace gerenciado, como "Current/MercuryManagedNamespace.hpp". É preferível criar esse cabeçalho do que repetir e duplicar o conteúdo em cada arquivo de cabeçalho quando houver vários arquivos desse tipo.

% cat << EOF > Current/MercuryManagedNamespace.hpp
#ifndef _WEAVE_MERCURY_MANAGEDNAMESPACE_CURRENT_HPP
#define _WEAVE_MERCURY_MANAGEDNAMESPACE_CURRENT_HPP

#include 

#if defined(WEAVE_CONFIG_MERCURY_NAMESPACE) && WEAVE_CONFIG_MERCURY_NAMESPACE != kWeaveManagedNamespace_Current
#error Compiling Weave Mercury current-designation managed namespace file with WEAVE_CONFIG_MERCURY_NAMESPACE defined != kWeaveManagedNamespace_Current
#endif

#ifndef WEAVE_CONFIG_MERCURY_NAMESPACE
#define WEAVE_CONFIG_MERCURY_NAMESPACE kWeaveManagedNamespace_Current
#endif

namespace nl {
namespace Weave {
namespace Profiles {

namespace WeaveMakeManagedNamespaceIdentifier(Mercury, kWeaveManagedNamespaceDesignation_Current) { };

namespace Mercury = WeaveMakeManagedNamespaceIdentifier(Mercury, kWeaveManagedNamespaceDesignation_Current);

}; // namespace Profiles
}; // namespace Weave
}; // namespace nl

#endif // _WEAVE_MERCURY_MANAGEDNAMESPACE_CURRENT_HPP
EOF

Em seguida, inclua esse cabeçalho antes de outras diretivas de inclusão específicas do módulo nos cabeçalhos existentes. Exemplo:

#include 

#include 

Criar cabeçalhos de compatibilidade

No entanto, mover os cabeçalhos existentes para um novo local e gerenciar o namespace sozinho não é suficiente para garantir que as implantações existentes funcionem sem alteração, já que todas usam diretivas de inclusão que especificam os cabeçalhos movidos acima.

Para resolver isso, é necessário criar cabeçalhos de wrapper de compatibilidade com nomes que correspondem aos que acabaram de ser movidos.

% touch Mercury.hpp Bar.hpp Foo.hpp Foobar.hpp

Se apenas um namespace gerenciado designado como Current estiver sendo criado sem criar um namespace gerenciado designado como “Desenvolvimento” ou “Próximo” para acompanhá-lo, o conteúdo desses arquivos poderá simplesmente consistir em um cabeçalho de inclusão e uma diretiva de inclusão especificando o cabeçalho recém-movido com o mesmo nome:

#ifndef _WEAVE_MERCURY_BAR_HPP
#define _WEAVE_MERCURY_BAR_HPP

#include 

#endif // _WEAVE_MERCURY_BAR_HPP

No entanto, se um namespace gerenciado designado como “Desenvolvimento” ou “Próximo” estiver sendo criado também para acomodar um desenvolvimento novo e incompatível, algo um pouco mais complexo precisará ser feito.

Como antes, um cabeçalho para a configuração de namespace gerenciado é criado, aqui como MercuryManagedNamespace.hpp. Novamente, é preferível repetir e duplicar esse conteúdo em cada arquivo de cabeçalho quando há vários arquivos desse tipo.

% cat << EOF > MercuryManagedNamespace.hpp
#ifndef _WEAVE_MERCURY_MANAGEDNAMESPACE_HPP
#define _WEAVE_MERCURY_MANAGEDNAMESPACE_HPP

#include 

#if defined(WEAVE_CONFIG_MERCURY_NAMESPACE)                             \
  && (WEAVE_CONFIG_MERCURY_NAMESPACE != kWeaveManagedNamespace_Current) \
  && (WEAVE_CONFIG_MERCURY_NAMESPACE != kWeaveManagedNamespace_Development)
#error "WEAVE_CONFIG_MERCURY_NAMESPACE defined, but not as namespace kWeaveManagedNamespace_Current or kWeaveManagedNamespace_Development"
#endif

#if !defined(WEAVE_CONFIG_MERCURY_NAMESPACE)
#define WEAVE_CONFIG_MERCURY_NAMESPACE kWeaveManagedNamespace_Current
#endif

#endif // _WEAVE_MERCURY_MANAGEDNAMESPACE_HPP
EOF

Observe que, conforme desejado, essa designação de namespace gerenciado será definida como "Current" se nenhuma configuração tiver sido definida.

Com esse cabeçalho, os cabeçalhos do wrapper de compatibilidade agora podem ser editados para conter:

#include 

#if WEAVE_CONFIG_MERCURY_NAMESPACE == kWeaveManagedNamespace_Development
#include 
#else
#include 
#endif // WEAVE_CONFIG_MERCURY_NAMESPACE == kWeaveManagedNamespace_Development

ou o que for apropriado para o caso de uso de gerenciamento de namespace em questão.

Criar conteúdo de desenvolvimento

Neste ponto, a infraestrutura já está em vigor para começar a criar novas funcionalidades e APIs além das atuais.

% mkdir Development
% touch Development/Mercury.hpp Development/Bar.hpp Development/Foo.hpp Development/Foobar.hpp
% cat << EOF > Development/MercuryManagedNamespace.hpp
#ifndef _WEAVE_MERCURY_MANAGEDNAMESPACE_DEVELOPMENT_HPP
#define _WEAVE_MERCURY_MANAGEDNAMESPACE_DEVELOPMENT_HPP

#include 

#if defined(WEAVE_CONFIG_MERCURY_NAMESPACE) && WEAVE_CONFIG_MERCURY_NAMESPACE != kWeaveManagedNamespace_Development
#error Compiling Weave Mercury development-designated managed namespace file with WEAVE_CONFIG_MERCURY_NAMESPACE defined != kWeaveManagedNamespace_Development
#endif

#ifndef WEAVE_CONFIG_MERCURY_NAMESPACE
#define WEAVE_CONFIG_MERCURY_NAMESPACE kWeaveManagedNamespace_Development
#endif

namespace nl {
namespace Weave {
namespace Profiles {

namespace WeaveMakeManagedNamespaceIdentifier(Mercury, kWeaveManagedNamespaceDesignation_Development) { };

namespace Mercury = WeaveMakeManagedNamespaceIdentifier(Mercury, kWeaveManagedNamespaceDesignation_Development);

}; // namespace Profiles
}; // namespace Weave
}; // namespace nl

#endif // _WEAVE_MERCURY_MANAGEDNAMESPACE_DEVELOPMENT_HPP
EOF

Obviamente, se um módulo for muito mais simples do que o exemplo apresentado aqui e não tiver muitas classes, fontes, arquivos ou cabeçalhos, isso poderá ser feito no mesmo arquivo principal sem mover os arquivos e criar vários cabeçalhos independentes de configuração e compatibilidade. No entanto, com esse exemplo complexo, ele deve inspirar soluções de namespace gerenciado em um espectro, do complexo ao simples.

Como usar namespaces gerenciados como integradores

Um dos principais focos do integrador de SDKs do Weave é incluir os cabeçalhos de API pública do SDK do Weave adequados e integrar e desenvolver aplicativos com base neles.

Como exemplo funcional, suponha novamente um perfil do Weave, Mercury, que tem namespaces gerenciados designados Next-, Current- e Legacy, cujos cabeçalhos públicos são estruturados da seguinte maneira:

  • Weave/Profiles/Mercury/Mercury.hpp
  • Weave/Profiles/Mercury/Bar.hpp
  • Weave/Profiles/Mercury/Foo.hpp
  • Weave/Profiles/Mercury/Foobar.hpp
  • Weave/Profiles/Mercury/Next/Mercury.hpp
  • Weave/Profiles/Mercury/Next/Bar.hpp
  • Weave/Profiles/Mercury/Next/Foo.hpp
  • Weave/Profiles/Mercury/Next/Foobar.hpp
  • Weave/Profiles/Mercury/Current/Mercury.hpp
  • Weave/Profiles/Mercury/Current/Bar.hpp
  • Weave/Profiles/Mercury/Current/Foo.hpp
  • Weave/Profiles/Mercury/Current/Foobar.hpp
  • Weave/Profiles/Mercury/Legacy/Mercury.hpp
  • Weave/Profiles/Mercury/Legacy/Bar.hpp
  • Weave/Profiles/Mercury/Legacy/Foo.hpp
  • Weave/Profiles/Mercury/Legacy/Foobar.hpp

em que Mercury.hpp é o cabeçalho "umbrella" do módulo.

A menos que o caso de uso em questão motive a inclusão explícita de um módulo gerenciado de namespace no Weave, por exemplo:

#include 

é melhor referenciar cabeçalhos públicos do módulo Weave pelos caminhos padrão não gerenciados (por exemplo, Weave/Profiles/Mercury/Mercury.hpp). Isso permite acompanhar um progresso de desenvolvimento da API sem alterar continuamente as diretivas de inclusão de um projeto, conforme essas APIs fluem pelo lifecycle gerenciado.

Seguindo essa estratégia, as implantações podem redirecionar o código a outra designação de namespace gerenciado, a atual, por exemplo, especificando a configuração desejada no pré-processador C/C++. Isso pode ser feito na linha de comando, no código-fonte ou em um cabeçalho de configuração ou prefixo:

#define WEAVE_CONFIG_MERCURY_NAMESPACE kWeaveManagedNamespace_Current

e use o caminho "include" não gerenciado / não qualificado:

#include 

Quando e se a designação do namespace gerenciado mudar para as APIs de destino, por exemplo, de Atual para Legado, basta fazer uma nova segmentação ajustando a definição do pré-processador:

#define WEAVE_CONFIG_MERCURY_NAMESPACE kWeaveManagedNamespace_Legacy