Escolar Documentos
Profissional Documentos
Cultura Documentos
24
Agora que o formulário está criado e suas principais propriedades estão configuradas,
vamos trabalhar o ambiente de dados, incluindo a tabela de produtos.
6. Após adicionar o código acima, feche a janela de edição de código e clique com o
botão direito no fundo do ambiente de dados e escolha Add CursorAdapter... O
builder de CursorAdapter será acionado. Informe as seguintes propriedades na
primeira parte do builder:
24
24
10. Para finalizar, você ainda deve substituir o código do evento init do cursoradapter
produtos pelo seguinte código:
local llReturn
do case
case not pemstatus(This, '__VFPSetup', 5)
This.AddProperty('__VFPSetup', 0)
case This.__VFPSetup = 2
This.__VFPSetup = 0
return
endcase
llReturn = dodefault()
24
this.DataSource = CREATEOBJECT("ADODB.RecordSet")
* 3, AdUseClient
this.DataSource.CursorLocation = 3
* 3, adLockOptmistic
this.DataSource.LockType = 3
This.DataSource.ActiveConnection = This.Parent.oConnection
if This.__VFPSetup = 1
This.__VFPSetup = 2
endif
return llReturn
12. O próximo passo agora é configurar a tabela do formulário (Grid) para exibir as
colunas formatadas da forma como queremos. Primeriamente clique no objeto
grdLista e defina a propriedade ColumnCount = 5. Isso fará com que a grade fique
ajustada para 5 colunas.
13. Agora devemos ajustar cada coluna individualmente. Para tal, segure a tecla CTRL
e clique sobre a grade. Depois, clique sobre o cabeçalho da coluna, defina o texto
descritivo para cada cabeçalho conforme tabela abaixo:
Coluna Título do Cabeçalho
1 Cód. Produto
2 Descrição do Produto
3 Estoque
4 Unidade
5 Valor Unitário
14. Agora defina as demais propriedades de cada coluna conforme a próxima tabela.
Para definir as propriedades da coluna (não do cabeçalho) você clica com o mouse
em cima do controle interno, na primeira linha abaixo do cabeçalho.
Coluna Propriedades a alterar
1 ControlSource = produtos.id_produto
Width = 87
2 ControlSource = produtos.descricao_produto
Width = 331
3 ControlSource = produtos.qtd_estoque
InputMask
Width = 106
4 ControlSource = produtos.unidade
Width = 83
5 ControlSource = produtos.valor_unitario
InputMask = 99,999.99
Width = 106
24
15. Definidas todas as propriedades, o formulário de navegação para produtos estará
pronto, conforme a figura a seguir:
A primeira etapa para o cadastro de produtos está realizada. O próximo passo é criar o
formulário para inclusão e edição de produtos. Para tal, siga os passos:
2. Assim que a janela Form Designer estiver aberta com o novo formulário criado,
defina as seguintes propriedades:
Propriedade Valor
Caption Cadastro de Produto
Height 362
Name Produtos
Width 553
Campo_sequencial Id_produto
24
Comandoprimeirofoco thisform.txtDescricao_produto.SetFocus()
4. Ao abrir o ambiente de dados, clique duplo no seu fundo para que seja aberto o
editor de programas. Adicione o código a seguir ao evento BeforeOpenTables():
SET MULTILOCKS ON
* Estabelece a conexão
This.oConnection.Open()
24
24
24
* 3, AdUseClient
THIS.DATASOURCE.CursorLocation = 3
* 3, adLockOptmistic
THIS.DATASOURCE.LockType = 3
THIS.DATASOURCE.ActiveConnection = THIS.PARENT.oConnection
RETURN llReturn
10. Agora que o acesso a dados está completamente configurado, chega a hora de
posicionarmos os controles no formulário. Para poupar trabalho na associação dos
controles com os campos da tabela, você pode simplesmente arras os campos do
ambiente de dados para a área de desenho do formulário. Você deve posicionar os
campos conforme mostra a próxima figura, sendo que, se necessário você deve
substituir alguns controles.
24
11. O retângulo que está em volta dos campos é um objeto Shape. Após inseri-lo você
deve enviá-lo para trás dos demais objetos, senão os objetos não recebem o foco
adequadamente. Para enviá-lo para trás, clique sobre o objeto Shape, vá no menu
Format / Send to back.
12. Após o posicionamento dos campos em seus devidos locais, faz-se necessário
também a definição da ordem de tabulação dos mesmos, para que fique agradável
de se trabalhar. Para definir a ordem de tabulação, clique no menu View / Tab
order.
24
13. Observando na figura acima, você pode notar que o campo id_produto encontra-se
em uma cor diferente. Isto se deve ao fato de que o mesmo está desabilitado para
edição. É apenas leitura e sua propriedade Enabled está com o valor .F.. Sempre
defina os campos que o usuário não deve mexer com a propriedade Enabled = .F..
14. Para finalizar o formulário de produtos, devemos fazer a crítica geral para os dados
informados no formulário. Para tal, vamos inserir o seguinte código no método
Criticar() do formulário:
SELECT (thisform.cTabela)
WITH thisform
IF VAZIO(descricao_produto)
MESSAGEBOX("Informe a descrição do produto!";
,0+48,_Screen.Caption)
.txtDescricao_produto.SetFocus()
RETURN .F.
ENDIF
IF VAZIO(unidade)
MESSAGEBOX("Informe a unidade do produto!";
,0+48,_Screen.Caption)
.cboUnidade.SetFocus()
RETURN .F.
ENDIF
IF VAZIO(valor_unitario)
MESSAGEBOX("Informe o valor unitário do produto!";
,0+48,_Screen.Caption)
.txtValor_unitario.SetFocus()
RETURN .F.
ENDIF
24
ENDWITH
15. Podemos dizer que a grosso modo nosso formulário está funcional.
Considero de extrema importância lembrar que o objetivo deste curso não é ensinar
a desenvolver um sistema de controle de estoques ou financeiro, mas sim de
ensinar técnicas de desenvolvimento em Visual FoxPro. Por este motivo, não entramos em
detalhes peculiares ao sistema, mas nos atemos aos recursos da linguagem para a
execução de tarefas que estão envolvidas nesse tipo de sistema, mostrando-lhe o caminho
a seguir. Cabe a você como desenvolvedor e artista que é, usar tudo o que for necessário
e que estiver no seu conhecimento para criar aplicações concisas e agradáveis aos olhos
dos usuários. Mais importante que uma interface bonita é uma interface que funcione. No
entanto, se for possível unir as duas, então será perfeito. Use sempre as máscaras de
formatação nos campos, induzindo sempre o usuário a acertar. Critique sempre que
houver necessidade a fim de não deixar que uma informação necessária seja deixada sem
preencher.
24
Construindo o formulário de navegação de Compras
Como você já percebeu, para cada tabela que queremos editar/incluir dados, de acordo
com nossas classes projetadas, precisamos criar primeiramente um formulário de
navegação. A partir deste formulário é que lançamos o formulário de edição.
24
5. Vá para a aba de número 2. Data Access e defina os campos do cursor, digitando a
expressão a seguir no Select Command:
SELECT compras.id_compra, compras.data_registro,
compras.data_nf, compras.numero_nf,
cliente_fornecedor.nome_razao AS nome_fornecedor
FROM compras
LEFT JOIN cliente_fornecedor
ON compras.id_fornecedor = cliente_fornecedor.codigo
6. Você pode digitar o comando Select acima sem se preocupar com a formatação,
atentando apenas para a grafia correta dos nomes dos campos e tabelas. O
comando acima possui uma sintaxe um pouco diferente do que já vimos até o
momento, pois nele fazemos uma junção (JOIN) das tabelas Compras e
Cliente_fornecedor. LEFT JOIN cliente_fornecedor quer dizer, junte-se à tabela da
esquerda da expressão de relacionamento, a tabela cliente_fornecedor. A
expressão de relacionamento é:
ON compras.id_fornecedor = cliente_fornecedor.codigo
8. Sempre que você desejar que campos de uma ou mais tabelas apareçam em uma
consulta e houver uma expressão de relacionamento entre as tabelas você pode
usar JOIN para estabelecer um relacionamento. Para maiores detalhes consulte o
tópico Join Conditions for Tables, Queries, and Views no help do Visual FoxPro.
9. Ok, uma vez definido o comando Select, clique no botão Build imediatamente acima
da caixa de texto Schema, a fim de que seja construída a expressão do
CursorSchema.
10. Defina as demais propriedades do CursorAdapter e então clique OK. Veja a figura
23.24:
24
this.oCommand.ActiveConnection = this.Parent.oConnection
12. Agora feche a janela de código e clique duplamente na área do ambiente de dados
para adicionarmos o seguinte código ao evento BeforeOpenTables():
SET MULTILOCKS ON
24
* Define que o tipo de acesso será por ADO
this.DataSourceType = "ADO"
* Estabelece a conexão
This.oConnection.Open()
13. Como você já sabe, os dois códigos acima estabelecem a conexão com o banco de
dados e faz o seu compartilhamento. Muito bem, agora que os dados estão
definidos, já podemos formatar nosso grid. Feche o ambiente de dados.
16. Agora associe cada coluna do grid com seu respectivo campo na ordem que eles
aparecem na tabela.
cCampo = id_compra
cTabela = compras
formularioedicao = compras
19. Ao final, o formulário deverá ter uma aparência mais ou menos assim:
24
Os formulários que construímos até o presente momento usam tabelas solitárias solitários,
ou seja, estão desconectados de quaisquer outras tabelas que não seja a tabela principal
em edição. Entretanto, muito comumente necessitamos de criar formulários de uma
complexidade relativamente maior onde várias tabelas precisam ser envolvidas e de
alguma forma relacionam-se entre si.
Num cenário básico onde estaremos construindo um formulário para a entrada de produtos
(compra), envolveremos a tabela principal compras, a tabela filha compra_itens, e as
tabelas estrangeiras produtos e cliente_fornecedores.
24
próxima da arquitetura cliente/servidor, desenvolvemos um formulário específico que será
responsável por pesquisar dados em qualquer tabela estrangeira, e um controle disparador
que acoplaremos em nossos formulários, preencheremos algumas propriedades e pronto!
Nosso formulário de pesquisa estrangeira saberá lidar com qualquer tabela.
Uma coisa é certa, desenvolver aplicativos em Visual FoxPro é uma tarefa um tanto
empolgante e bastante produtivo quando aplicamos os conceitos de programação
orientada a objetos que até o momento estamos empregando. Um belo exemplo disto são
os formulários de navegação e de edição onde seria possível criar dezenas deles num
único dia, e sem muita exaustão.
Embora a classe esteja pronta para a maioria dos tipos de cadastros algumas vezes
precisaremos especializar mais ainda o formulário incluindo novos métodos, propriedades
adicionais e talvez até incluir outros controles como botões de comandos, chamar
formulários adicionais, etc.
Chega então o momento em que teremos que criar formulários para a entrada (compra) e
saída (venda) de produtos. Nesse tipo de formulário há certa complexidade devido ao fato
que envolve várias tabelas. Por exemplo, num processo de compra de produtos, teríamos
no mínimo as tabelas de compras, compra_itens, produtos, cliente_fornecedores
envolvidas no processo onde as três primeiras estariam sendo usadas para incluir/alterar
registros e a quarta apenas para consulta.
24
principal para permitir que a nova regra seja codificada com eficiência. Acredite-me, tais
situações são bem mais freqüentes do que gostaríamos.
Para muitos programadores iniciantes é nesse ponto que se perdem, ou seja, não
conseguem manter o elo das informações e acabam produzindo softwares inconsistentes.
No Visual FoxPro tudo é muito tranqüilo. Podemos manipular dezenas de tabelas sem que
o ponteiro se perca e venha causar confusão como em certas linguagens xBase.
É importante lembrar que para obter o melhor resultado de programação sobre as tabelas
envolvidas e não ter nenhum problema com falha na gravação dos dados, devemos tomar
o cuidado de definir muito bem os atributos dos CursorAdapter’s envolvidos de maneira
que, aqueles que vão ter informações inseridas ou atualizadas estejam devidamente
configurados para enviar as atualizações, bem como os pares de campos atualizáveis, etc.
Tabela de Compras
Name Compras
Alias Compras
Data Source Type ADO
24
Select Command select compras.id_compra, compras.data_registro,
compras.id_fornecedor, compras.data_nf,
compras.numero_nf from compras
Schema ID_COMPRA N(7, 0), DATA_REGISTRO D, ID_FORNECEDOR
N(7, 0), DATA_NF D, NUMERO_NF C(10)
Number of tecords All
to tetch at a time
Maximum number All
of records to fetch
Buffer mode Optmistic row buffering
override
Send Updates Marcar (sim)
Auto update Marcar (sim)
Tables Compras
KeyField ID_COMPRA
Campos Todos
Atualizáveis
SQL WHERE Key fields only
Clause
Tabela de Compras_itens
Name Compras_itens
Alias Compras_itens
Data Source Type ADO
Select Command select compras_itens.id_produto,
produtos.descricao_produto, compras_itens.quantidade,
compras_itens.valor_unitario,
compras_itens.valor_total_item,
compras_itens.id_compra, compras_itens.id_temp from
compras_itens inner join produtos on
compras_itens.id_produto=produtos.id_produto
Schema ID_PRODUTO N(7, 0), DESCRICAO_PRODUTO C(40),
QUANTIDADE N(8, 3), VALOR_UNITARIO N(8, 2),
VALOR_TOTAL_ITEM N(11, 2), ID_COMPRA N(7, 0), ID_TEMP
C(10)
Number of tecords All
to tetch at a time
Maximum number All
of records to fetch
Buffer mode Optmistic row buffering
override
Send Updates Marcar (sim)
Auto update Marcar (sim)
Tables Compras_itens
KeyField ID_TEMP
Campos Todos, exceto DESCRICAO_PRODUTO
Atualizáveis
SQL WHERE Key fields only
Clause
24
Tabela de Fornecedores
Name Fornecedores
Alias Fornecedores
Data Source Type ADO
Select Command select cliente_fornecedor.codigo,
cliente_fornecedor.nome_razao from cliente_fornecedor
Schema CODIGO N(7, 0), NOME_RAZAO C(40)
Number of tecords All
to tetch at a time
Maximum number All
of records to fetch
Buffer mode Optmistic row buffering
override
Send Updates Desmarcado
Auto update Desmarcado
Tables
KeyField
Campos Nenhum
Atualizáveis
SQL WHERE Key fields only
Clause
Tabela de Produtos
Name Produtos
Alias Produtos
Data Source Type ADO
Select Command select produtos.id_produto,
produtos.descricao_produto, produtos.valor_unitario,
produtos.qtd_estoque from produtos
Schema ID_PRODUTO N(7, 0), DESCRICAO_PRODUTO C(40),
VALOR_UNITARIO N(11, 2), QTD_ESTOQUE N(11, 3)
Number of tecords All
to tetch at a time
Maximum number All
of records to fetch
Buffer mode Optmistic row buffering
override
Send Updates Marcado
Auto update Marcado
Tables Produtos
KeyField ID_PRODUTO
Campos QDT_ESTOQUE
Atualizáveis
SQL WHERE Key fields only
Clause
24
4. Não se esqueça que o código do evento BeforeOpenTables() do ambiente de dados
e do evento Init() de cada CursorAdapter é obrigatório de se acrescentar, caso
contrário o cursor não será preenchido. Como já repetimos esta tarefa por várias
vezes anteriormente, julgo que você já seja capaz de executá-la sem que eu a
descreva nesse momento.
6. A tabela a seguir lhe traz a lista das propriedades mais importantes para cada
controle do formulário acima.
Propriedades dos controles contidos no formulário
24
DisabledForeColor = 0,0,0
Enabled = .F.
Height = 23
Left = 36
Name = txtId_compra
TabIndex = 10
Top = 54
Width = 84
24
Enabled = .F.
Height = 23
Left = 314
Name = txtNomeFornecedor
TabIndex = 17
Top = 54
Width = 245
Width = 45
24
24
Top = 316
Width = 106
Width = 106
Coluna 1 Header1:
Caption = Código
Column1:
ControlSource = compras_itens.id_produto
Width = 84
Coluna 2 Header1:
Caption: Descrição do Produto
Column2:
ControlSource = compras_itens.descricao_produto
Width = 290
Coluna 3 Header1:
Caption: Quantidade
Column3:
ControlSource = compras_itens.quantidade
24
Width = 73
Coluna 4 Header1:
Caption: Valor Unitário
Column4:
ControlSource = compras_itens.valor_unitario
InputMask = 999,999.99
Width = 92
Coluna 5 Header1:
Caption: Total do Item
Column5:
ControlSource = compras_itens.valor_total_item
InputMask = 999,999.99
Width = 92
DIMENSION this.aCampos[2,5]
this.aCampos[1,1] = "Nome do Fornecedor"
this.aCampos[1,2] = "nome_razao"
this.aCampos[1,3] = 50
this.aCampos[1,4] = "!"
this.aCampos[1,5] = ""
this.aCampos[2,1] = "Código Fornecedor"
this.aCampos[2,2] = "codigo"
this.aCampos[2,3] = 6
this.aCampos[2,4] = "L"
this.aCampos[2,5] = "999999"
9. Assim que os controles estiverem posicionados, meio caminho terá sido percorrido.
Vem então a hora da verdade onde temos que inserir códigos para dar vida aos
controles. Vamos começar adiciona o código dos botões Incluir Item, Alterar item e
Excluir Item. A tabela abaixo lista o código de cada um:
24
ENDIF
ENDIF
thisform.cntEditarItem.cntProduto.txtPe.Value = ;
compras_itens.id_produto
thisform.cntEditarItem.txtDescricao_produto.Value = ;
compras_itens.descricao_produto
thisform.cntEditarItem.txtQuantidade.Value = ;
compras_itens.quantidade
thisform.cntEditarItem.txtValor_unitario.Value = ;
compras_itens.valor_unitario
thisform.cntEditarItem.txtValor_total_item.Value = ;
compras_itens.valor_total_item
24
* Exibe o controle de inclusão/edição de itens
thisform.cntEditarItem.Visible = .T.
thisform.cntEditarItem.cntProduto.txtPe.SetFocus()
ENDIF
* Apaga o item
DELETE
TABLEUPDATE(.T.,.T.,"compras_itens")
* Atualiza os itens
thisform.dataenvironment.compras_itens.CursorRefresh()
ENDIF
ELSE
MESSAGEBOX("Não existem itens a excluir";
,0+48,_Screen.Caption)
ENDIF
10. O código do evento click de cada botão de comando para incluir e alterar itens faz
referência a um controle que ainda não existe no formulário, sendo este
cntEditarItem. Trata-se de um objeto container que hospedará dentro de si alguns
outros controles, conforme vimos na figura a seguir:
11. Observe na figura acima que há alguns controles contidos no objeto cntEditarItem.
São alguns objetos Label, TextBox e CommandButton. Talvez você esteja se
perguntando porque em vez de criar um container não criamos um outro formulário
para abrigar estes elementos. Bem, particularmente prefiro esse tipo de edição para
registros filhos pois torna-se mais fácil o gerenciamento de sessões de dados no
Visual FoxPro. Como trabalhamos na maioria das vezes com sessões privadas de
dados, se editássemos em uma nova janela quando incluíssemos o registro o Visual
FoxPro automaticamente finaliza a transação para a sessão de formulário que está
24
sendo fechada, tornando mais difícil o gerenciamento de transações no banco de
dados, fazendo-se necessárias algumas gambiarras para garantir que não fiquem
registros órfãos nas tabelas filhas.
24
24
Enabled = .F.
Height = 23
IntputMask = 999,999.99
Left = 581
Name = txtValor_unitario_item
Top = 30
Width = 92
14. Após inserir todos os controles, edite o controle cntProduto e adicione o seguinte
código ao evento LostFocus do :
24
this.aCampos[4,5] = "999,999.999"
15. Adicione ainda ao controle txtPe contido no controle cntProduto o seguinte código
ao seu evento LostFocus():
LOCAL lcCursor
lcCursor = this.Parent.tabela_local
IF USED(lcCursor)
IF RECCOUNT(lcCursor) > 0
this.parent.Parent.txtValor_unitario.Value ;
= &lcCursor..valor_unitario
this.Parent.Parent.txtDescricao_produto.Value ;
= &lcCursor..descricao_produto
ENDIF
ENDIF
18. Agora temos um código um pouco maior que é usado no evento Click() botão
Gravar Item:
IF VAZIO(this.Parent.cntProduto.txtPe.Value)
MESSAGEBOX("Informe o código do produto!";
,0+48,_screen.Caption)
this.Parent.cntProduto.txtPe.SetFocus()
RETURN
ENDIF
IF VAZIO(this.Parent.txtQuantidade.Value)
MESSAGEBOX("Informe a quantidade do produto!";
,0+48,_screen.Caption)
this.Parent.txtQuantidade.SetFocus()
RETURN
24
ENDIF
IF VAZIO(this.Parent.txtValor_unitario.Value)
MESSAGEBOX("Informe o valor unitário do produto!";
,0+48,_screen.Caption)
this.Parent.txtValor_unitario.SetFocus()
RETURN
ENDIF
SELECT compras_itens
IF thisform.operacao_item = "NOVO"
APPEND BLANK
GATHER MEMVAR
IF TABLEUPDATE(.T.,.T.,"compras_itens")
thisform.DataEnvironment.produtos.SelectCmd = lcSelect
IF thisform.DataEnvironment.produtos.CursorFill(.t.,.f.)
SELECT produtos
* Calcula estoque
lnNova_quantidade = produtos.qtd_estoque + m.quantidade
ENDIF
ENDIF
ENDIF
IF thisform.operacao_item = "EDITAR"
GATHER MEMVAR
IF TABLEUPDATE(.T.,.T.,"compras_itens")
24
thisform.DataEnvironment.produtos.SelectCmd = lcSelect
IF thisform.DataEnvironment.produtos.CursorFill(.t.,.f.)
SELECT produtos
* Calcula estoque
lnNova_quantidade = produtos.qtd_estoque + lnDiferenca
ENDIF
ENDIF
ENDIF
ENDIF
19. O código acima faz duas tarefas distintas. Uma delas é a de ler os valores contidos
em cada um dos controles, criticá-los e gravá-los na tabela de itens da compra. A
segunda tarefa é a de atualizar o estoque de produtos. Ou seja, se foi incluído um
produto com X quantidades, ele vai lá no estoque e incrementa a quantidade X para
aquele produto. Se houver alteração na quantidade, ele verifica e processa o
estoque também. Outro fato importante a notar no procedimento que adotamos para
a inclusão/edição de itens da compra é que os controles não estão ligados à tabela.
Nós apenas os utilizamos para fazer a leitura e depois os gravamos manualmente
na tabela. Esta é outra técnica muito usada e com certeza você fará uso dela por
muitas vezes em outros sistemas.
24
this.Parent.txtQuantidade.Value = 0.000
this.Parent.txtValor_unitario.Value = 0.00
this.Parent.txtValor_total_item.Value = 0.00
21. Nosso formulário já possui forma e algumas funcionalidades. Vamos então finalizá-
lo acrescentando mais dois métodos novos e escrevendo código em um já
existente. Vamos começar criando um novo método chamado AtualizarItens(). Para
tal, vá no menu Form e escolha New Method. Informe como nome AtualizarItens e
clique em OK. Após, localize o novo método criado na janela de propriedades e
adicione o código ao mesmo:
thisform.grdCompras_itens.RecordSource = ""
WITH thisform.dataenvironment.compras_itens
.SelectCmd = lcSelect
* Executa a consulta
.CursorFill(.T.,.F.)
ENDWITH
IF USED("compras_itens")
24
lcTalk = SET("Talk")
lcConsole = SET("Console")
CALCULATE SUM(compras_itens.valor_total_item) ;
ALL TO thisform.txtVAlor_total.Value
GO TOP
* Associa o cursor gerado com o grid de itens da compra
thisform.grdCompras_itens.RecordSource = "compras_itens"
SELECT (thisform.cTabela)
ENDIF
22. O código acima garante que o grid de itens esteja exibindo as informações corretas
sobre os itens da compra. Este é um típico relacionamento do tipo um-para-n em
aplicações cliente/servidor, sendo que o lado um do relacionamento é a tabela
compras e o lado n é a tabela compras_itens.
lnTotal = (thisform.cntEditarItem.txtQuantidade.Value * ;
thisform.cntEditarItem.txtValor_unitario.Value)
thisform.cntEditarItem.txtValor_total_item.Value = lnTotal
thisform.Refresh
24. O método acima é usado apenas para calcular o valor total do item quando este
está em edição/inclusão.
24
25. Agora localize o método ConfigurarRelacionamentos() do formulário compras e
adicione o código a seguir ao mesmo, que será responsável por definir o
relacionamento entre compras e fornecedores:
26. E finalmente, para fechar com chave de ouro, adicione o seguite código ao método
RealizarOperacao() do formulário compras:
Muito bem, agora é com você. Faça os testes, tire suas próprias conclusões e altere à
vontade para entender o mecanismo.