quarta-feira, 9 de agosto de 2006

Dica C++: Destrutor virtual abstrato

Em uma classe base, métodos virtuais são aqueles que podem ter sua implementação sobrescrita por uma classe filha.
Isto é uma verdade para métodos, mas não para destrutores. A implementação de um destrutor virtual em uma classe filha não sobrescreve a implementação da classe base. Ela estende.
Primeiro é executado o código do destrutor da classe filha, depois o código do destrutor da classe base.

Exemplo:


class Base
{
public:
virtual ~Base()
{
cout<< "\nDestrutor da classe base." << endl;
};

virtual void Metodo()
{
cout << "\nMétodo da classe base." << endl;
};
};

class Derivada : public Base
{
public:
virtual ~Derivada()
{
cout<< "\nDestrutor da classe derivada." << endl;
};

virtual void Metodo()
{
cout << "\nMétodo da classe derivada." << endl;
};
};

// ...

int main()
{
Base *obj = new Derivada;

obj->Metodo();

delete obj;
}


No exemplo acima, se um destrutor virtual não fosse declarado, o destrutor da classe filha não seria executado.

O destrutor virtual da classe filha extender o código do destrutor da classe base,claro, tem sua razão de ser. Se não fosse esse mecanismo, por exemplo, para uma classe base que tem objetos que são desalocados no momento de sua destruição, a classe filha teria que fazer todo o trabalho novamente...

E quando desejarmos criar uma classe puramente abstrata, ou seja, uma interface ?
O destrutor dela provavelmente teria de ser virtual, mas sendo abstrata não poderia ter código. Bom, e como não vai ter código se há a necessidade de executar o código de destruição, pelo destrutor ser virtual ???

Simples, declare um destrutor virtual abstrato com implementação.
Mas se é abstrato como terá implementação ?¿?
Bom, infelizmente C++ não foi bem planejado nesta parte... :(

No arquivo .h, declare normalmente:


class BasePura
{
public:
virtual ~BasePura() = 0; // destrutor virtual abstrato

virtual void Metodo() = 0;
};


No arquivo .cpp (implementação), implemente o destrutor:


BasePura::~BasePura()
{
// implementacao normalmente vazia
}


Esta é uma das partes mal planejadas do C++, que devem ser corrigidas futuramente
pelos novos padrões da linguagem, definidas pelo ISO C++ Standards Commitee.

terça-feira, 16 de maio de 2006

Separação em camadas - parte 1 (MVC)

Introdução

A idéia geral dos modelos de separação do software em camadas é a de dar você a possibilidade de variar as camadas independentemente e isso gerar pouco ou nenhum impacto nas demais.

Para conseguir isso, cada camada é projetada de forma que nenhuma saiba muito sobre o funcionamento interno da outra. A maioria só conhece o protocolo pelo qual vai se comunicar com a camada associada.

Não conhecendo detalhes sobre a implementação das camadas associadas, uma camada comunica-se sem necessitar entender o funcionamento das demais. Por isso o nível de abstração do modelo aumenta e você pode facilmente variar a implementação de cada parte (aplicando reutilização do modelo através da combinação de herança e polimorfismo).


MVC

O Model-View-Controller é um padrão criado inicialmente para ser utilizado no sistema de interface gráfica do SmalltalkTM (Goldberg e Robson, 1983), possuindo as seguintes metas:

  • Criar um conjunto de componentes que suporte um processo de desenvolvimento de software de alta interatividade.
  • Prover um conjunto de componentes que torne possível para programadores criar facilmente aplicações gráficas portáveis.


Antes do MVC, os projetos de interface com o usuário tendiam a agrupar o comportamento da interface e a lógica do problema no mesmo contexto, digamos numa mesma classe. O MVC separa cada parte numa classe diferente, a fim de aumentar a flexibilidade e a reutilização.

O MVC propõe a separação do modelo de interação com a interface com o usuário em três partes: uma Visão (View), um Modelo (Model) e uma Controladora (Controller). A Visão representa a interface com o usuário, a representação interativa do software. O Modelo representa o domínio da aplicação, a lógica sob a qual a Visão opera, transforma e obtém informações. A Controladora é um mediador entre o Modelo e a Visão, que tem como objetivo controlar a interação entre ambos, esconder os detalhes e diminuir a dependência entre as mesmas.

O funcionamento do modelo se dá da seguinte maneira:

1. O usuário executa alguma ação de entrada na interface, ou melhor, na Visão.

2. A Visão notifica a Controladora para mudar o Modelo de acordo com a ação executada.

3. A Controladora notifica o Modelo sobre a ação.

4. O Modelo recebe a notificação da Controladora, possivelmente alterando seu estado, e notifica indiretamente a todos que necessitam saber que seu estado se alterou.


A notificação indireta é feita registrando-se no Modelo todos os objetos que necessitam saber sobre sua atualização. No entanto, o Modelo não sabe nada a respeito dos objetos que ele notifica, a não ser que eles possuem um método comum para atualização (possivelmente se chamando Atualizar ou outro nome conveniente). Quando o Modelo precisa notificar outros objetos sobre sua mudança ele apenas chama este método, que envia uma mensagem para todos os objetos registrados (broadcast).

Assim sendo, os objetos que são notificados de atualizações no Modelo implementam um método comum (Atualizar), e por terem o mesmo comportamento, implementam (herdar de) uma mesma interface.

Quais podem ser os objetos notificados ? Eles podem ser as Controladoras ou mesmo as Visões. (Em breve, possivelmente em outro post, estarei discutindo problemas e melhorias relacionadas, além de outros modelos).

Nota sobre uso de Padrões:

O comportamento acima descrito sobre a notificação de objetos foi catalogado como um Padrão de Projeto (Design Pattern) sobre o nome Observador (Observer). A idéia é que as classes que são notificadas sobre as atualizações são as “observadoras” e as que enviam a notificação são as “observadas”.



Caso você também tenha notado, o papel da classe Controladora do modelo MVC pode ser descrita também como um Padrão, catalogado sob o nome de Mediador (Mediator). No padrão Mediador, um objeto encapsula como um conjunto de objetos interage. Ele promove o acoplamento fraco para evitar que os objetos se refiram explicitamente uns aos outros, permitindo que eles variem independentemente.

Sendo assim, vamos analisar um exemplo simples, para retratar o modelo MVC:

Um usuário deseja conceder desconto em uma venda que ele está realizando. Quando o novo desconto é informado, o total da venda é recalculado e atualizado na tela, refletindo a mudança.
Para isso, teremos uma janela de venda (GUI_Venda) e um classe de venda (Venda).
Venda é uma classe (filha de) Observada
e GUI_Venda é (filha de) uma classe Observadora.

Vamos nos ater ao problema proposto:
Ao se conceder um desconto à venda, ela recalcula seu total. É desejado entretanto que ao recalcular seu total, a interface com o usuário exiba o novo total recalculado.

Tomando-se as devidas abstrações, o modelo seria parecido com este:


Ao recalcular seu total (método RecalcularTotal), venda notifica seus observadores (veja diagrama estrutural do padrão Observador), fazendo com que eles se atualizem com o total da venda. Isso acontece sem que Venda saiba quem está se atualizando. Ela sabe apenas que há observadores que serão atualizados.

Essa é a idéia por trás do padrão Observador, e é a base do MVC.

A atualização via notificação indireta é uma poderosa ferramenta para nos auxiliar no desenvolvimento de diferentes interfaces para o mesmo modelo. Isso porque a informação permanece sempre sincronizada com o modelo. Ao alterarmos o modelo, essa alteração se reflete em todas as interfaces.

Em um próximo post estarei discutindo mais sobre o modelo MVC, alguns padrões relacionados e alguns outros modelos, como o Model-View-Presenter (MVP).

Até breve.

domingo, 30 de abril de 2006

Baixando "na unha" vídeos do Google Video

A cada dia vídeos e mais vídeos são adicionados no Google Video e é cada vez mais freqüente o surgimento de players FLV para exibí-los. Apesar do site fazer streaming do vídeo, impedindo de baixá-lo da forma usual, há algumas formas de baixá-lo diretamente, utilizando-se de alguns pequenos passos.
Se você quiser ser poupado do trabalho, recomendo baixar o Google Video Downloader, ou outro programa que já faz o trabalho por você (Obs: O Google Video Downloader requer o Microsoft.NET Framework 1.1 - com 23.1 MB ).

Se quiser tentar a outra forma, aqui vai:

1- Abra o vídeo no Google Video da forma usual
2- Quando a página for carregada e o vídeo começar a ser carregado, abra o código fonte da página (no Firefox, clique com o botão direito na página e vá em "Código-fonte". No Internet Explorer, o procedimento é similar)
3- Localize o texto googleplayer.swf?videoURL
4- Um pouco a frente, está o texto http
5- Copie desde http até true (que está um pouco a frente de autoPlay)
6- Cole o texto num editor de texto qualquer
7- Substitua todos os seguintes trechos (ex: usando Editar -> Substituir no Notepad e clicando em Substiuir Tudo)
  • substitua %3A por :
  • substitua %2F por /
  • substitua %3F por ?
  • substitua %3D por =
  • substitua \u003d por =
  • substitua %26 por &

8- Copie e cole o texto, ou melhor, a nova URL no seu browser. Um arquivo .FLV vai aparecer pra ser baixado. Pronto.

Para o vídeo ser visualizado, use algum
"FLV player" disponível (há diversas opções gratuitas).
Prepare a pipoca e assista seus vídeos prediletos sem ter que fazer streaming. ;)


Explicação mais... "técnica":
O passo 7 se baseia na substituição dos códigos Unicode daURL em sua forma normal. Cada código possui o símbolo
% mais o código hexadecimal ASCII do símbolo, que pode ser obtido no AsciiTable.com. (Traduzindo, se você encontrar mais % no texto, vá no site AsciiTable.com e veja o símbolo referente ao texto. Por exemplo, %24 equivalerá à $, pois 24 é o número hexadecimal referente ao símbolo $).