Namespaces gerenciados

Resumo

Introdução

Os namespaces gerenciados são usados no SDK do Weave para fornecer aos desenvolvedores e integradores do SDK do Weave orientações e subtextos divulgados sobre a designação de conjuntos de APIs específicos no SDK. Assim, eles podem planejar e prever o caminho de migração nas 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 administrados com uma das quatro designações:

Desenvolvimento

Qualquer namespace gerenciado com a designação "Desenvolvimento" é uma indicação para os desenvolvedores e integradores de que as APIs contidas nelas estão em desenvolvimento ativo, podem estar sujeitas a mudanças e não têm suporte oficial. Em geral, os integradores não são incentivados a usar essas APIs, a menos que sejam especificamente instruídos a fazer isso.

Próxima

Qualquer namespace gerenciado com a designação Next é uma indicação para os desenvolvedores e integradores de que as APIs contidas nelas, embora tenham concluído o desenvolvimento ativo em grande parte, ainda podem estar sujeitas a mudanças e têm suporte para fins de avaliação inicial. As APIs designadas representam a próxima frente evolucionária em uma API do SDK do Weave e se tornarão as APIs padrão atuais em um ciclo importante de lançamentos no futuro imediato.

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

A designação do próximo namespace gerenciado oferece aos desenvolvedores e integradores uma visão do futuro do SDK do Weave, indicando qual será a API padrão atual em uma versão futura.

A designação de namespace gerenciado do Next é opcional. Assim, um namespace gerenciado pode fazer a transição ao longo de um ciclo de vida sem usá-la. Consulte Ciclo de vida de namespaces gerenciados.

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 oficial atual compatível com essa parte ou módulo do SDK do Weave. Embora ainda possam haver melhorias contínuas para essas APIs, as alterações serão em grande parte relativas à compatibilidade com versões anteriores e APIs e devem ser mantidas.

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

Legado

Qualquer namespace gerenciado com a designação "Legado" indica aos desenvolvedores e integradores que as APIs contidas nelas foram descontinuadas e substituídas por uma nova API atual. Elas representam o que era a API atual.

As APIs designadas desaparecerão completamente na próxima versão principal do SDK do Weave; Consequentemente, os desenvolvedores e integradores precisam estabelecer planos para a migração dessas APIs caso pretendam permanecer na vanguarda das versões do SDK do Weave.

Ciclo de vida dos namespaces gerenciados

A figura a seguir ilustra o ciclo de vida de um namespace gerenciado à medida que ele passa do desenvolvimento e, potencialmente, para o legado:

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

Se for empregado, o ciclo de vida do namespace gerenciado começará com a designação de desenvolvimento.

Quando o desenvolvimento estiver 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 totalmente descartada e o namespace gerenciado não é mais empregado, tornando a designação implicitamente atual.

Se o código precisa existir junto e ainda não substituir o código atual, a designação deverá migrar para Next. Se o código precisar substituir o código atual, a designação precisará migrar para a Current.

Usando a designação Next, depois que o código tiver passado 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 Current, se o código precisar ser substituído por um novo, mas ainda precisar ser mantido por vários ciclos de lançamento, a designação migrará para Legado.

Da designação legada, o código é completamente removido 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 um integrador, integrando o Weave ao próprio aplicativo, plataforma e código do sistema. As duas seções a seguir detalham recomendações para lidar com namespaces gerenciados do Weave dessas duas perspectivas.

Como usar namespaces gerenciados como um desenvolvedor

Um foco fundamental do desenvolvedor de SDK do Weave é aprimorar e desenvolver novas APIs e funcionalidades do SDK do Weave, ao mesmo tempo que, em muitos casos, é compatível com as implantações existentes de API e funcionalidade.

Quando não é possível satisfazer essas duas áreas de foco de maneira compatível com versões anteriores na mesma API, os namespaces gerenciados oferecem um mecanismo para gerenciar essas APIs em paralelo, de uma maneira que não interrompa as implantações existentes de API e funcionalidade.

Como exemplo funcional, suponha que um perfil do Weave, Mercury, que exista atualmente na seguinte hierarquia de namespace não gerenciada:

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 módulo "umbrella" cabeçalho. A maioria dos integradores simplesmente inclui o módulo "umbrella" como mostrado:

#include 

No entanto, a desenvolvedora da Mercury chegou a um ponto em que há a necessidade de desenvolver uma próxima geração de APIs e, potencialmente, o protocolo de transmissão via cabo que não são compatíveis com versões anteriores das implantações existentes. Usar namespaces gerenciados pode ajudar a conseguir isso sem corromper essas implantações atuais.

Mover o namespace existente para o atual

Com o objetivo de continuar a oferecer suporte à versão atual da API e à 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/

Observe que, além de mover os arquivos, as proteções de inclusão de cabeçalho para os arquivos movidos também devem ser renomeadas, possivelmente decorando-os com "_CURRENT", já que novos arquivos com nomes semelhantes serão criados 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 esse conteúdo em cada arquivo de cabeçalho quando houver vários arquivos de cabeçalho.

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

#include <Weave/Support/ManagedNamespace.hpp>

#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 de 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 seu namespace não é suficiente para garantir que as implantações existentes funcionem sem alterações, pois todas usam diretivas de inclusão que especificaram os cabeçalhos recém-movidos.

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

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

Se apenas um namespace gerenciado atualmente designado está sendo criado sem criar um namespace gerenciado designado como Desenvolvimento ou Próximo para acompanhá-lo, o conteúdo desses arquivos pode simplesmente consistir em um cabeçalho include guard e uma diretiva include especificando o cabeçalho recém-movido de 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 e também para acomodar desenvolvimentos novos e incompatíveis, 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, isso é preferível a repetir e duplicar esse conteúdo em cada arquivo de cabeçalho quando houver vários arquivos de cabeçalho.

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

#include <Weave/Support/ManagedNamespace.hpp>

#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, como desejado, a designação do namespace gerenciado é definida como "Atual" se nenhuma configuração tiver sido definida.

Com esse cabeçalho em vigor, 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

Nesse ponto, a infraestrutura está pronta 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 <Weave/Support/ManagedNamespace.hpp>

#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, origem, arquivos ou cabeçalhos, tudo isso poderá ser feito no mesmo arquivo de cabeçalho, sem mover 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 ao longo de um espectro de complexo a simples.

Como usar namespaces gerenciados como um integrador

Um foco importante do integrador de SDKs do Weave é incluir os cabeçalhos da API pública apropriados do SDK do Weave e integrar e desenvolver aplicativos com base neles.

Como exemplo funcional, considere novamente um perfil do Weave, Mercury, que tem namespaces gerenciados designados como Next-, Current- e Legacy, com cabeçalhos públicos 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 módulo "umbrella" cabeçalho.

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 os cabeçalhos públicos do módulo do Weave pelos caminhos padrão não gerenciados (por exemplo, Weave/Profiles/Mercury/Mercury.hpp). Isso permite seguir uma progressão de desenvolvimento da API sem alterar continuamente as diretivas de inclusão de um projeto à medida que essas APIs fluem pelo ciclo de vida gerenciado.

Seguindo essa estratégia, as implantações podem redirecionar o código para uma designação de namespace gerenciado diferente, a designação 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 de inclusão 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 legada, basta fazer uma nova segmentação ajustando a definição do pré-processador:

#define WEAVE_CONFIG_MERCURY_NAMESPACE kWeaveManagedNamespace_Legacy