Práticas que facilitam programar Clipper/Harbour

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

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.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

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.

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
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.

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
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.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

A sequência daquele fonte:

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
E agora o fonte equivalente ajustado pra incluir essa parte.

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
Poucas alterações, e já incluiu a segunda parte.
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/
Avatar do usuário
fladimir
Colaborador
Colaborador
Mensagens: 2445
Registrado em: 15 Nov 2006 20:21

Práticas que facilitam programar Clipper/Harbour

Mensagem por fladimir »

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.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

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á:

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
...
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.

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.
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

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 )
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.

Código: Selecionar todos

IF .NOT. AbreArquivos( { "clientes", "fornec", "pedidos" } )
   RETURN
ENDIF
SELECT clientes
OrdSetFocus( "nome" )
// SET ORDER TO 2
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().
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

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.

Código: Selecionar todos

PRIVATE mNomeMes, mNumeroMes

mNumeroMes = 10
mNomeMes = ""
NomeMes()
? mNomeMes
RETURN

FUNCTION NomeMes()
   IF mNumeroMes = 10
      mNomeMes = "OUTUBRO"
  ELSE
      mNomeMes = ""
   ENDIF
   RETURN ""
A rotina acima funciona.
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
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.
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/
marcosgambeta
Usuário Nível 3
Usuário Nível 3
Mensagens: 332
Registrado em: 16 Jun 2005 22:53

Práticas que facilitam programar Clipper/Harbour

Mensagem por marcosgambeta »

JoséQuintas escreveu:De qualquer jeito, é melhor evitar o uso de variável pública.
Variáveis do tipo PUBLIC e PRIVATE podem ser uma fonte de problemas, caso o desenvolvedor não mantenha um bom controle sobre elas.

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
Fica reduzido à uma única variável pública, sendo que o trabalho maior seria modificar o código-fonte para colocar o nome do objeto antes da variável:

Código: Selecionar todos

var1 -> oMinhasVariaveis:var1
var2 -> oMinhasVariaveis:var2
var3 -> oMinhasVariaveis:var3
var4 -> oMinhasVariaveis:var4
var5 -> oMinhasVariaveis:var5
É apenas uma das formas de se lidar com a situação. Não digo que é a melhor solução, mas pode ajudar a deixar o código-fonte mais organizado.

E além de classes, tem também a opção de usar uma variável do tipo HASH.
Atenciosamente,
Marcos Antonio Gambeta
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Bem lembrado.

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
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.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Um texto interessante
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
Fonte:
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

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.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Uma situação que tem em muitos destes fontes que estou mexendo, até esqueci de mencionar:

Código: Selecionar todos

DO WHILE arquivo->Locador == mLocador
   SKIP
ENDDO
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 .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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

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.

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
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:

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"
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.
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/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Aquele texto sobre fontes....

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 ] ) )
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.
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/
Avatar do usuário
Duda 'Sgluber'
Usuário Nível 3
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

Mensagem por Duda 'Sgluber' »

JoséQuintas escreveu:Um texto interessante
...
Gostei do texto, Quintas... obrigado! Imagem
Comecei pra valer nos tempos do MSX e nunca mais parei... grande caminhada! :-)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

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.
TABELA, C, 6
CODIGO, C, 6
DESCRICAO, C, 40
portador, centro de custo, NCM, CFOP, CST ICMS, CST IPI, CST Pis, CST Cofins, enquadramento PIS, enquadramento Cofins, enquadramento IPI, etc.
Tá cheio de tabela que pode ser agrupada.

Na validação por exemplo, usando essa tabela:

Código: Selecionar todos

SEEK "PISCST" + Código
E o cadastro multiuso:

Código: Selecionar todos

SET FILTER TO TABELA="PISCST"
Nesse caso, pra evitar erro de digitação, coloquei em #define e compilo usando -w3 -es2

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/
Responder