Página 1 de 1

Padrão /w3

Enviado: 18 Nov 2012 19:45
por JoséQuintas
É muito bom acostumar com esse padrão de programação.
Mas é importante que não fique limitado aos erros de compilação.

Exemplo:

Código: Selecionar todos

procedure main
mvar := space(10)
@ 2, 20 get mvar valid ConteudoOk()
read

function ConteudoOk()
return .not. empty(mvar)
Essa rotina não passa no padrão /w3.
Primeiro porque as variáveis não estão definidas em cada rotina.
Segundo porque a função ConteudoOk() usa uma variável que não conhece.
Mas se acrescentar MEMVAR para a variável mvar, já passa na compilação com /w3.

A intenção do /w3 não é apenas essa.
O certo é que cada rotina conheça as variáveis que usa.
Então, o mais correto seria alterar dois pontos:
Valid ConteudoOk(mVar)
Function ConteudoOk(mVar)

Obs. Poderia ser indicado direto no valid, mas este é só um exemplo do que seria o padrão /w3

Mas mesmo assim... qual vantagem?
Antes de alterar, a rotina ConteudoOk() é totalmente dependente da variável existir na rotina que a chama. Não se pode nem mexer no nome da variável, e se for usada por outra rotina, é obrigatório usar o mesmo nome de variável.
Após alterar, ConteudoOk() se tornou uma função independente, e pode tranquilamente ser modificada, ou usada em qualquer rotina, seja qual for a variável.

É isso que se deve tomar cuidado: não confundir padrão /w3 com apenas evitar erros ao compilar com /w3.

Acontece de vez em quando de digitar errado o nome de uma variável, e só vamos descobrir quando está rodando no cliente.
Usando o padrão /w3 isso já não acontece, porque o compilador vai reclamar das variáveis usadas que não foram declaradas.

Por isso aconselho: se puder usar, use o padrão /w3.
Se tem um sistema grande, vai ser um grande trabalho fazer o ajuste, podendo causar até erros aonde já funcionava.
Mas pode já adotar o padrão pra novas rotinas.

Aqu fiz o contrário do que indicaram:
Coloquei no fonte velho #pragma /w0
E fixei o compilador com /w3 /es2

Com isso, tudo que é novo já é feito desse modo. E os programas antigos, vou alterando um por vez.

Padrão /w3

Enviado: 10 Jul 2016 17:56
por fladimir
Com relação a isto realmente é uma ótima prática

Agora na alteração me deparei com um problema... veja o final do código

Código: Selecionar todos

function Consulta()
    ...
	break(oErro)
return .F. 
o compilador da a mensagem: Warning W0028 Unreachable code

devido o break antes do return tipo não vai ler a linha debaixo... porém se eu tiro o return da outra mensagem...

Código: Selecionar todos

Warning W0007  Function 'CONSULTA' does not end with RETURN statement
E agora como resolver?

Padrão /w3

Enviado: 10 Jul 2016 18:11
por Jairo Maia
Acho que o problema está na forma de uso do Break.

Quando você usa o Break sem direcionamento, ele retorna para a linha imediatamente abaixo do End Sequence de onde ele ele foi chamado numa função ou bloco entre: Begin Sequence / End Sequence.

Quando você usa o Break com direcionamento, por exemplo: Break NomeDaFuncao(), ele retorna para a função que foi direcionado sem retorno para onde ele foi chamado, ou seja, a execução dá sequência de onde ele foi direcionado.

Não é possível receber o valor de Variável ou Objeto através de um Break, tal como um Return.

Acho que é isso.

Padrão /w3

Enviado: 10 Jul 2016 21:05
por JoséQuintas
O erro "Warning W0028 Unreachable code" significa que NADA será executado depois de BREAK, e por isso aquela continuação do fonte não tem sentido.

Mas pera lá....
BREAK não é usado dentro de um BEGIN-END ? Algo como o EXIT do DO WHILE?

Código: Selecionar todos

BEGIN SEQUENCE WITH __BreakBlock()
    IF x = 10
       BREAK
   ENDIF
END SEQUENCE

Padrão /w3

Enviado: 11 Jul 2016 01:01
por Jairo Maia
Não. Break tem uma amplitude muito maior que isso. Exemplo:

Código: Selecionar todos

#include "inkey.ch"

Function Main()

 Alert( "Voce está na funcao Inicial" )

 BEGIN SEQUENCE
 
  Teste()

  Hb_Alert( "Voce nao pressionou ESC" ) // esta funcao não será executada se pressionar ESC...
 
 END SEQUENCE

 If LastKey() = K_ESC
  Hb_Alert( [Voce pressionou ESC, entao voce nao viu a mensagem;;"Voce nao pressionou ESC";;porque ela esta antes da linha END SEQUENCE.])
 EndIf

Return Nil

Function Teste()

 Hb_Alert( "Pressione ESC para entender o Break" )

 If LastKey() = K_ESC
  Break
 EndIf
 
Return Nil

Padrão /w3

Enviado: 11 Jul 2016 08:36
por JoséQuintas
Fiz um teste usando esse mesmo fonte.
Se colocar assim, dá o erro que foi mencionado.

Código: Selecionar todos

#include "inkey.ch"

Function Main()

 Alert( "Voce está na funcao Inicial" )

 BEGIN SEQUENCE

 Teste()

 Hb_Alert( "Voce nao pressionou ESC" ) // esta funcao não será executada se pressionar ESC...

 END SEQUENCE

 If LastKey() = K_ESC
 Hb_Alert( [Voce pressionou ESC, entao voce nao viu a mensagem;;"Voce nao pressionou ESC";;porque ela esta antes da linha END SEQUENCE.])
 EndIf

Return Nil

Function Teste()

 Hb_Alert( "Pressione ESC para entender o Break" )

 //If LastKey() = K_ESC
 Break
 //EndIf

Return Nil
Até tem sentido, porque se o BREAK é para exceções, faltaria a saída normal.
A saída, num caso destes, seria enganar o compilador:

Código: Selecionar todos

IF .T.
   BREAK
ENDIF
Aliás... se sempre sai com BREAK, tanto faz ter ou não, vai sair de qualquer jeito.
O uso é que está estranho mesmo, É como um IF sem ELSE, ou um ELSE sem IF.

Padrão /w3

Enviado: 11 Jul 2016 09:12
por JoséQuintas
Um fonte assim ficaria confuso, por exemplo se alterar área de uso, e outras coisas.

Mas independente disso, se em consulta() sempre sai com break, ficou sem opção de escolha para com BREAK/sem BREAK.
Talvez melhor colocar a condição no fonte anterior.

Código: Selecionar todos

IF SeiLaPorQue
   Consulta()
   BREAK
ENDIF
Teria que analisar os fontes em conjunto.
Talvez usar o retorno de consulta()

Código: Selecionar todos

IF .NOT. Consulta()
   // o que fazer? BREAK?
ENDIF
Parece que o compilador fez bem em não aceitar o BREAK dessa forma.
Tem algo esquisito aí... rs

Padrão /w3

Enviado: 11 Jul 2016 10:53
por Kapiaba
Eu uso assim, e vai tranquilo:

Código: Selecionar todos

/n /m /w /es1 /gc1
Abs.

Padrão /w3

Enviado: 11 Jul 2016 10:54
por fladimir
Vlw pessoal vou dar uma olhada

Padrão /w3

Enviado: 11 Jul 2016 11:27
por JoséQuintas
A vantagem do -w3 -es2 é mostrar aonde pode ter coisa errada.
Não se trata apenas de compilar ou não, ou de apenas tratar o erro, mas de confirmar se da forma que foi feito está correta.

Exemplo de um erro parecido:

Código: Selecionar todos

DO WHILE .NOT. Eof()
   ? "alguma coisa"
   EXIT
   SKIP
ENDDO
Aí também acusaria erro, porque o EXIT sai fora do DO WHILE, então SKIP em seguida é inútil.
Mas se SKIP é inútil, o DO WHILE também...
Então não se trata apenas de eliminar o erro do SKIP, mas de revisar o fonte, pra ver se era isso mesmo.
o BREAK indicado seria uma situação parecida com essa.
Se compilar com -w1 -es1, não acusa erro, mas o fonte continua esquisito.... rs

Se alterar para:

Código: Selecionar todos

IF .T.
   EXIT
ENDIF
Isso elimina o erro de compilação, mas de qualquer forma o fonte continua esquisito.

Essas são algumas checagens extras interessantes ao usar -w3 -es2.
É algo como ter um programador experiente te mostrando as coisas "esquisitas", que podem ser problema.
Às vezes é só resolver a mensgem de erro, mas às vezes é bom revisar o que acontece no fonte.

Isso num fonte pequeno tá bem visível, mas num fonte grande só mesmo com a ajuda do compilador.
(ou no caso do BREAK, que usa até fontes/rotinas diferentes).