14 de abril de 2010

Criando componentes com Delphi - parte I

Um componente é um pedaço de programa construído para executar uma tarefa específica. Desse modo, o mesmo pedaço pode ser adicionado a quaisquer programas que precisem executar a tarefa proposta. Além de agilizar a criação de novos programas, criar componentes os torna mais seguros já que, uma vez que o componente foi bem testado, o risco de que ele apresente alguma falha fica reduzido. Para resumir em uma expressão, componentizar significa reutilizar códigos que já foram validados - com todas os benefícios que isso implica (tempo, dinheiro, segurança, etc.).

O desenvolvimento de programas através dos ambientes Delphi e C++ Builder é fortemente calcado na criação de componentes. Embora a maioria dos componentes disponíveis sejam visuais, isto é, propiciam ao usuário do programa final algum tipo de interação visual (botões, caixas de edição, tree views, etc.), isto não é uma obrigação. Há uma categoria de componentes "não visuais" que executam suas tarefas sem serem apresentados na tela. Mas esse fato é apenas uma das faces de um componente Delphi. Como todos os componentes nesse ambiente podem ser arrastados para montar um form, é preciso ainda se preocupar em como será a interação do componente com o programador que o está utilizando, quais propriedades serão publicadas para configuração através do Object Inspector, etc.

Por isso, iniciar a criação de um componente em Delphi demanda o planejamento de suas características estruturais. Responder algumas perguntas básicas ajuda nesse planejamento:
O que meu componente deve fazer ?
Pode parecer bobagem, mas estabelecer logo de cara o comportamento esperado para o componente ajuda a evitar surpresas desagradáveis. Querer acrescentar mais tarde uma funcionalidade que não tinha sido prevista pode exigir uma revisão radical da estrutura, tanto do componente quanto de outros fontes associados a ele.
Meu componente será exibido na interface gráfica ?
Todo componente no Delphi deve ser criado como uma herança direta ou indireta da classe TComponent, que é quem fornece o comportamento para interação com o form e outros detalhes. Responder a essa pergunta ajudará a determinar qual das classes derivadas de TComponent deverá ser usada como superclasse para nosso componente. Por exemplo, todos os componentes visíveis para o usuário devem herdar de TControl (ou uma de suas muitas heranças).
O componente que vou construir é totalmente novo ou já algo parecido ?
Aqui novamente o objetivo é estabelecer a classe base mais apropriada para nosso componente. Se o que você almeja é, por exemplo, padronizar o comprimento e a altura dos botões que serão adicionados aos forms seu programa, não é preciso criar um novo botão do zero. Neste caso, é mais prático criar uma herança de TButton.
Como será a interação com o programador ?
A resposta a essa pergunta permite determinar com antecedência quais propriedades deverão ser publicadas no inspector, a planejar a forma com que o componente como um todo se comportará quando houver alterações no valor dessas propriedades - inclusive em Design - e antever se será preciso criar um editor especial para facilitar a manutenção desses valores em tempo de design.
Meu componente estará vinculado a um Banco de dados ?
Permitir que um componente interaja com banco de dados exige alguns cuidados extras. O componente poderá estar ligado a um único campo, a uma query ou a uma tabela inteira, sendo que a comunicação deve ser feita por intermédio de classes especiais. Também é preciso cuidado para não disparar alterações não previstas nos dados.
Meu componente estará vinculado a outro(s) componente(s) ?
Vincular um componente a outro não é uma situação rara - muitos componentes permitem associar um Popup Menu ou um Action (ação genérica), por exemplo. Mas isso requer atenção com as interações decorrentes de tal associação. Um problema clássico envolvendo esse cenário é como agir quando o componente associado é removido da memória (comando Free).
Introduzir eventos faz sentido no meu componente ?
Eventos servem para notificar o programador a respeito de ocorrências relevantes dentro do seu componente. Eles dão ao programador a oportunidade de tomar providências, modificando o comportamento padrão do seu componente ou usando informações fornecidas por ele para realizar alguma outra operação - como mostrar um status. Alguns exemplos de eventos: um botão foi clicado, um novo registro está posicionado no banco de dados, uma operação se encerrou, um erro ocorreu, etc.
Em suas versões mais recentes, o Delphi passou a diferenciar os pacotes de componentes que podem ser usados em tempo de Design daqueles exclusivos para uso em tempo de execução. Essa diferenciação ocorreu porque componentes complexos podem incluir editores especiais para facilitar a vida do programador que está configurando o componente em tempo de design. Esses editores deixavam o pacote maior mas eram irrelevantes para o usuário final, de forma que agora eles podem ser incluídos num pacote a parte que não precisa ser distribuído.

Portanto, ao planejar um pacote de componentes, essa organização também deve ser levada em consideração - embora ainda exista a possibilidade de se criar pacotes que funcionem tanto em Design quanto em Execução.

Em outros posts eu mostro na prática e passo a passo como criar componentes, desde simples heranças de componentes preexistentes até a criação de editores especiais para componentes complexos, passando por uso de eventos, aplicação de funções da API do Windows, vínculo com banco de dados, associações entre componentes e outros assuntos que forem surgindo.

Um comentário :

Anônimo disse...

Excelente post, parabéns.

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.