Design C++ moderno

Da Wikipédia, a enciclopédia livre
  (Redireccionado de Design baseado em políticas )
Ir para a navegação Saltar para pesquisar
Design C++ moderno
Modern C++ Design.jpg
AutorAndrei Alexandrescu
Linguageminglês
SujeitoC++
EditorAddison-Wesley
Data de publicação
2001
Páginas323 pp
ISBN978-0-201-70431-0
OCLC45129236
005.13/3 21
Classe LCQA76.73.C153 A42 2001

Modern C++ Design: Generic Programming and Design Patterns Applied é um livro escrito por Andrei Alexandrescu , publicado em 2001 pela Addison-Wesley . Foi considerado como "um dos livros C++ mais importantes" por Scott Meyers . [1]

O livro utiliza e explora uma técnica de programação C++ chamada metaprogramação de modelo . Embora Alexandrescu não tenha inventado a técnica, ele a popularizou entre os programadores. Seu livro contém soluções para problemas práticos que os programadores C++ podem enfrentar. Várias frases do livro agora são usadas na comunidade C++ como termos genéricos: C++ moderno (em oposição ao estilo C/C++), design baseado em políticas e typelist .

Todo o código descrito no livro está disponível gratuitamente em sua biblioteca Loki . O livro foi republicado e traduzido para vários idiomas desde 2001.

Design baseado em políticas [ editar ]

Design baseado em políticas , também conhecido como design de classe baseado em políticas ou programação baseada em políticas , é o termo usado em Design C++ moderno para uma abordagem de design baseada em um idioma para C++ conhecido como políticas . Ele foi descrito como uma variante em tempo de compilação do padrão de estratégia e tem conexões com a metaprogramação de modelo C++ . Foi popularizado pela primeira vez em C++ por Andrei Alexandrescu com Modern C++ Design e com sua coluna Generic<Programming> no C/C++ Users Journal , e atualmente está intimamente associado com C++ e Dpois requer um compilador com suporte altamente robusto para templates , o que não era comum antes de 2003.

Exemplos anteriores desta abordagem de projeto, baseada em código genérico parametrizado, incluem módulos paramétricos (functors) das linguagens ML , [2] e alocadores C++ para política de gerenciamento de memória.

O idioma central no design baseado em políticas é um modelo de classe (chamado de classe host ), recebendo vários parâmetros de tipo como entrada, que são instanciados com tipos selecionados pelo usuário (chamados de classes de política ), cada um implementando uma interface implícita específica (chamada de policy ) e encapsular algum aspecto ortogonal (ou principalmente ortogonal) do comportamento da classe host instanciada. Ao fornecer uma classe de host combinada com um conjunto de diferentes implementações predefinidas para cada política, uma biblioteca ou módulopode suportar um número exponencial de diferentes combinações de comportamento, resolvidas em tempo de compilação e selecionadas pela mistura e correspondência das diferentes classes de política fornecidas na instanciação do modelo de classe do host. Além disso, escrevendo uma implementação personalizada de uma determinada política, uma biblioteca baseada em política pode ser usada em situações que exigem comportamentos imprevistos pelo implementador da biblioteca. Mesmo nos casos em que nunca mais de uma implementação de cada política será usada, a decomposição de uma classe em políticas pode ajudar no processo de design, aumentando a modularidade e destacando exatamente onde as decisões de design ortogonal foram tomadas.

Embora a montagem de componentes de software a partir de módulos intercambiáveis ​​esteja longe de ser um conceito novo, o design baseado em políticas representa uma inovação na maneira como aplica esse conceito no nível (relativamente baixo) de definir o comportamento de uma classe individual. As classes de política têm alguma semelhança com os retornos de chamada , mas diferem porque, em vez de consistir em uma única função , uma classe de política normalmente contém várias funções relacionadas ( métodos ), geralmente combinadas com variáveis ​​de estado ou outros recursos, como tipos aninhados. Uma classe de host baseada em políticas pode ser pensada como um tipo de metafunção, pegando um conjunto de comportamentos representados por tipos como entrada e retornando como saída um tipo que representa o resultado da combinação desses comportamentos em um todo funcional. (Ao contrário das metafunções MPL , no entanto, a saída geralmente é representada pela própria classe de host instanciada, em vez de um tipo de saída aninhado.)

Uma característica-chave do idioma de política é que, geralmente (embora não seja estritamente necessário), a classe host derivará de (se tornará uma classe filha de) cada uma de suas classes de política usando herança múltipla (pública) . (As alternativas são para a classe host conter meramente uma variável de membro de cada tipo de classe de política, ou então herdar as classes de política de forma privada; no entanto, herdar as classes de política publicamente tem a grande vantagem de que uma classe de política pode adicionar novos métodos, herdados pelo classe de host instanciada e acessível a seus usuários, sobre a qual a própria classe de host nem precisa saber.) Uma característica notável desse aspecto do idioma de política é que, em relação à programação orientada a objetos, as políticas invertem o relacionamento entre a classe base e a classe derivada - enquanto em OOP as interfaces são tradicionalmente representadas por classes base ( abstratas ) e as implementações de interfaces por classes derivadas, no design baseado em políticas a classe derivada (host) representa as interfaces e a base (políticas) as implementam. No caso de políticas, a herança pública não representa um relacionamento é-um entre o host e as classes de política. Embora isso seja tradicionalmente considerado evidência de um defeito de design em contextos OOP, isso não se aplica no contexto do idioma da política.

Uma desvantagem das políticas em sua encarnação atual é que a interface de política não tem uma representação direta e explícita no código , mas é definida implicitamente, por meio da digitação de pato , e deve ser documentada separadamente e manualmente, nos comentários . A ideia principal é usar a análise de variabilidade de comunalidade para dividir o tipo em implementação e interface fixas, a classe baseada em políticas e as diferentes políticas. O truque é saber o que entra na classe principal e quais políticas devem ser criadas. O artigo mencionado acima dá a seguinte resposta: sempre que precisarmos tomar uma possível decisão de limitação de design, devemos adiar essa decisão, devemos delegá-la a uma política nomeada apropriadamente.

As classes de política podem conter implementação, definições de tipo e assim por diante. Basicamente, o designer da classe de modelo principal definirá o que as classes de política devem fornecer, quais pontos de personalização eles precisam implementar.

Pode ser uma tarefa delicada criar um bom conjunto de políticas, apenas o número certo (por exemplo, o mínimo necessário). Os diferentes pontos de personalização, que estão juntos, devem entrar em um argumento de política, como política de armazenamento, política de validação e assim por diante. Os designers gráficos podem dar um nome às suas políticas, que representam conceitos, e não aquelas que representam operações ou pequenos detalhes de implementação.

O design baseado em políticas pode incorporar outras técnicas úteis. Por exemplo, o padrão de método de modelo pode ser reinterpretado para tempo de compilação, de modo que uma classe principal tenha um algoritmo esqueleto , que – em pontos de customização – chama as funções apropriadas de algumas das políticas.

Isso será alcançado dinamicamente por conceitos [3] em versões futuras de C++.

Exemplo simples [ editar ]

Apresentamos a seguir um exemplo simples (criado) de um programa C++ hello world , onde o texto a ser impresso e o método de impressão são decompostos usando políticas. Neste exemplo, HelloWorld é uma classe de host onde são necessárias duas políticas, uma para especificar como uma mensagem deve ser mostrada e a outra para a mensagem real que está sendo impressa. Observe que a implementação genérica está em Rune, portanto, o código não pode ser compilado, a menos que ambas as políticas ( Printe Message) sejam fornecidas.

#include <iostream> 
#include <string> 

template < typename OutputPolicy , typename LanguagePolicy >    
class  HelloWorld : private OutputPolicy , private LanguagePolicy {      
 público :
  // Método de comportamento. 
void Executar () const {     
    // Dois métodos de política. 
Imprimir ( Mensagem ());    
  }

 privado :
  usando LanguagePolicy :: Mensagem ; 
  usando OutputPolicy :: Print ; 
};

class  OutputPolicyWriteToCout { 
 protegido :
  template < typename MessageType >  
  void Imprimir ( MessageType && mensagem ) const {    
    std :: cout << mensagem << std :: endl ;    
  }
};

class  LanguagePolicyInglês { 
 protegido :
  std :: string Message () const { return "Olá, Mundo!" ; }      
};

class  IdiomaPolíticaAlemão { 
 protegido :
  std :: string Message () const { return "Hallo Welt!" ; }      
};

int main () {  
  // Exemplo 1 
usando HelloWorldEnglish = HelloWorld < OutputPolicyWriteToCout , LanguagePolicyEnglish > ;      

  HelloWorldEnglish hello_world ; 
  Olá_mundo . Executar (); // Imprime "Olá, Mundo!".  

  // Exemplo 2 
// Faz o mesmo, mas usa outra política de idioma. using HelloWorldGerman = HelloWorld < OutputPolicyWriteToCout , LanguagePolicyGerman > ;  
      

  HelloWorldGerman hello_world2 ; 
  hello_world2 . Executar (); // Imprime "Hallo Welt!". }  

Os designers podem facilmente escrever mais OutputPolicys adicionando novas classes com a função de membro Printe tomando-as como novos OutputPolicys.

Biblioteca Loki [ editar ]

Loki é o nome de uma biblioteca de software C++ escrita por Andrei Alexandrescu como parte de seu livro Modern C++ Design .

A biblioteca faz uso extensivo de metaprogramação de modelo C++ e implementa várias ferramentas comumente usadas: typelist , functor , singleton , smart pointer , object factory , visitor e multimethods .

Originalmente, a biblioteca era compatível apenas com dois dos compiladores C++ mais padronizados ( CodeWarrior e Comeau C/C++ ): esforços posteriores a tornaram utilizável com uma ampla variedade de compiladores (incluindo Visual C++ 6.0 mais antigo , Borland C++ Builder 6.0 , Clang e CCG ). Os fornecedores de compiladores usaram o Loki como referência de compatibilidade, aumentando ainda mais o número de compiladores compatíveis. [4]

A manutenção e o desenvolvimento do Loki continuaram por meio de uma comunidade de código aberto liderada por Peter Kümmel e Richard Sposato como um projeto SourceForge . As contribuições contínuas de muitas pessoas melhoraram a robustez geral e a funcionalidade da biblioteca. O Loki não está mais vinculado ao livro, pois já possui muitos componentes novos (por exemplo, StrongPtr, Printf e Scopeguard). O Loki inspirou ferramentas e funcionalidades semelhantes agora também presentes na coleção da biblioteca Boost . [ citação necessária ]

Veja também [ editar ]

Referências [ editar ]

Links externos [ editar ]