Definindo abstrações através de Classes
De ccppbrasil.org
A abstração é o mecanismo utilizado na representação de um problema em todas as áreas do conhecimento.
Com ela definimos tipos e conceitos nas mais variadas formas para se representar elementos do problema, tornando assim o seu entendimento lógico e compreensível.
Com abstrações mudados o domínio do problema. Por exemplo: costumamos representar um ponto com as coordenadas (x,y). O conceito real do ponto não é o mesmo que o conceito do ponto usado na abstração. O elemento real, por exemplo, pode ser o centro de um campo de futebol, mas o centro deste gramado pode ser visto com um disco e não como um ponto. O centro do campo possui um diâmetro e na abstração não tenho este dado, além disso o conceito não inclui o fato de estar num gramado. Não estou usando o diâmetro, nem o local pois não interessa ao meu problema.
Este exemplo demonstra a troca de domínio que está ocorrendo e a simplificação. Na essência de um programa de computador as abstrações refletem instruções para o processador. Estas também são abstrações das operações que estão correndo com os bytes dentro do computador. Note que "bytes" também é um conceito, uma abstração que representa memória.
Na matemática, quase tudo pode ser escrito com pequenos axiomas. Utilizando soma e subração fazemos tudo, ou quase tudo. Nem por isso representamos todas expressões com "+" e "-".
Podemos escrever:
2 + 2 + 2 + 2
ou simplemesmente:
2 * 4
Depois de aprender o conceito da multiplicação este torna-se mais claro e mais intuitivo do que usar o 2 + 2 + 2 + 2.
Do mesmo modo podemos pensar em abstrair 2 * 2 * 2 * 2 como 2 ^ 4, que poderia ser escrito como 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2.
Da mesma forma, um programa de computador poderia ser todo feito utilizando assembly, com o mínimo de abstração disponível. Teríamos que representar um conceito de um ponto, por exemplo, como valores na memória e operações sobre estes valores. Claro que as peças básicas devem ser conhecidas. Com elas podemos criar simplificações e tirar outras conclusões.
Contudo, fica claro que não é por este motivo que as abstrações não devem ser utilizadas.
O C++ oferece maravilhos mecanismos de abstração. E, como em nenhuma outra linguagem, estes mecanismos seguem um princípio de zero overhead.
Algums programadores C criticam o C++ afirmando que os mecanismos de abstração criam overhead e por isso preferem utilizarar apenas o paradigma procedural apenas. Essa afirmação pode ser verdade caso o programa em C++ seja mal feito. Assim como problemas de performance podem ocorrerer em um programa em C mal feito.
Os mecanismos mais representativos de abstrações no C++ são as classes e os templates. As classes vêm do paradigma conhecido como orientação a objetos. E diferente de outras linguagens que são apenas orientadas a objetos como Java ou C#, no C++ tem-se o controle de tudo. Por exemplo, não é preciso ter uma classe base para tudo. Não é preciso ter funções virtuais se você não quiser. Os membros não são inicializados se você não quiser, enfim, você tem pleno controle.
Os templates são um assunto tão fascinante e poderoso que mereceria um texto específico. Através dos templates a qualidade do código gerado é inigualável, superando o código gerado em C (claro que é sempre possível escrever qualquer coisas em C, assim como é possível fazer em assembly).
Definindo abstrações através de classes:
- Escolha um nome representativo. Caso a escolha do nome esteja difícil é sinal de que você não sabe ao certo o que quer representar;
- Liste as operações que você deseja;
- Pense nas caracteríticas básicas como tipo, construção, cópia, limpeza. Bloqueie o que não é usado ou permitido;
- Torne as coisas certas fácis de serem feitas. Torne as coisas erradas difíceis ou impossíveis de serem feitas;
- Separe interface de implementação. Não crie uma dependência desnecessária.
Algums dos conceitos do C++ podem ser mal usados, causando overhead. Se você for um programador de verdade, e geralmente quem usa C++ o é, saiba o que está ocorrendo por trás das operações. Saiba o que o que faz um constructor, um desctructor uma operação virtual, etc. Dessa forma você terá confiança no que está fazendo e fará o código correto no que diz respeito a performance. Não supervalorize uma característica. Não pense que tudo precisa de uma forte abstração. Tenha em mente seu problema atual, não queira que sua classe resolva todos o problemas do mundo. Por exemplo, não coloque todas as suas funções virtuais como forma de deixar mais customizável, isso pode estar somente alterando o real significado da sua classe.
Uma das abstrações mais interessante criadas usando C++ se encontra na sua própria biblioteca padrão (STL): são os iterators.
O conceito do iterator é um apontador para um item de um container. Pode ser um item de um vector, de uma lista, de uma mapa, enfim, qualquer container. Para o caso do vector, essa abstração se torna na sua forma básica de implementação nada mais do que um ponteiro. Isso significa zero overhead.
Conclusões
Não deixe de usar abstrações. Torne o trabalho mais fácil para si mesmo e para outros programadores que utilizem sua classe. Torne seus tipos seguros, prevenindo ou dificultado que coisas erradas sejam feitas.
Torne seu problema mais fácil de ser manipulado e entendido, assim haverá mais clareza, segurança e facilidade de manuntenção.
Caso venha do C, não deixa de aprender todas as ferramentas de abstração do C++ e surpreenda-se com o que o que pode ser feito sem overhead.
Mentalize problemas através de tipos básicos. Com a prática, será mais fácil criar novos conceitos.
Thiago Rosso Adams - 11/01/2006
