Jmsilva Posted July 24, 2019 Report Share Posted July 24, 2019 Boas práticas = Uma ajuda sem ninguém pedir Olá pessoal, sei que este espaço se presta para ajuda direcionada a um objetivo específico, erro ou dúvidas. Pois bem, sabemos que outras linguagens existem materiais farto na internet, já xHarbour resume-se aos fóruns e nas documentações própria. Com o conhecimento de outras linguagens como o JAVA, por exemplo, vejo que temos algumas facilidades em determinado pontos e perdemos em outros. Mas com a expertise do dia-a-dia, sempre descobri mos técnicas do xHarbour que não vejo nos fóruns, e nem nos exemplos disponíveis GitHub, Google e etc. A minha sugestão em boas práticas, refere-se à codificação, boas praticas em programar, não estou falando de regras de negócios, cada um ou cada empresa tem a sua que é a base do seu sistema. Aqui nos temos grandes programadores, diria os melhores, acredito que cada um tem algo a compartilhar, como uma rotina genérica, forma manipular um objeto e etc. Posso citar como exemplo a TCalc, uma classe que desenvolvi tempos atrás, serve para gerar planilhas através LibreOficce está disponível neste fórum. Salvo juízo contrário, cada programador poderia compartilhar aquilo que acha interessante que pudesse ajudar no aprendizado dos demais. Com a ajuda dos demais poderia até acrescentar algo para otimizar e favorecendo o próprio autor ou apenas servir de material didático para os demais. Como ponta pé inicial, gostaria de apresentar uma forma que acho legal para definição de variáveis. Hipoteticamente, vamos imagina um sistema que tem 3 dbfs, Médico, Paciente e Agenda de consultas: #include "hbstruct.ch" //include obrigatório REQUEST HB_GT_WIN_DEFAULT //Definição de 3 objetos , um para cada tabela Static oMed,oPac,oAgenda //pode ser local private, publica – prefiro statica de PRG, assim //posso usar em métodos e funções sem a necessidade de enviar como parâmetro, para rotina //de outros prg, a sim precisa enviar via parâmetro. Procedure Main() STRUCTURE oMed //variaveis para tabela de médicos MEMBER cCrm AS STRING INIT Space(6) MEMBER cNome AS STRING INIT Space(20) ENDSTRUCTURE STRUCTURE oPac //variaveis para tabela de pacientes MEMBER cCpf AS STRING INIT Space(11) MEMBER cNome AS STRING INIT Space(20) MEMBER dDtNasc AS DATE INIT CTOD('') ENDSTRUCTURE STRUCTURE oAgenda //variaveis para tabela de agendamento de consulta MEMBER cCrm AS STRING INIT Space(6) MEMBER cCpf AS STRING INIT Space(11) MEMBER dDtConsulta AS DATE INIT CTOD('') ENDSTRUCTURE //gets e says e gravações Return rochinha 1 Quote Link to comment Share on other sites More sharing options...
emotta Posted August 9, 2019 Report Share Posted August 9, 2019 Quanto a estruturas para não misturar as variaveis eu utilizo outra técnica que eu particularmente prefiro. A técnica que uso é a seguinte: Todas as tabelas criadas eu identifico por 3 letras seguidas de mais 4 digitos para identificar a empresa. Quando a tabela é uma tabela compartilhada entre as empresas eu mantenho como padrão a empresa 0001. Também identifico no sistema essa tabela somente pelas 3 letras iniciais da tabela. Dentro desta tabela os campos eu crio sempre começando pelo alias e depois o underline e os demias 6 caracteres identificam o nome do campo. (aprendi desta maneira na Microsiga/TOTVS e gostei por isso continuo assim até hoje) Departamentos (tabela unica para todas as empresas) => Nome da tabela SA10001 => Identificador de alias dentro do programa SA1. Estrutura de campos: CODIGO => SA1_CODIGO (Caracter 6) NOME DO DEPARTAMENTO => SA1_NOME (caracter 30) Funcionarios (tabela exclusiva de cada empresa) => Nome da tabela SA20001, SA20002, SA20003,...,SA29999. Identificador de alias dentro do programa SA2. Estrutura de campos: CODIGO => SA2_CODIGO (caracter 5) NOME => SA2_NOME (caracter 40) DEPARTAMENTO => SA2_CODDEP (caracter 6) Com estas regras eu nunca preciso me preocupar com campos repetidos pois eles nunca se repetem pois o campo NOME do departamento é sempre o SA1_NOME e o nome do funcionário é o SA2_NOME Também sigo outra regra sobre os indices. Sempre é caracter, caso o campo seja numero eu o transformo com STR ou DTOS para data. Desta maneira o indice sempre fica do tipo CARACTER No fonte fica mais ou menos assim: Function u_Teste() DbSelectArea("SA1") M->SA1_CODIGO := SA1->SA1_CODIGO M->SA1_NOME := SA1->SA1_NOME DbSelectArea("SA2") M->SA2_CODIGO := SA2->SA2_CODIGO M->SA2_NOME := SA2->SA2_NOME M->SA2_CODDEP := SA2->SA2_CODDEP cDesDep := RetField("SA1",1,M->SA2_CODDEP,"SA1_NOME") // A funcão RETFIELD trata de selecionar a area do cPar1, posicionar no indice do nPar2, fazer o dbseek no cPar3 e retornar o campo através de macro do cPar4 Jmsilva 1 Quote Link to comment Share on other sites More sharing options...
Ariston Santos Posted August 10, 2019 Report Share Posted August 10, 2019 Não tenho muito a contribuir, até porque mais preciso de ajuda do que posso ajudar. No entanto, tem algumas dicas que aprendi com colegas do fórum que vale a pena repassar: Primeiramente, no que se refere à definição de variáveis, gosto de usar o estilo “forma de camelo”, isto é, usar minúsculas e maiúsculas nas definições de variáveis. Por exemplo cObs := “” // e não cobs := “” Em segundo lugar, sempre endentar o código (usar espaços ou tabulação), para não parecer bagunçado e difícil de compreender, bom como inserir comentários, principalmente quando sinto que vou precisar lembrar de alguma anotação mais adiante. Exemplo: Local cObser := “” // Mostrar apenas se cObser não estiver vazia. IF Empty(nomeClient) IF Empty(cObser) cObser += “; “ + CRLF // Quebrar a linha caso exista mais de uma inconsistência ENDIF cObser += “• O nome do cliente deve ser informado” ENDIF Em vez de: Local cObser := “” If Empty(nomeClient) If Empty(cObser) cObser += “; “ + CRLF EndIf cObser += “• O nome do cliente deve ser informado” EndIf E, em terceiro lugar, tomar muito cuidado com o famoso “enxugar o código”. Resumir três ou mais linhas de código em apenas, às vezes, uma é muito bom. Ex.1: nNumero++ // em vez de nNumero := nNumero + 1 Ex.2: cImg := Iif(nPic = 3, “bmpTres”, Iif(nPic = 2, “bmpDois”, “bmpUm”)) Em vez de: cImg := “” IF nPic = 1 cImg := “bmpUm” ELSEIF nPic = 2 cImg := “bmpDois” ELSE cImg := “bmpTres” ENDIF Mas quando se trabalha em equipe, enxugar demais pode deixar o código complicado para o entendimento dos colegas, por isso, prefira, para o bem de todos, deixar o código menos complicado possível, mesmo que isso signifique abrir mão da técnica de enxugar o código. Note também que eu gosto de iniciar a declaração de variáveis com uma letra que identifique o tipo de conteúdo dela: STATIC oXbrItn := NIL // Objeto - Ex: XBrowse() a ser definido LOCAL nCodigo := 0 // Numérica LOCAL cDesItn := Space(80) // Caractere / String LOCAL mDetalh := "" // Memo / String LOCAL dCadast := CtoD(" ") // Data LOCAL lLockIt := .F. // Lógica Por fim, conforme dá para notar acima, gosto de utilizar como boa prática algo que me permita diferenciar "Function()" de "COMMAND". Para isso, gosto de fazer bom uso das minúsculas e maiúsculas. Por exemplo, escrever Funções com iniciais maiúsculas ou usando o “estilo camelo”, e comandos com todas MAIÚSCULAS. É claro que nem sempre lembro de seguir todas essas regrinhas, afinal, ninguém é perfeito. Também nem toda IDE de desenvolvimento permite isso. O bom é que existem muitas IDEs com recursos de endentação automática, auto-complete e auto-case (estilo camelo automático). Com elas, esse tipo de técnica manual está sendo automatizado, permitindo a gente se concentrar mais na codificação em si. Quote Link to comment Share on other sites More sharing options...
Jmsilva Posted August 16, 2019 Author Report Share Posted August 16, 2019 Em linguagem como Java por exemplo, uma variável declarada do tipo String se transforma em um objeto, como no exemplo que segue: String txt = "Hello World"; System.out.println(txt.toUpperCase()); // Outputs "HELLO WORLD" System.out.println(txt.toLowerCase()); // Outputs "hello world" No xHarbour/Harbour podemos fazer melhor, mas vou demostrar forma nativa, não conheço todos os métodos/eventos, estou pesquisando. É possível utilizar em qq tipo de variável, e podemos fazer melhor que o Java, que necessita declarar no escopo o TIPO, no nosso velho (x)Harbour, as propriedades são em consequência ao valtype() do CONTEÚDO da variável. O comando mágico para esta façanha é: ENABLE TYPE CLASS ALL Veja exemplo nativo com manipulação de uma variável do tipo Array: ENABLE TYPE CLASS ARRAY aVar := {} //Modo tradicional aVar:Init(3,Array(2)) //aVar := Array(3,2) aVar:AtPut(1,{"001", "Maça"} ) //aVar[1,{"001", "Maça"} ) aVar:AtPut(2,{"002", "Pera"} ) //aVar[2,{"002", "Pera"} ) aVar:AtPut(3,{"003", "Uva"} ) //aVar[3,{"003", "Uva"} ) aVar:InsertAt(4,{"004","Morango"}) //AADD(aVar,{"004", "Morango"} ) XBrowse(aVar ) //xBrowse(aVar) Dica do dia! Quote Link to comment Share on other sites More sharing options...
Jmsilva Posted October 3, 2019 Author Report Share Posted October 3, 2019 Function ViaCep() Local oOle,cXml,cCep := "01302001" Local cLink := "http://viacep.com.br/ws/<<CEP>>/xml/" Local oXml,oTag,cLog,cComple,cBairro,cCidade,cUf cLink := StrTran(cLink,"<<CEP>>",cCep) BEGIN SEQUENCE Try oOle := CreateObject("Msxml2.XMLHTTP.3.0") oOle:Open("GET",cLink,.F.) oOle:Send() cXml := oOle:ResponseBody oOle := nil Catch BREAK End //verifica se não encontrou o cep atraves tag "erro" oXml := TXmlDocument():New(cXml) oTag := oXml:findFirst("erro") If !Empty(oTag) .and. oTag:cData == "true" MsgStop("CEP não encontrado !") BREAK Endif oTag := oXml:findFirst("logradouro") cLog := IIF(Empty(oTag),'',oTag:cData) oTag := oXml:findFirst("complemento") cComple := IIF(Empty(oTag),'',oTag:cData) oTag := oXml:findFirst("bairro") cBairro := IIF(Empty(oTag),'',oTag:cData) oTag := oXml:findFirst("localidade") cCidade := IIF(Empty(oTag),'',oTag:cData) oTag := oXml:findFirst("uf") cUf := IIF(Empty(oTag),'',oTag:cData) XBrowse({cLog,cComple,cBairro,cCidade,cUf}) END SEQUENCE Return {cLog,cComple,cBairro,cCidade,cUf} Pesquisa de CEP OnLine! Theotokos and aferra 2 Quote Link to comment Share on other sites More sharing options...
Jmsilva Posted November 6, 2019 Author Report Share Posted November 6, 2019 Function ViaCep() Local oOle,cJSon,cCep := "91312001" Local cLink := "http://viacep.com.br/ws/<<CEP>>/json/" Local hResp := Hash() cLink := StrTran(cLink,"<<CEP>>",cCep) BEGIN SEQUENCE Try oOle := CreateObject("Msxml2.XMLHTTP.3.0") oOle:Open("GET",cLink,.F.) oOle:Send() cJSon := oOle:ResponseBody oOle := nil Catch BREAK End HB_JsonDecode(cJSon,@hResp) IF HHasKey(hResp, "erro" ) MsgStop("Cep não localizado !") Endif XBrowse(hResp) END SEQUENCE Return hResp #BoasPraticas aferra 1 Quote Link to comment Share on other sites More sharing options...
Jmsilva Posted July 1, 2020 Author Report Share Posted July 1, 2020 Boas práticas de hj é sobre pesquisa INCREMENTAL em TBrowse com uso BackGound - Rotina em segundo plano. Tenho interesse por processamento paralelo e BackGround, o primeiro não consegui ainda, sei que tem parâmetros para incluir na compilação, mas não deu certo, o segundo consegui, no caso a rotina abaixo está rodando tbrowse() em uma tabela 'temp' indexada por nome, ao precionar F3 abre get para digitar e o conteúdo GET vai "Refresh() ando" no Browse. Se curtiu tecle "Joinha" oTB:ForceStable() nKEY := Inkey(0) IF nKEY == K_ESC EXIT ELSEIF nKEY == K_F3 /*processamento em segundo plano*/ HB_IdleAdd( {|| HB_BackGroundRun() } ) nTask := HB_BackGroundAdd( {|| RefreshTB(oTB) }, 1000 ) SET BACKGROUND TASKS ON /*------------------------------*/ cChave := Space(35) //BOX3DOF(14,16,18,58) @ 14,16 clear to 18,58 DispBox(14,16,18,58,2,"n/b") @ 16,20 GET cChave PICT "@!" READ HB_BackGroundDel( nTask ) oTB:RefreshAll() Endif **---------------------------------------------------------------------- Function RefreshTB(oTB) //fica rodando BackGround **---------------------------------------------------------------------- Local cTela,oGet:=GetActive() Static cLast := '' If HB_IsObject(oGet) .and. cLast != oGet:buffer cTela := SaveScreen(14,16,18,58) TEMP->(DBSEEK(oGet:buffer,.T.)) oTB:RefreshAll() oTB:ForceStable() Restscreen(14,16,18,58,cTela) cLast := oGet:buffer oGet:SetFocus() Endif Return .t. xHarbour/Harbour, FiveWin, SqlRdd e Pelles C - Editor xEdit Valdir and evertonlb 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.