Práticas que facilitam programar Clipper/Harbour
Moderador: Moderadores
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Lembrando: isso tem a ver com deixar o fonte mais claro, mas também com usar a compilação com -w3 -es2
Isso é aproveitar o compilador como um ajudante pra conferir seu fonte.
De qualquer jeito, é melhor evitar o uso de variável pública.
Na declaração de variável pública ou private, é algo como dizer ao compilador: é possível que esta variável tenha sido criada em algum lugar, pra alguma coisa, ou vai ser usada em algum lugar.
Já a declaração de variável local, é algo como dizer ao compilador: vou usar esta variável aqui.
Então o compilador pode ajudar ainda mais na checagem.
É sempre bom ter ajudante, e como usamos o compilador, porque não aproveitar a ajuda que ele pode nós dar.
O "salário dele" é seguir algumas regras, que dá pra concordar com a maioria, ou encontrar alternativas pra algumas coisas, como por exemplo pra variável pública.
Isso é aproveitar o compilador como um ajudante pra conferir seu fonte.
De qualquer jeito, é melhor evitar o uso de variável pública.
Na declaração de variável pública ou private, é algo como dizer ao compilador: é possível que esta variável tenha sido criada em algum lugar, pra alguma coisa, ou vai ser usada em algum lugar.
Já a declaração de variável local, é algo como dizer ao compilador: vou usar esta variável aqui.
Então o compilador pode ajudar ainda mais na checagem.
É sempre bom ter ajudante, e como usamos o compilador, porque não aproveitar a ajuda que ele pode nós dar.
O "salário dele" é seguir algumas regras, que dá pra concordar com a maioria, ou encontrar alternativas pra algumas coisas, como por exemplo pra variável pública.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
O que é programação?
É criar rotinas pra reduzir o serviço manual, tornando o serviço mais rápido e mais eficiente.
Ok.
O serviço de programação também é um serviço manual.
E o mais importante: é o NOSSO serviço.
Então um foco principal é deixar o NOSSO serviço mais rápido e mais eficiente.
Uma rotina que peguei hoje.
Independente do menu estranho, e dos caracteres ASCII, dá pra facilitar.
No fonte tá visível: tudo da mesma cor. Pra que SET COLOR?
São retângulos, todos iguais, pra que repetir isso?
Como são todos iguais, mais fácil criar uma função de desenhar retângulo.
Dá até pra reduzir mais, fazendo um FOR/NEXT, mas... nesses retângulos vai o nome da opção - mais pra frente do fonte.
Até deixei a função preparada pra aceitar os textos, vai reduzir mais fonte ainda.
Muito menos fonte, mesmo sem mexer na tela.
Os caracteres do box, só alterar depois a função Retângulo.
Lembrem-se disso:
Programa é pra reduzir serviço, e pode muito bem reduzir o nosso serviço.
E fonte menor, mais fácil de fazer alteração/manutenção/conversão pra gráfico/etc.
Aliás... tem gente mais preocupada em acrescentar tela gráfica.
Dá uma ajeitada nos fontes antes, pode facilitar o serviço depois.
Dependendo da LIB gráfica, também vai poder usar uma única rotina pra criar os botões.
É criar rotinas pra reduzir o serviço manual, tornando o serviço mais rápido e mais eficiente.
Ok.
O serviço de programação também é um serviço manual.
E o mais importante: é o NOSSO serviço.
Então um foco principal é deixar o NOSSO serviço mais rápido e mais eficiente.
Uma rotina que peguei hoje.
Independente do menu estranho, e dos caracteres ASCII, dá pra facilitar.
Código: Selecionar todos
PROCEDURE Main
SetMode( 25, 80 )
col = 01
lin = 02
SET COLOR TO &vacor6
@ lin+3 , col SAY "ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+4 , col SAY "Û Û"
@ lin+5 , col SAY "Û Û"
@ lin+6 , col SAY "ßßßßßßßßßßßßßßßßßßß"
col = 20
lin = 02
SET COLOR TO &vacor6
@ lin+3 , col SAY " ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+4 , col SAY " Û Û"
@ lin+5 , col SAY " Û Û"
@ lin+6 , col SAY " ßßßßßßßßßßßßßßßßßßß"
col = 40
lin = 02
SET COLOR TO &vacor6
@ lin+3 , col SAY " ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+4 , col SAY " Û Û"
@ lin+5 , col SAY " Û Û"
@ lin+6 , col SAY " ßßßßßßßßßßßßßßßßßßß"
col = 60
lin = 02
SET COLOR TO &vacor6
@ lin+3 , col SAY " ÛßßßßßßßßßßßßßßßßÛ"
@ lin+4 , col SAY " Û Û"
@ lin+5 , col SAY " Û Û"
@ lin+6 , col SAY " ßßßßßßßßßßßßßßßßßß"
col = 01
lin = 02
SET COLOR TO &vacor6
@ lin+07, col SAY "ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+08, col SAY "Û Û"
@ lin+09, col SAY "Û Û"
@ lin+10, col SAY "ßßßßßßßßßßßßßßßßßßß"
col = 20
lin = 02
SET COLOR TO &vacor6
@ lin+07, col SAY " ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+08, col SAY " Û Û"
@ lin+09, col SAY " Û Û"
@ lin+10, col SAY " ßßßßßßßßßßßßßßßßßßß"
col = 40
lin = 02
SET COLOR TO &vacor6
@ lin+07, col SAY " ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+08, col SAY " Û Û"
@ lin+09, col SAY " Û Û"
@ lin+10, col SAY " ßßßßßßßßßßßßßßßßßßß"
col = 60
lin = 02
SET COLOR TO &vacor6
@ lin+07, col SAY " ÛßßßßßßßßßßßßßßßßÛ"
@ lin+08, col SAY " Û Û"
@ lin+09, col SAY " Û Û"
@ lin+10, col SAY " ßßßßßßßßßßßßßßßßßß"
col = 01
lin = 02
SET COLOR TO &vacor6
@ lin+11, col SAY "ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+12, col SAY "Û Û"
@ lin+13, col SAY "Û Û"
@ lin+14, col SAY "ßßßßßßßßßßßßßßßßßßß"
col = 20
lin = 02
SET COLOR TO &vacor6
@ lin+11, col SAY " ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+12, col SAY " Û Û"
@ lin+13, col SAY " Û Û"
@ lin+14, col SAY " ßßßßßßßßßßßßßßßßßßß"
col = 40
lin = 02
SET COLOR TO &vacor6
@ lin+11, col SAY " ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+12, col SAY " Û Û"
@ lin+13, col SAY " Û Û"
@ lin+14, col SAY " ßßßßßßßßßßßßßßßßßßß"
col = 60
lin = 02
SET COLOR TO &vacor6
@ lin+11, col SAY " ÛßßßßßßßßßßßßßßßßÛ"
@ lin+12, col SAY " Û Û"
@ lin+13, col SAY " Û Û"
@ lin+14, col SAY " ßßßßßßßßßßßßßßßßßß"
col = 01
lin = 02
SET COLOR TO &vacor6
@ lin+15, col SAY "ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+16, col SAY "Û Û"
@ lin+17, col SAY "Û Û"
@ lin+18, col SAY "ßßßßßßßßßßßßßßßßßßß"
col = 20
lin = 02
SET COLOR TO &vacor6
@ lin+15, col SAY " ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+16, col SAY " Û Û"
@ lin+17, col SAY " Û Û"
@ lin+18, col SAY " ßßßßßßßßßßßßßßßßßßß"
col = 40
lin = 02
SET COLOR TO &vacor6
@ lin+15, col SAY " ÛßßßßßßßßßßßßßßßßßÛ"
@ lin+16, col SAY " Û Û"
@ lin+17, col SAY " Û Û"
@ lin+18, col SAY " ßßßßßßßßßßßßßßßßßßß"
col = 60
lin = 02
SET COLOR TO &vacor6
@ lin+15, col SAY " ÛßßßßßßßßßßßßßßßßÛ"
@ lin+16, col SAY " Û Û"
@ lin+17, col SAY " Û Û"
@ lin+18, col SAY " ßßßßßßßßßßßßßßßßßß"
RETURN
São retângulos, todos iguais, pra que repetir isso?
Como são todos iguais, mais fácil criar uma função de desenhar retângulo.
Código: Selecionar todos
PROCEDURE Main
SetMode( 25, 80 )
Retangulo( 5, 1 )
Retangulo( 5, 20 )
Retangulo( 5, 40 )
Retangulo( 5, 60 )
Retangulo( 9, 1 )
Retangulo( 9, 20 )
Retangulo( 9, 40 )
Retangulo ( 9, 60 )
Retangulo( 13, 1 )
Retangulo( 13, 20 )
Retangulo( 13, 40 )
Retangulo( 13, 60 )
Retangulo( 17, 1 )
Retangulo( 17, 20 )
Retangulo( 17, 40 )
Retangulo( 17, 60 )
RETURN
FUNCTION Retangulo( mLin, mCol, cTexto1, cTexto2 )
@ mLin, mCol TO mLin + 3, mCol + 18 DOUBLE
RETURN NIL
Até deixei a função preparada pra aceitar os textos, vai reduzir mais fonte ainda.
Muito menos fonte, mesmo sem mexer na tela.
Os caracteres do box, só alterar depois a função Retângulo.
Lembrem-se disso:
Programa é pra reduzir serviço, e pode muito bem reduzir o nosso serviço.
E fonte menor, mais fácil de fazer alteração/manutenção/conversão pra gráfico/etc.
Aliás... tem gente mais preocupada em acrescentar tela gráfica.
Dá uma ajeitada nos fontes antes, pode facilitar o serviço depois.
Dependendo da LIB gráfica, também vai poder usar uma única rotina pra criar os botões.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
A sequência daquele fonte:
E agora o fonte equivalente ajustado pra incluir essa parte.
Poucas alterações, e já incluiu a segunda parte.
Código: Selecionar todos
SET COLOR TO &vacor9
col = 05
lin = 02
@ lin+04, col PROMPT " Clientes " /// clie
col = 27
lin = 02
@ lin+04, col PROMPT " Split " //// spli
@ 07,23 say "Inst./ Garantia"
col = 46
lin = 02
@ lin+04, col PROMPT " Agenda " //// agenda
@ 07,44 say " Telefonica"
col = 64
lin = 02
@ lin+04, col PROMPT " Garantias " //// Garantia
@ 07,62 say " "
col = 04
lin = 02
@ lin+08, col PROMPT " Agendamento " //// Peca
@ 11,02 say "Manutencao Progr." //Manutencao Preventiva Programado
col = 23
lin = 02
@ lin+08, col PROMPT " Historico O.S " //// histor
@ 11,25 say " Imprimir "
col = 42
lin = 02
@ lin+08, col PROMPT " Atendimento O.S " /// atendi
@ 11,47 say " Diario "
col = 65
lin = 02
@ lin+08, col PROMPT "Logradouro" //// limpo
@ 11,68 say " MAPA"
col = 07
lin = 02
@ lin+12, col PROMPT " Tirar " //// venda
@ 15,02 say "Pedido / Entrega "
col = 26 ////22
lin = 02
@ lin+12, col PROMPT " Consulta " //// vernota
@ 15,22 say "Pedido / Entrega"
col = 43
lin = 02
@ lin+12, col PROMPT "Carne Pagamento" //// carne 12
@ 15,45 say "Venda Prazo"
col = 67
lin = 02
col = 62
lin = 02
@ lin+12, col PROMPT "O r c a m e n t." //// obra 13
@ 15,65 say " Numerado "
col = 06
lin = 02
@ lin+16, col PROMPT " Senha " ////14
col = 23
lin = 02
@ lin+16, col PROMPT " DEBITO " ///95
@ 19,23 say "Carne Pagamento"
col = 45
lin = 02
@ lin+16, col PROMPT "Consulta Cep" ////14
col = 65
lin = 02
@ lin+16, col PROMPT " Sair "
MENU TO OP
Código: Selecionar todos
PROCEDURE Main
SetMode( 25, 80 )
Retangulo( 5, 1, "Clientes" )
Retangulo( 5, 20, "Split", "Inst./Garantia" )
Retangulo( 5, 40, "Agenda", "Telefonica" )
Retangulo( 5, 60, "Garantias" )
Retangulo( 9, 1, "Agendamento", "Manutenção Progr." )
Retangulo( 9, 20, "Histórico O.S.", "Imprimir" )
Retangulo( 9, 40, "Atendimento O.S.", "Diário" )
Retangulo ( 9, 60, "Logradouro", "MAPA" )
Retangulo( 13, 1, "Tirar", "Pedido/Entrega" )
Retangulo( 13, 20, "Consulta", "Pedido/Entrega" )
Retangulo( 13, 40, "Carne Pagamento", "Venda Prazo" )
Retangulo( 13, 60, "Orcamento", "Numerado" )
Retangulo( 17, 1, "Senha" )
Retangulo( 17, 20, "Debito", "Carne Pagamento" )
Retangulo( 17, 40, "Consulta CEP" )
Retangulo( 17, 60, "Sair" )
MENU TO OP
RETURN
FUNCTION Retangulo( mLin, mCol, cTexto1, cTexto2 )
cTexto2 := iif( cTexto2 == NIL, "", cTexto2 )
SetColor( vaCor6 )
@ mLin, mCol TO mLin + 3, mCol + 18 DOUBLE
SetColor( vaCor9 )
@ mLin + 1, mCol + 1 PROMPT Pad( cTexto1, 16 )
@ mLin + 2, mCol + 1 SAY Pad( cTexto2, 16 )
RETURN NIL
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Práticas que facilitam programar Clipper/Harbour
Isso mesmo, simplificando de forma clara e objetiva.
Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:
“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”.
Até 2017 Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL
Novos Projetos:
Desktop Visual Windev Desktop
Celular Android/iOS Windev Mobile
WEB Windev Web
Sejamos gratos a Deus.
“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”.
Até 2017 Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL
Novos Projetos:
Desktop Visual Windev Desktop
Celular Android/iOS Windev Mobile
WEB Windev Web
Sejamos gratos a Deus.
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
A de hoje é sobre abrir arquivos.
É normal abrir arquivos em todos os programas.
Mas são sempre os mesmos, no máximo o que acontece é ser em ordem diferente.
Então porque não uma função pra isso.
Vamos lá:
Por enquanto pular testes de arquivos, índices, etc.
Tem gente que usa assim em todos os fontes.
Somado à checagem de existir ou não o arquivo, fica maior ainda.
Já usei assim também.
Numa determinada época deixei numa função fixa no próprio fonte, só pra separar em blocos.
IMPORTANTE: Tem gente que ainda não entende sobre variáveis locais, parâmetros na função, e funções/procedures STATIC. Isso facilita muito.
Então o fonte virou isto:
PROCEDURE Main
IF .NOT. AbreArquivos()
RETURN
ENDIF
...
STATIC FUNCTION AbreArquivos()
// E o conteúdo do fonte anterior
RETURN .T.
[/code]
Em todos os fontes, pode ser usado exatamente o mesmo nome, já que é estática, visível somente no fonte. Cada fonte tem sua função AbreArquivos().
Isso é pouco, mas já deixa o fonte de sua rotina menor, por separar a parte de abrir arquivos.
Mas olhando a parte de abrir arquivos, são todas iguais, tem o SELECT 0, e depois o NET_USE()
Então simplificar, vamos criar AbreUmArquivo() que vai abrir só um arquivo.
Já poderemos ter uma única função AbreUmArquivo() para o sistema inteiro.
Economizou o SELECT 0. É pouco, mas já evita com que esqueça disso.
Bom, é sempre igual, só altera o nome.
E se... a função aceitasse uma lista de arquivos?
Já temos pra abrir um arquivo, falta pra uma lista de arquivos.
Vamos lá, se é lista... array
Pronto.
Uma função que recebe uma lista, e que chama a nossa rotina de abrir um único arquivo para cada nome da lista.
Lembrando: não precisa mais AbreUmArquivo() ou AbreArquivos() em cada fonte. Basta uma função dessa pro sistema inteiro (ou pra todos os sistemas).
E se quiser testar se arquivo existe?
Só acrescentar em AbreUmArquivo()
E se quiser também abrir os índices?
Só mexer em AbreUmArquivo().
Pode identificar qual é o arquivo, e já acrescentar os índices.
Pode até criar AbreCdx(), pra aceitar a lista igual foi feito pra DBFs.
Vantagem: menos digitação, e certeza de que os arquivos serão abertos com o/os índices corretos.
Precisa usar determinado arquivo em outra ordem?
Ok. Depois de abrir seleciona.
Ah sim... selecionar arquivo pelo NOME, e índice também pelo NOME ou TAG, facilita. Identifica mais rápido a ordem que está sendo usada, sem ter que ficar vasculhando fonte.
Importante:
Como digo sempre, são sugestões.
Cada um pode criar um jeito até melhor de usar, ou pra atender o seu uso.
E se precisar alias conforme módulo?
Só acrescentar um parâmetro a mais pra AbreArquivos() e pra AbreUmArquivo()
E se precisar exclusivo?
Também poderia acrescentar um parâmetro pra isso.
Vantagens?
Menos digitação pra novos fontes.
Mais seguro: vai ter certeza que está sempre certa a abertura de arquivos, porque sempre é igual
Menos fonte pra trabalhar, o que deixa mais visível o restante do fonte.
Etc. etc.
E pode aperfeiçoar as aberturas, colocar mensagens de aviso, etc, alterando uma única função, a AbreUmArquivo().
É normal abrir arquivos em todos os programas.
Mas são sempre os mesmos, no máximo o que acontece é ser em ordem diferente.
Então porque não uma função pra isso.
Vamos lá:
Código: Selecionar todos
PROCEDURE Main
SELECT 0
IF .NOT. Net_Use( "CLIENTES" )
RETURN
ENDIF
SELECT 0
IF .NOT. Net_Use( "FORNEC" )
RETURN
ENDIF
SELECT 0
IF .NOT. Net_Use( "PEDIDOS" )
RETURN
ENDIF
...
Tem gente que usa assim em todos os fontes.
Somado à checagem de existir ou não o arquivo, fica maior ainda.
Já usei assim também.
Numa determinada época deixei numa função fixa no próprio fonte, só pra separar em blocos.
IMPORTANTE: Tem gente que ainda não entende sobre variáveis locais, parâmetros na função, e funções/procedures STATIC. Isso facilita muito.
Então o fonte virou isto:
PROCEDURE Main
IF .NOT. AbreArquivos()
RETURN
ENDIF
...
STATIC FUNCTION AbreArquivos()
// E o conteúdo do fonte anterior
RETURN .T.
[/code]
Em todos os fontes, pode ser usado exatamente o mesmo nome, já que é estática, visível somente no fonte. Cada fonte tem sua função AbreArquivos().
Isso é pouco, mas já deixa o fonte de sua rotina menor, por separar a parte de abrir arquivos.
Mas olhando a parte de abrir arquivos, são todas iguais, tem o SELECT 0, e depois o NET_USE()
Então simplificar, vamos criar AbreUmArquivo() que vai abrir só um arquivo.
Já poderemos ter uma única função AbreUmArquivo() para o sistema inteiro.
Código: Selecionar todos
PROCEDURE Main
IF .NOT. AbreUmArquivo( "clientes" )
RETURN
ENDIF
IF .NOT. AbreUmArquivo( "fornec" )
RETURN
ENDIF
IF .NOT. AbreUmArquivo( "pedidos" )
RETURN
ENDIF
...
FUNCTION AbreUmArquivo( cNome )
SELECT 0
IF .NOT. Net_Use( cNome )
RETURN .F.
ENDIF
RETURN .T.
Bom, é sempre igual, só altera o nome.
E se... a função aceitasse uma lista de arquivos?
Já temos pra abrir um arquivo, falta pra uma lista de arquivos.
Vamos lá, se é lista... array
Código: Selecionar todos
PROCEDURE Main
IF .NOT. AbreArquivos( { "clientes", "fornec", "pedidos" } )
RETURN
ENDIF
...
FUNCTION AbreArquivos( acLista )
LOCAL nCont
FOR nCont = 1 TO Len( acLista )
IF .NOT. AbreUmArquivo( acLista[ nCont ] )
CLOSE DATABASES
RETURN .F.
ENDIF
NEXT
RETURN .T.
FUNCTION AbreUmArquivo( cNome )
RETURN Net_Use( cNome )
Uma função que recebe uma lista, e que chama a nossa rotina de abrir um único arquivo para cada nome da lista.
Lembrando: não precisa mais AbreUmArquivo() ou AbreArquivos() em cada fonte. Basta uma função dessa pro sistema inteiro (ou pra todos os sistemas).
E se quiser testar se arquivo existe?
Só acrescentar em AbreUmArquivo()
E se quiser também abrir os índices?
Só mexer em AbreUmArquivo().
Pode identificar qual é o arquivo, e já acrescentar os índices.
Pode até criar AbreCdx(), pra aceitar a lista igual foi feito pra DBFs.
Vantagem: menos digitação, e certeza de que os arquivos serão abertos com o/os índices corretos.
Precisa usar determinado arquivo em outra ordem?
Ok. Depois de abrir seleciona.
Código: Selecionar todos
IF .NOT. AbreArquivos( { "clientes", "fornec", "pedidos" } )
RETURN
ENDIF
SELECT clientes
OrdSetFocus( "nome" )
// SET ORDER TO 2
Importante:
Como digo sempre, são sugestões.
Cada um pode criar um jeito até melhor de usar, ou pra atender o seu uso.
E se precisar alias conforme módulo?
Só acrescentar um parâmetro a mais pra AbreArquivos() e pra AbreUmArquivo()
E se precisar exclusivo?
Também poderia acrescentar um parâmetro pra isso.
Vantagens?
Menos digitação pra novos fontes.
Mais seguro: vai ter certeza que está sempre certa a abertura de arquivos, porque sempre é igual
Menos fonte pra trabalhar, o que deixa mais visível o restante do fonte.
Etc. etc.
E pode aperfeiçoar as aberturas, colocar mensagens de aviso, etc, alterando uma única função, a AbreUmArquivo().
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Uma coisa muito importante pra muitos, a maioria já sabe, mas ainda tem gente que não sabe:
Aprenda STATIC FUNCTION, FUNCTION, LOCAL
STATIC FUNCTION
Você pode ter a função Imprime() por exemplo, em todos os relatórios, mesmo nome, sem ter que inventar novos nomes. Cada relatório tem sua própria Imprime()
FUNCTION NomeMes( nCont )
O parâmetro é sempre local, e função sempre retorna alguma coisa.
Não tem porque usar PRIVATE pra isso, isso só complica.
Há exceções, mas não faça da exceção uma regra.
LOCAL
Variável visível somente no módulo.
Pode usar aquele nome no sistema inteiro, e uma variável não tem nada a ver com a outra. Assim não inventa nomes complicados.
É como se fosse o josé do departamento pessoal, e o josé da contabilidade.
Mesmo nome, mas cada um no seu setor, então o sistema não mistura.
Basta declarar LOCAL.
Senão com PRIVATE vai ter que inventar: JOSE_Prog1, JOSE_Prog2, e vai se complicar.
Até dá pra fazer igual com PRIVATE, mas estará arriscando o que não precisa arriscar.
Se ainda não aprendeu direito isso, é muito bom investir nisso.
É a base pra todo resto.
Até mesmo em Clipper, já que não há limite de variáveis LOCAL, mas há limite de variáveis PRIVATE.
A rotina acima funciona.
Agora de outro jeito:
Muita diferença.
É só exemplo, poderia reduzir um pouco mais.
Acho que isso ainda é confuso pra quem veio do Clipper Summer, porque naquela época não existia declaração de variável LOCAL.
Se não entendeu a vantagem de variável LOCAL, e de criar uma função que não é dependente de nome de variável, treine e pergunte, até aprender.
Vai poder fazer maravilhas de fontes.
Sem isso, tudo fica mais complicado.
Jovem gosta de tudo complicado, e se entende com complicações.
Às vezes não é porque está ficando velho, mas porque continua programando complicado igual jovem gosta.
Jovem não gosta de seguir regras, e aí... só jovem entende a complicação que fez.
Com o passar do tempo... essa complicação vai ficando cada vez mais complicada, porque vai deixando de ser jovem.
Então.... ao invés de se sentir velho.... descomplique.
Vai se sentir cada vez mais jovem, porque vai enxergar coisas que não enxergava antes.
Passei por isso! Experiência própria!
Parece que fica cada vez melhor.
Aprenda STATIC FUNCTION, FUNCTION, LOCAL
STATIC FUNCTION
Você pode ter a função Imprime() por exemplo, em todos os relatórios, mesmo nome, sem ter que inventar novos nomes. Cada relatório tem sua própria Imprime()
FUNCTION NomeMes( nCont )
O parâmetro é sempre local, e função sempre retorna alguma coisa.
Não tem porque usar PRIVATE pra isso, isso só complica.
Há exceções, mas não faça da exceção uma regra.
LOCAL
Variável visível somente no módulo.
Pode usar aquele nome no sistema inteiro, e uma variável não tem nada a ver com a outra. Assim não inventa nomes complicados.
É como se fosse o josé do departamento pessoal, e o josé da contabilidade.
Mesmo nome, mas cada um no seu setor, então o sistema não mistura.
Basta declarar LOCAL.
Senão com PRIVATE vai ter que inventar: JOSE_Prog1, JOSE_Prog2, e vai se complicar.
Até dá pra fazer igual com PRIVATE, mas estará arriscando o que não precisa arriscar.
Se ainda não aprendeu direito isso, é muito bom investir nisso.
É a base pra todo resto.
Até mesmo em Clipper, já que não há limite de variáveis LOCAL, mas há limite de variáveis PRIVATE.
Código: Selecionar todos
PRIVATE mNomeMes, mNumeroMes
mNumeroMes = 10
mNomeMes = ""
NomeMes()
? mNomeMes
RETURN
FUNCTION NomeMes()
IF mNumeroMes = 10
mNomeMes = "OUTUBRO"
ELSE
mNomeMes = ""
ENDIF
RETURN ""
Agora de outro jeito:
Código: Selecionar todos
LOCAL mNumeroMes
mNumeroMes := 10
? NomeMes( nNumeroMes )
RETURN
FUNCTION NomeMes( nMes )
LOCAL mNomeMes
IF nMes == 10
mNomeMes = "OUTUBRO"
ELSE
mNomeMes = ""
ENDIF
RETURN mNomeMEs
É só exemplo, poderia reduzir um pouco mais.
Acho que isso ainda é confuso pra quem veio do Clipper Summer, porque naquela época não existia declaração de variável LOCAL.
Se não entendeu a vantagem de variável LOCAL, e de criar uma função que não é dependente de nome de variável, treine e pergunte, até aprender.
Vai poder fazer maravilhas de fontes.
Sem isso, tudo fica mais complicado.
Jovem gosta de tudo complicado, e se entende com complicações.
Às vezes não é porque está ficando velho, mas porque continua programando complicado igual jovem gosta.
Jovem não gosta de seguir regras, e aí... só jovem entende a complicação que fez.
Com o passar do tempo... essa complicação vai ficando cada vez mais complicada, porque vai deixando de ser jovem.
Então.... ao invés de se sentir velho.... descomplique.
Vai se sentir cada vez mais jovem, porque vai enxergar coisas que não enxergava antes.
Passei por isso! Experiência própria!
Parece que fica cada vez melhor.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
-
marcosgambeta
- Usuário Nível 3

- Mensagens: 332
- Registrado em: 16 Jun 2005 22:53
Práticas que facilitam programar Clipper/Harbour
Variáveis do tipo PUBLIC e PRIVATE podem ser uma fonte de problemas, caso o desenvolvedor não mantenha um bom controle sobre elas.JoséQuintas escreveu:De qualquer jeito, é melhor evitar o uso de variável pública.
O ideal mesmo é evitar ou, pelo menos, minimizar o uso.
Usando OOP, tem uma ideia que pode ser aplicada quando a aplicação tem muitas variáveis PUBLIC: criar uma classe e colocar estas variáveis como propriedades da classe.
Código: Selecionar todos
// usando variáveis públicas
PUBLIC var1
PUBLIC var2
PUBLIC var3
PUBLIC var4
PUBLIC var5
var1 := 1
var2 := 2
var3 := 3
var4 := 4
var5 := 5
// usando uma classe
CLASS MinhasVariaveis
DATA var1
DATA var2
DATA var3
DATA var4
DATA var5
METHOD new
END CLASS
METHOD new () CLASS MinhasVariaveis
::var1 := 1
::var2 := 2
::var3 := 3
::var4 := 4
::var5 := 5
RETURN self
PUBLIC oMinhasVariaveis := MinhasVariaveis():new()
? oMinhasVariaveis:var1
? oMinhasVariaveis:var2
? oMinhasVariaveis:var3
? oMinhasVariaveis:var4
? oMinhasVariaveis:var5
Código: Selecionar todos
var1 -> oMinhasVariaveis:var1
var2 -> oMinhasVariaveis:var2
var3 -> oMinhasVariaveis:var3
var4 -> oMinhasVariaveis:var4
var5 -> oMinhasVariaveis:var5
E além de classes, tem também a opção de usar uma variável do tipo HASH.
Atenciosamente,
Marcos Antonio Gambeta
Marcos Antonio Gambeta
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Bem lembrado.
Também dá pra aproveitar o funcionamento diferente de array.
Um uso interessante:
Este pode ser aproveitado em multithread, desde que se tome cuidado.
Multithread são várias rotinas ao mesmo tempo.
Supondo uma rotina FOR nCont = 1 to Len( array )
Durante esse loop, outra rotina poderia alterar a quantidade de elementos do array, o que teria um resultado imprevisível.
Também dá pra aproveitar o funcionamento diferente de array.
Um uso interessante:
Código: Selecionar todos
PROCEDURE Main
AAdd( PublicVar(), 10 )
? PublicVar()[ 1 ]
RETURN
FUNCTION PublicVar()
STATIC VarPublic := {}
RETURN VarPublic
Multithread são várias rotinas ao mesmo tempo.
Supondo uma rotina FOR nCont = 1 to Len( array )
Durante esse loop, outra rotina poderia alterar a quantidade de elementos do array, o que teria um resultado imprevisível.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Um texto interessante
http://computerworld.com.br/seis-caract ... m-escritos
Fonte:Nem todo sistema é construído da mesma forma. Desenvolvedores citam pontos que tornam um código melhor do que outro
Phil Johnson
25 de Setembro de 2015 - 15h59
Há muitas e muitas linhas de código sustentando sistemas ao redor do mundo. Para se ter uma ideia, apenas o Google soma mais de dois bilhões de linhas em sua estrutura. Mas nem todas fontes são criadas de maneira semelhante.
Para descobrir o que faz de alguns códigos melhores que outros, buscamos a opinião de diversos desenvolvedores. Além disso, indagamos outros programadores para ver quais características esperam ou querem de um sistema no qual trabalharão. Com base nisso, listamos seis pontos que softwares “bem escritos” têm em comum.
É facilmente legível
Os desenvolvedores parecem concordar que uma das qualidades mais importantes de um código é a sua legibilidade. Sistemas escritos de uma forma que podem ser lidos rapidamente por outros programadores são considerados um trabalho de alto nível.
“Sinto que se eu não consigo entender a intenção do autor do sistema em cinco minutos ou menos, o programador fez um trabalho ruim”, dispara Luke Burnham, engenheiro de software da Lionbridge. “Um código é escrito uma vez e lido muitas outras ao longo de sua vida útil”, adiciona, citando a necessidade de usar recursos que facilitem esse processo de leitura e entendimento.
Para um desenvolvedor de aplicativos web que pediu para não ser identificado, um bom código é aquele que “segue um estilo de codificação consistente (o espaçamento adequado, o recuo, o fluxo geral)”, disse. Ele também enfatizou a importância de escolher “nomes de variáveis” que fazem sentido de uma maneira geral.
Em resumo: mais legível significa mais compreensível e facilita a vida de todos. Assim, quanto mais rápido alguém poder compreender a estrutura, melhor.
Tem comentários úteis
Além de boa formatação e “nomeação”, os comentários podem também tornar o código, em última análise, mais facilmente compreendido. Mas não apenas quaisquer comentários, como Burnham salienta. “Eu não preciso comentários para me dizer o que um loop faz. Preciso de comentários para me dizer por que o código está fazendo o que está fazendo”, afirma. “Para mim, um bom código tem comentários que explicam o que passou na cabeça do autor durante a construção”.
É simples
O melhor código – e isso parece consenso – muitas vezes é algo simples. Bons programadores sabem como fazer o trabalho sem excesso, que compliquem demais as coisas. “... há uma correlação estatística comprovada entre a complexidade de código e bugs ...”, escreveu Neville Kuyt.
É flexível
A funcionalidade de uma parte do código existente, muitas vezes, necessita ser alterada, expandida, ou reutilizada em outros lugares no futuro. É por isso que Burnham aconselha: “Bons softwares são escritos com as exigências tanto de hoje quanto com as perspectivas para futuro”.
Obviamente, prever o que está porvir é impossível. “Mas praticamente todo bom programador é capaz de criar um sistema flexível o suficiente que exija mudanças mínimas para acomodar novos requerimentos”, adiciona o engenheiro.
Código é bom se os desenvolvedores são capazes de "adicionar ou alterar certas partes do código sem ter que quebrar outras partes do código", comentou um desenvolvedor, que pediu para não ser identificado. “Você realmente saberá quando um código de alguém é bom mesmo terá que mexer nele”.
É sustentável
Não importa quão bem um pedaço de código é escrito, inevitavelmente, ele terá bugs. "Obviamente alguém pode ter que corrigi-lo", disse Kevin Moylan, engenheiro de software na Genuine Interactive. "E a pessoa que fará isso pode ser você”.
Manutenção, então, é um atributo-chave de um bom código. Todo o código tem de ser mantido: não há necessidade de tornar essa tarefa ainda mais difícil do que o necessário. Portanto, evite fazer coisas como "valores que podem mudar (urls, teclas de acesso, senhas de banco de dados, etc)", escreveu o desenvolvedor anônimo.
Funciona
Finalmente, há uma característica aparentemente óbvia de bom código de software que provavelmente deve ainda ser reforçada antes do final desse texto: ele precisa, efetivamente, funcionar. Em resumo, o sistema tem que fazer o trabalho para o qual foi projetado. “Não importa o quão grande ele se parece, se ele não fazer o trabalho, não é bom”, sintetizou Burnham
http://computerworld.com.br/seis-caract ... m-escritos
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Só um comentário extra sobre o texto acima:
Quando estamos mexendo no nosso próprio fonte, entendemos tudo.
E se estamos com a mão na massa, está tudo na ponta da língua.
Muitas vezes não dá pra perceber isso.
uma frase comum: "Vou ter que lembrar o que o fonte faz".
É bom ficar atento se isso é porque o processo é complicado, ou se é porque o fonte está complicado.
Quando estamos mexendo no nosso próprio fonte, entendemos tudo.
E se estamos com a mão na massa, está tudo na ponta da língua.
Muitas vezes não dá pra perceber isso.
uma frase comum: "Vou ter que lembrar o que o fonte faz".
É bom ficar atento se isso é porque o processo é complicado, ou se é porque o fonte está complicado.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Uma situação que tem em muitos destes fontes que estou mexendo, até esqueci de mencionar:
Isso é perigoso, porque se coincidir com código zerado, simplesmente isso trava.
É importante testar também EOF.
Código: Selecionar todos
DO WHILE arquivo->Locador == mLocador
SKIP
ENDDO
É importante testar também EOF.
Código: Selecionar todos
DO WHILE arquivo->Locador == mLocador .AND. .NOT. Eof()
SKIP
ENDDO
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Um exemplo de fonte que considero ruim.
Só imaginar o seguinte: o programador usava o EDIT do DOS, o que significa 24 linhas na tela, ou 3 páginas de fonte.
Usar outro editor e mais linhas seria melhor, mas o problema não tem a ver com o editor.
Este é um relatório simples, mas visualizar a lógica dele até com outro editor e mais linhas, ainda continua sendo um problema.
Faça um teste:
Confira esse fonte quanto a Eof(), SKIP ou quebra de página se está ok.
Preste atenção em quanto tempo gasta pra isso, ou o quanto precisa ir/voltar no fonte.
Sem usar classe, usando o básico mesmo, poderia estar neste estilo, por exemplo:
Vantagem?
Ao olhar o fonte no editor, já vai ter uma visão completa, mesmo estando dividido em blocos.
Vai ser muito mais rápido conferir SKIP, quebra de página, etc.
É deixar o trabalho mais rápido e mais fácil pra nós mesmos.
Só imaginar o seguinte: o programador usava o EDIT do DOS, o que significa 24 linhas na tela, ou 3 páginas de fonte.
Usar outro editor e mais linhas seria melhor, mas o problema não tem a ver com o editor.
Este é um relatório simples, mas visualizar a lógica dele até com outro editor e mais linhas, ainda continua sendo um problema.
Código: Selecionar todos
GO TOP
LF = 0
PG = 1
DO WHILE ! Eof()
IF LF = 0
@ 01, 02 SAY DToC( Date() ) + " Pag." + StrZero( PG, 2 )
@ 02, 04 SAY Chr( 14 )
@ 02, 04 SAY TITU00
@ 02, 04 SAY TITU00
@ 02, 10 SAY Chr( 20 )
@ 03, 04 SAY Chr( 14 )
@ 03, 04 SAY TITU01
@ 03, 40 SAY Chr( 20 )
@ 04, 10 SAY Chr( 27 ) + Chr( 52 )
@ 04, 40 -( Len( TITU02 ) / 2 ) SAY TITU02
@ 04, 40 SAY Chr( 27 ) + Chr( 53 )
@ 06, 01 SAY Chr( 15 )
@ 06, 01 SAY " COD L O C A D O R E N D E R E C O BAIRRO CIDADE C E P TELEFONE N/I"
@ 07, 01 SAY "==== =================================== ============================== ================ =============== ========= ============== ==="
LF = 8
PG += 1
ENDIF
IF LF < 62
@ LF, 01 SAY StrZero( locad00->COD )
@ LF, 06 SAY locad00->NOME
@ LF, 42 SAY locad00->ENDERECO
@ LF, 73 SAY locad00->BAIRRO
@ LF, 90 SAY locad00->CIDADE
@ LF, 106 SAY locad00->CEP
@ LF, 116 SAY SubStr( locad00->TELEFONE, 7, 8 )
@ LF, 131 SAY locad00->EFETIVOS
LO1000 += 1
LF += 1
SKIP
ELSE
@ LF, 01 SAY Chr( 18 )
LF = 0
EJECT
LOOP
ENDIF
ENDDO
IF LF < 62
LF += 1
@ LF, 05 SAY "SAO " + StrZero( LO1000, 4 ) + " LOCADORES EFETIVOS CATALOGADOS"
EJECT
ELSE
EJECT
@ 01, 02 SAY DToC( Date() ) + " Pag." + StrZero( PG, 2 )
@ 02, 04 SAY Chr( 14 )
@ 02, 04 SAY TITU00
@ 02, 04 SAY TITU00
@ 02, 10 SAY Chr( 20 )
@ 03, 04 SAY Chr( 14 )
@ 03, 04 SAY TITU01
@ 03, 40 SAY Chr( 20 )
@ 04, 10 SAY Chr( 27 ) + Chr( 52 )
@ 04, 40 - ( Len( TITU02 ) / 2 ) SAY TITU02
@ 04, 40 SAY Chr( 27 ) + Chr( 53 )
LF = 7
@ LF, 05 SAY "SAO " + StrZero( LO1000, 4 ) + " LOCADORES EFETIVOS CATALOGADOS"
EJECT
ENDIF
Confira esse fonte quanto a Eof(), SKIP ou quebra de página se está ok.
Preste atenção em quanto tempo gasta pra isso, ou o quanto precisa ir/voltar no fonte.
Sem usar classe, usando o básico mesmo, poderia estar neste estilo, por exemplo:
Código: Selecionar todos
DO WHILE .NOT. Eof()
IF nLin > 66
Cabecalho()
ENDIF
@ nlin, 0 SAY "..."
SKIP
ENDDO
IF nLin > 60
Cabecalho()
ENDIF
@ nLin, 0 SAY "TOTAL DE EFETIVOS"
Ao olhar o fonte no editor, já vai ter uma visão completa, mesmo estando dividido em blocos.
Vai ser muito mais rápido conferir SKIP, quebra de página, etc.
É deixar o trabalho mais rápido e mais fácil pra nós mesmos.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Aquele texto sobre fontes....
Achei um exemplo de observação ruim nos fontes do Harbour.
Por acaso existe alguma dúvida que ::aGroupTotals é a "variável" em questão, e que Array() vai atribuir um array?
Esse é um tipo de comentário que só serve pra atrapalhar a visão do fonte, sendo desnecessário.
Isso foi um dos ítens apresentados naquele texto.
Achei um exemplo de observação ruim nos fontes do Harbour.
Código: Selecionar todos
// Initialize ::aGroupTotals as an array
::aGroupTotals := Array( Len( ::aReportData[ RPT_GROUPS ] ) )
Esse é um tipo de comentário que só serve pra atrapalhar a visão do fonte, sendo desnecessário.
Isso foi um dos ítens apresentados naquele texto.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
- Duda 'Sgluber'
- Usuário Nível 3

- Mensagens: 148
- Registrado em: 11 Mar 2013 21:57
- Localização: Interior de São Paulo
Práticas que facilitam programar Clipper/Harbour
Gostei do texto, Quintas... obrigado!JoséQuintas escreveu:Um texto interessante
...

Comecei pra valer nos tempos do MSX e nunca mais parei... grande caminhada! 
- JoséQuintas
- Administrador

- Mensagens: 20267
- Registrado em: 26 Fev 2007 11:59
- Localização: São Paulo-SP
Práticas que facilitam programar Clipper/Harbour
Tem algumas coisas que uso no meu aplicativo, que me ajudam muito.
Mudanças entre versões.
Renomear arquivos, acrescentar liberação de senha pra rotina nova, acrescentar/retirar campos, etc.
Se embutir no EXE, não esquece de fazer no cliente, e nem precisa se preocupar quando é que o cliente vai trocar versão.
Tabelas num único arquivo.
Um cadasto genérico é interessante.
Tá cheio de tabela que pode ser agrupada.
Na validação por exemplo, usando essa tabela:
E o cadastro multiuso:
Nesse caso, pra evitar erro de digitação, coloquei em #define e compilo usando -w3 -es2
Mudanças entre versões.
Renomear arquivos, acrescentar liberação de senha pra rotina nova, acrescentar/retirar campos, etc.
Se embutir no EXE, não esquece de fazer no cliente, e nem precisa se preocupar quando é que o cliente vai trocar versão.
Tabelas num único arquivo.
Um cadasto genérico é interessante.
portador, centro de custo, NCM, CFOP, CST ICMS, CST IPI, CST Pis, CST Cofins, enquadramento PIS, enquadramento Cofins, enquadramento IPI, etc.TABELA, C, 6
CODIGO, C, 6
DESCRICAO, C, 40
Tá cheio de tabela que pode ser agrupada.
Na validação por exemplo, usando essa tabela:
Código: Selecionar todos
SEEK "PISCST" + Código
Código: Selecionar todos
SET FILTER TO TABELA="PISCST"
Código: Selecionar todos
#define AUX_PISCST "PISCST"
SEEK AUX_PISCST + Codigo
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
https://github.com/JoseQuintas/
