Blog – FAQ 9

Blog - FAQ 9

Olá, leitores!
Preparados para o último FAQ do ano?
Confira, neste artigo, as dúvidas que recebi nesse último semestre de 2015, desde que fiz o último FAQ. Agora é torcer para que os mecanismos de busca indexem este artigo para ajudar programadores que estiverem com dúvidas semelhantes! 🙂

 

 

(As 3 perguntas a seguir se referem ao artigo “[Delphi] Dicas do componente DBGrid“)

Qual o procedimento para alterar apenas a cor de uma coluna na DBGrid? Por exemplo, fazer com que a coluna referente à data de vencimento fique de uma cor específica em caso de atraso.
Para alterar a cor de uma única coluna é preciso envolver o código de pintura em uma função IF que identifique a coluna. Utilizando o cenário que você mencionou, sobre a data de vencimento, essa seria a codificação no evento OnDrawColumnCell da DBGrid:

if AnsiUpperCase(Column.FieldName) = 'DATAVENCIMENTO' then
begin
  // se o pagamento estiver em atraso
  if ClientDataSet.FieldByName('Situacao').AsString = 'ATRASO' then
  begin
    // pinta de vermelho
    DBGrid1.Canvas.Font.Color := clRed;
    DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
  end;
end;

 

Existe uma forma de aumentar a altura da linha da DBGrid?
Sim, é possível. Para isso, é preciso criar um “Hack” da classe TDBGrid (ou “class cracker”) e alterar o valor da propriedade DefaultRowHeight:

type
  TDBGridHack = class(TDBGrid);
 
...
 
TDBGridHack(DBGrid1).DefaultRowHeight := 30;

Porém, quando a DBGrid recebe os dados, a altura da linha volta ao tamanho padrão. Há 2 alternativas para tratar esse comportamento:
1) Colocar o código de alteração da altura da linha no evento AfterOpen do DataSet. Dessa forma, toda vez que o DataSet for aberto e a DBGrid receber os dados, o tamanho da linha será alterado;
2) Criar um componente herdado da classe TDBGrid (por exemplo, TMinhaDBGrid) e adicionar os comportamentos desejados, embora essa opção demande um pouco mais de tempo.

 

Uso o componente TADOTable e tentei aplicar o exemplo de ordenação ao clicar no título da coluna, mas recebo um erro informando que o método “AddIndex” não existe.
Para os componentes do conjunto ADO, realmente há uma diferença. Ao invés de utilizar a propriedade IndexName, deve-se trabalhar com a propriedade Sort:

var
  sOrdenacao: string;
  i: smallint;
begin
  // retira a formatação em negrito de todas as colunas
  for i := 0 to DBGrid1.Columns.Count - 1 do
    DBGrid1.Columns[i].Title.Font.Style := [];
 
  // configura a ordenação ascendente ou descendente
  if ADOTable1.Sort = Column.FieldName + ' ASC' then
    sOrdenacao := Column.FieldName + ' DESC'
  else
    sOrdenacao := Column.FieldName + ' ASC';
 
  // formata o título da coluna em negrito
  Column.Title.Font.Style := [fsBold];
 
  // atribui a ordenação selecionada
  ADOTable1.Sort := sOrdenacao;
 
  ADOTable1.First;
end;

 

(As 3 perguntas a seguir se referem ao artigo “[Delphi XE] Envio de e-mail com componentes Indy“)

Ao tentar enviar o e-mail pela segunda vez consecutiva, ocorre a mensagem: “Error creating SSL context”.
É preciso liberar a DLL após o envio da mensagem para evitar este erro. Declare a unit IdSSLOpenSSL na uses do formulário:

uses
  IdSSLOpenSSL;

Em seguida, após o envio do e-mail, inclua a seguinte instrução (recomendo colocá-la no Finally):

UnLoadOpenSSLLibrary;

 

Gostaria de saber se essa rotina de envio de e-mails funciona com o Hotmail.
Sim! Para enviar mensagens com uma conta do Hotmail, basta configurar o componente TIdSMTP com os seguintes valores:

IdSMTP.UseTLS := utUseExplicitTLS;
IdSMTP.AuthType := satDefault;
IdSMTP.Port := 587;
IdSMTP.Host := 'smtp.live.com';
IdSMTP.Username := 'usuario@hotmail.com';
IdSMTP.Password := 'senha';

Não se esqueça também de mudar o endereço do remetente no componente TIdMessage:

IdMessage.From.Address := 'usuario@hotmail.com';

 

No momento da autenticação, aparece uma mensagem solicitando que eu faça login diretamente no browser. Como resolver isso?
Muita gente está recebendo essa mensagem que, na verdade, é um procedimento de segurança do Gmail. Esse link poderá ajudar: https://support.google.com/mail/answer/78754

 

(Referente aos artigos sobre Funcionalidade de Atualização Automática pelo Delphi)
Para executar scripts em um banco Firebird, o que você aconselharia: utilizar o isql ou um aplicativo externo?
Bom, eu optaria pelo isql utilizando o parâmetro “-o” para gerar um arquivo de log, como no exemplo abaixo:

isql Banco.fdb -m -b -i Script.sql -q -u SYSDBA -p masterkey -o ArquivoLog.txt

Após a execução do script, é possível ler o arquivo de log e verificar se houve algum erro. Outra alternativa é utilizar o método CreateProcess para exibir o resultado das instruções do script na tela do usuário.

 

(Referente ao artigo “Práticas de otimização em Banco de Dados“)
Para aumentar a performance no ambiente de produção dos meus clientes, passei a utilizar tabelas temporárias e alimentá-las via Stored Procedures. Criar Views seria uma alternativa?
Views são adequadas para trazer dados de diferentes tabelas, formando uma visão de dados personalizada, evitando, assim, vários inner joins a cada consulta. Para melhorar o desempenho em tabelas que contém uma grande massa de dados, sugiro trabalhar com índices (indexes) para manter os dados devidamente ordenados, agilizando as buscas. Clique aqui para acessar um site interessante sobre indexação.

 

(Referente ao artigo “Dicas para o desenvolvimento de um software – Parte 3“)
Não entendi muito bem o conceito de Orientação a Objetos. Muitos usam o exemplo da classe “Pessoa”, mas, mesmo assim, não compreendi o conceito.
O exemplo da classe “Pessoa” é clássico no cenário didático da Programação Orientada a Objetos. Por exemplo, vamos supor que a aplicação irá trabalhar com Pessoas Físicas e Pessoas Jurídicas. Esses dois tipos de pessoas compartilham vários atributos em comum, como ID, Nome, Documento (CPF ou CNPJ), Endereço, Bairro, Cidade, UF, etc. Sendo assim, criamos a classe “Pessoa”, declarando estes atributos em comum, e depois herdamos a classe “Pessoa Física” e “Pessoa Jurídica”, declarando atributos mais específicos, como, por exemplo, a razão social para pessoa jurídica e data de nascimento para pessoa física. Só aqui já alcançamos dois pilares: abstração e herança. Não será necessário duplicar os atributos em ambas as classes, pois ela já estará contida na classe base.
Porém, sabemos que o documento é diferente para as duas classes. CPF é para pessoa física e CNPJ é para pessoa jurídica. É aqui que entra o polimorfismo. A classe “Pessoa” (classe base) terá um método chamado “ValidarDocumento”, mas quem irá implementá-lo são as classes filhas. A classe “Pessoa Física” irá validar o CPF, enquanto a “Pessoa Jurídica” irá validar o CNPJ. Observe que existirá apenas uma declaração de método, mas com implementações diferentes.
A respeito do encapsulamento, recomendo a leitura de um artigo que escrevi no início de 2014, disponível neste link.

 

(Referente ao artigo “Dicas para o desenvolvimento de um software – Parte 8“)
Quais tipos de estatísticas devem ser apresentados no software?
Bom, as estatísticas que um desenvolvedor deve disponibilizar na aplicação são aquelas que agregam valor para o cliente, ou seja, estatísticas que o ajudarão na tomada de decisões, ações estratégicas e redução de custos. De nada adianta prover relatórios e gráficos que nunca serão utilizados.
Existem vários tipos de estatísticas, mas cada uma fornece uma perspectiva específica de dados, atendendo diferentes necessidades. Portanto, a apresentação de estatísticas relevantes é um quesito que deve ser alinhado com o cliente. Se possível, o Product Owner pode apresentar vários protótipos e alternativas para levantar, junto ao cliente, quais serão as melhores opções. O efeito desse alinhamento é o desenvolvimento de funcionalidades que realmente atenderão as expectativas dos usuários, gerando uma maior satisfação de ambas as partes.

 

Quais princípios que um programador deveria seguir para elaborar um bom projeto?
Pergunta interessante! Eu diria que o desenvolvedor deve seguir as seguintes diretrizes na concepção de um novo projeto:

  • Desenvolver o projeto em um padrão que sempre possa receber novas funcionalidades sem comprometer o funcionamento existente;
  • Construir o projeto em uma arquitetura sustentável, explorando os pilares da Orientação a Objetos e da Engenharia de Software;
  • Empregar o conceito de abstração para modelar as classes de forma que um novo comportamento seja uma herança ao invés de uma nova condição IF;
  • Padronizar a escrita do código-fonte utilizando as práticas de Clean Code;
  • Elaborar testes unitários para garantir que o projeto se mantenha funcional a cada release.

 

Existe alguma função que, por exemplo, quando dois ou mais usuários do sistema tentarem gravar no mesmo milésimo de segundo, deixe o sistema em espera aguardando até que o banco de dados consiga armazenar uma das informações? Seria como se o sistema deixasse na fila de espera por alguns segundos para não correr risco de duplicidade nos registros quando mais de um usuário estiver gravando registros ao mesmo tempo.
Bom, acredito que você esteja se referindo à chave primária da tabela, na qual não pode se repetir, certo?
Essa é uma questão que é tratada de diferentes formas. Uma delas é por meio de Triggers no banco de dados. Este é um recurso que funciona como um “gatilho” quando determinado evento acontece em uma tabela, como, por exemplo, a inserção de um novo registro (On Before Insert). Sendo assim, pode-se criar uma Trigger para gerar um novo código antes que o registro seja inserido. Mesmo que dois usuários gravem registros no mesmo milésimo de segundo, o banco de dados irá analisar as transações e disparar essa Trigger para cada um deles em sequência.
Há também uma forma de controlar essa concorrência pela aplicação. Porém, antes de explicá-la, vale fazer uma observação: muitos desenvolvedores cometem o erro de gerar o novo valor da chave primária (código do cliente, por exemplo), durante a inserção do novo registro. Logo, se dois usuários iniciarem a inserção de dois registros ao mesmo tempo, o mesmo código será gerado, causando a violação de chave primária. A minha recomendação é atribuir o valor da chave primária antes da gravação do registro, ou seja, ao persistir os dados no banco com o Post e ApplyUpdates. Para isso, consulte o último código da tabela e incremente 1 unidade, atribuindo-o imediatamente ao campo do DataSet. Caso dois usuários insiram dois registros simultaneamente, a possibilidade de duplicidade será bastante reduzida.

 

Qual a diferença entre variável e constante?
A maior diferença entre variáveis e constantes são que essas últimas não permitem que o valor seja modificado.
Já me deparei com situações em que valores de variáveis foram indevidamente alterados durante a execução da aplicação, gerando inconsistências. Ao trocar essas instâncias por constantes, o problema foi solucionado.
O uso de constantes também expressa que o valor é fixo, e não variável. Em um ambiente colaborativo de desenvolvimento, essa informação pode ajudar a compreender melhor a regra de negócio.
Além disso, a utilização de constantes no projeto agiliza, e muito, a atividade de manutenção, sem contar na melhoria da expressividade do código. Quanto mais o código puder “falar por si só”, melhor será a compreensão.
No caso de propriedades científicas e matemáticas, que possuem valores imutáveis, ainda recomendo a utilização de constantes, já que nem todos os desenvolvedores têm conhecimento dos valores dessas propriedades. Por exemplo, ler a constante “nVALOR_PI” é mais compreensível do que o magic number 3,14.

 

Muitos profissionais recomendam a utilização da nuvem para backup de bancos de dados. Sempre utilizei estações na rede para backups e nunca tive problemas.
Utilizar computadores da rede para gravar backups é um método aceitável. Porém, imagine que aconteça um problema com essas estações, como um dano grave no HD. Todos os backups seriam perdidos. A vantagem de utilizar a nuvem é justamente evitar este risco, pois, mesmo se houver uma falha em todos os computadores da empresa, os backups continuariam salvos.
Para essa propósito, pode-se utilizar um servidor web para armazenar um espelho do banco. Ao final de cada dia, o banco de dados é transferido para este repositório como uma forma de cópia de segurança. Se o arquivo atingir centenas de MegaBytes, experimente compactá-lo antes de enviar. E mais uma dica: agende um horário propício para fazer o envio (durante a madrugada, por exemplo), para não prejudicar a utilização da aplicação.

 

Quais são os cargos comuns em uma fábrica de software?
Já tive a oportunidade de trabalhar em três empresas de desenvolvimento e observei bem os papéis e funções existentes em uma equipe.
O profissional que conhece as regras de negócio e o segmento do cliente é chamado de Analista de Negócio. As especificações de requisitos, considerando as características técnicas do projeto, são documentadas pelo Analista de Sistemas. As soluções técnicas, por sua vez, geralmente são elaboradas pelos Projetistas. Por fim, os Programadores implementam as funcionalidades e os Analistas de Testes garantem a qualidade da entrega. Observe que é um fluxo de atividades bem definido.
Só a título de conhecimento, empresas que utilizam Desenvolvimento Ágil definem papéis especiais, como Product Owner e Scrum Master, nos quais podem ser comparados, respectivamente, a um Analista de Negócios e um Líder da equipe de desenvolvimento.

 

Até mais, pessoal! 


Confira também os outros FAQs:

FAQ 01 | FAQ 02 | FAQ 03 | FAQ 04 | FAQ 05 | FAQ 06 | FAQ 07FAQ 08 | FAQ 09


 

Compartilhe!
Share on FacebookTweet about this on TwitterShare on LinkedInShare on Google+Pin on PinterestEmail this to someone

2 comentários

  1. Muito bom, seu site é uma verdadeira enciclopédia de Delphi, e o melhor de tudo, com constante atualizações.
    Parabéns, continue assim.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha o campo abaixo * Time limit is exhausted. Please reload CAPTCHA.