Acredito que todos saibam o que é ou já tiveram contato com essa funcionalidade, mas para aqueles que não estão acostumado com o nome Help Insight, esse é um recurso do IDE do Delphi que apresenta um popup com uma breve descrição sobre o identificador (classe, método, função, variável, ...) na qual o cursor do mouse está posicionado.
Também é possível invocar o Help Insight através do pressionamento das teclas CTRL + SHIFT + H.
Por padrão é apresentado nesse popup menu as seguintes informações:
- Nome do identificador
- Categoria do identificador (Campo, variável, método, classe, propriedade, ...)
- Localização (nome da unit seguido pelo número da linha e da coluna)
- Tipo (Se o identificador é string, integer, ...)
No caso do identificador ser um método, function ou procedure, a descrição é extendida apresentando também o(s) parâmetro(s) e o valor de retorno.
Isso tudo é feito automaticamente pelo IDE em tempo de edição, ou seja, nem necessitar que o código seja compilado.
O que eu não sabia, e é o objetivo desse artigo, é que o conteúdo do popup menu pode ser customizado exibindo informações mais detalhadas a respeito do identificador em questão.
Essa customização deve estar situada imediatamente acima do identificador a qual se deseja trabalhar e tem seu início demarcado através de um comentário coringa (///, três barras) seguido por uma tag XML reconhecida pelo Help Insight viewer.
As tags XML atualmente reconhecida são:
- summary
- param
- returns
- permission
- remarks
- comments
/// <summary> Verificar se um determinado componente/field teve ou não seu conteúdo
/// alterado. O método é utilizado dentro do framework para sinalizar os
/// componentes que foram modificados durante uma operação de update.</summary>
/// <param name="FieldComp"> Registro contendo informações sobre o field/componente. </param>
/// <param name="Index"> Índice do registro dentro da lista (<c>FFieldList</c>). </param>
/// <param name="Modified"> Parâmetro de saída que deve ser setado para True/False, dependendo
/// do status verificado pelo método. Por padrão, o parâmetro vem
/// com o valor True. </param>
/// <returns> O valor retornado deve significar que o método obteve sucesso ao comparar o
/// valor original com o valor atual do componente/field, ou seja, que o valor
/// do parâmetro Modified é válido.</returns>
/// <permission> Esse método é utilizado internamente apenas quando o formulário está em estado
/// de alteração de registro. A implementação original trás suporte para os
/// componentes mais comumente utilizados, entretanto, em caso de customização ou
/// extenção do suporte a outros componentes, esse método pode sempre ser
/// reimplementado nos formulários filhos. </permission>
/// <remarks> Originalmente esse método foi concebido para ser utilizado pelo framework como
/// um serviço. Assim, evite chamá-lo diretamente a menos que saiba com exatidão
/// o que está fazendo. </remarks>
/// <comments> Caso necessite reimplementar o método, é recomendado que faça uma chamada à
/// implementação da classe pai (Exemplo: Result := inherited;). </comments>
/// alterado. O método é utilizado dentro do framework para sinalizar os
/// componentes que foram modificados durante uma operação de update.</summary>
/// <param name="FieldComp"> Registro contendo informações sobre o field/componente. </param>
/// <param name="Index"> Índice do registro dentro da lista (<c>FFieldList</c>). </param>
/// <param name="Modified"> Parâmetro de saída que deve ser setado para True/False, dependendo
/// do status verificado pelo método. Por padrão, o parâmetro vem
/// com o valor True. </param>
/// <returns> O valor retornado deve significar que o método obteve sucesso ao comparar o
/// valor original com o valor atual do componente/field, ou seja, que o valor
/// do parâmetro Modified é válido.</returns>
/// <permission> Esse método é utilizado internamente apenas quando o formulário está em estado
/// de alteração de registro. A implementação original trás suporte para os
/// componentes mais comumente utilizados, entretanto, em caso de customização ou
/// extenção do suporte a outros componentes, esse método pode sempre ser
/// reimplementado nos formulários filhos. </permission>
/// <remarks> Originalmente esse método foi concebido para ser utilizado pelo framework como
/// um serviço. Assim, evite chamá-lo diretamente a menos que saiba com exatidão
/// o que está fazendo. </remarks>
/// <comments> Caso necessite reimplementar o método, é recomendado que faça uma chamada à
/// implementação da classe pai (Exemplo: Result := inherited;). </comments>
Observe que foi utilizado também as tags <c> e </c>. Essas tags delimitam um área de texto que será formatada no estilo de código fonte do Delphi (por padrão, Courier New).
O resultado é:
Convenhamos que se você está navegando pelo código, um help assim é muito, mas muito mais útil do que simplesmente visualizar a assinatura do identificador (padrão do Delphi), certo? Além do mais, você não precisa se deslocar até a definição/implementação/declaração do identificador para obter maiores detalhes, o que quase sempre resulta na interrupção da linha de raciocínio durante alguma investigação.
Uma outra vantagem que notei sobre a utilização do Help Insigh é poder ter dois tipos de documentação a respeito de um método sobre dois pontos de vista.
Deixa eu exemplificar. Observe o código fonte abaixo.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
private
{ Private declarations }
protected
function FieldIsModified(var FieldComp: TFieldItem; const Index: Integer; out Modified: Boolean): Boolean; virtual;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
{_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\
Definition.: Protected Strict [ ] Virtual/Override [X] Event [ ]
Ojective...:
Usefulness.:
Parameters.: [ I ] FieldComp =
[ I ] Index =
[ O ] Modified =
Result.....:
Comments...:
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\}
function TForm1.FieldIsModified(var FieldComp: TFieldItem; const Index: Integer; out Modified: Boolean): Boolean;
begin
// ...
end;
end.
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
private
{ Private declarations }
protected
function FieldIsModified(var FieldComp: TFieldItem; const Index: Integer; out Modified: Boolean): Boolean; virtual;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
{_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\
Definition.: Protected Strict [ ] Virtual/Override [X] Event [ ]
Ojective...:
Usefulness.:
Parameters.: [ I ] FieldComp =
[ I ] Index =
[ O ] Modified =
Result.....:
Comments...:
_/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\__/-\}
function TForm1.FieldIsModified(var FieldComp: TFieldItem; const Index: Integer; out Modified: Boolean): Boolean;
begin
// ...
end;
end.
Creio que a prática mais comum de documentação de código seja a inclusão de comentários imediatamente acima da implementação dos métodos/funções (como apresentando no exemplo acima), ficando a área de interface da unit com apenas as definições.
O código fonte acima contém a estrutura do bloco de comentário que costumo utilizar para documentar um método ou uma function (removi o texto para ficar mais fácil sua visualização). As informações que acrescento nesse bloco estão relacionadas principalmente com seu funcionamento, com sua dependência perante a solução como um todo e com cuidados que devem ser tomados na sua utilização.
Quando penso no Help Inside, penso em um ponto de vista onde saber como é o funcionamento interno de um método não é tão importante, naquele momento, quanto saber o que o método faz, suas entradas e suas saídas. Assim, quando digo que o Help Insight proporciona um segundo tipo de comentários é justamente a possibilidade de documentar o código fonte sob uma perspectiva mais focada no conceito do que em detalhes intrínsecos ao funcionamento.
Apesar de muito útil, fique um tanto desconfortável com relação a legibilidade (ou melhor, à falta de legibilidade) que a estrutura de definição das tags causa ao layout da classe.
Por exemplo, se você possui um classe com vários métodos e propriedades. Acrescentar um help insigh para cada definição irá dinimuir a visão do todo por exigir constante deslocamento entre as linhas para navegar pela classe (aqui o layout struct do Delphi se mostrou ainda mais útil).
Fiz alguns testes e notei que o IDE aceita a utilização de REGIONS para delimitar a área do Help Insight, o que pareceu uma forma bem razoável para resolver ou, no mínimo, minimizar a área visível ocupada.
Um segundo ponto com relação a legibilidade é que não há uma formatação específica para as tags.
b) Pode-se acrescentar espaços vários espaços em brancos, mas os excedentes serão ignorados (assim como em HTML);
c) Qualquer quebra de linha será ignorada, o que dá margem para formatar melhor o texto na unit, mas na hora de exibir o popup, as frases serão concatenadas em um único parágrafo.
Isso faz com que não seja possível escrever um pequeno trecho de código, por exemplo.
Em outras palavras, fiquei com a impressão que é mais legível ler as descrições do popup do que diretamente do código fonte.
Boa sorte.
2 comentários:
Excelente artigo, obrigado por compartilhar seu conhecimento conosco.
Saberia me dizer apartir de qual versão do delphi esta disponivel estes recursos?
Obrigado pelo comentário.
Help Insight é um recurso que já tem algum tempo de vida, mas, infelizmente, não tão utilizado.
Ele passou a fazer parte do Delphi a partir da versão 2005, lançada no último quarter de 2004.
Na página 40 do "Borland Delphi 2005 Reviewer's Guide" você encontra uma breve descrição.
http://www.borland.com/resources/en/pdf/white_papers/delphi_2005_reviewers_guide.pdf
Postar um comentário