Variables
En este tópico se recomienda utilizar convenciones en la declaración, inicialización y utilización de variables. La estandarización de estos asuntos aumenta la comprensión y el mantenimiento del código fuente.
Notación húngara
La notación húngara tiene como objetivo facilitar el reconocimiento del tipo de variable en un código fuente. La adopción de este criterio de denominación es bastante práctica e intuitiva, cuya idea básica es denominar todos los tipos de variables, con el fin de simplificar la comprensión. Para ello, debe agregarse un prefijo al nombre de la variable. Este prefijo será en letra minúscula y de acuerdo con su tipo de contenido. Denotaciones:
- "a" - Array.
- "b" - Bloque de código.
- C - Carácter.
- D - Fecha.
- "l" - Lógico.
- N - Numérico.
- "o" - Objeto.
- "u" - Indefinido.
Ejemplo:
// VariableDeclaration.prw
#INCLUDE "TOTVS.CH"
Function VariableDeclaration()
Local aArray := {}
Local bFormula := {||}
Local cName := ""
Local dData := CToD("01/01/01")
Local lLogical := .T.
Local nNumeric := 0
Local oObject := Nil
Local uUndefined := Nil
Return
Cantidad por línea
Las variables nunca deben declararse en la misma línea, independientemente de la cantidad o de si todas son del mismo tipo. Esto garantiza una mejor visualización y un espacio para comentarios. Por lo tanto, las variables deben declararse juntas verticalmente, pero en líneas separadas.
Posición
La posición de las variables es importantísima, todas deben quedar unidas verticalmente pero separadas por lo menos por un espacio en la parte inferior. Esto determinará que se forme un único bloque de variables, fácil de encontrar. La posición del bloque debe ser al inicio de la función o en una estructura de condición/repetición.
// VariablePosition.prw
#INCLUDE "TOTVS.CH"
Function VariablePosition()
Local cVar1 := ""
Local cVar2 := ""
Local cVar3 := ""
// Haz algún procesamiento
Return
Inicialización
Todas las variables deben inicializarse en su declaración. Según el estándar, los siguientes tipos de variables deben inicializarse con los siguientes contenidos:
- Array.
- {}
- Bloque de código.
- {||}
- Carácter.
- ""
- Fecha.
- DToC("//")
- Lógico
- .F. o .T.
- Numérico
- 0
- Objeto
- Nil
- Indefinido
- Nil
Formato de tipo
Los tipos de variables (arrays y cadena de caracteres larga), pueden ser complejos y si no se formatean de modo lógico y estructurado, resultan difíciles de leer. Para estos casos debe utilizarse un formato que siga una estructura lógica.
Arrays
Los Arrays pueden tener tanto estructuras simples como estructuras complejas y en ambos casos si no existe un formato claro y legible, su programación y mantenimiento pueden resultar difíciles y ocasionar problemas. En el momento de la atribución de valores en arrays, recomendamos el uso del formato horizontal para que quede claro para el lector cómo es la estructura de dimensiones del array:
// FormattingOfArrayType.prw
#INCLUDE "TOTVS.CH"
Function FormattingOfArrayType()
Local aMultiDimensionalArray := { {"A" ,1 },;
{"B" ,2 },;
{"C" ,3 }}
Local aCommentedArray := { "A",; // A
"B",; // B
"C"} // C
Return
Cuando se utiliza el array para representar un mapeo de clave y valor, y se define su tamaño, sugerimos la utilización de defines para denominar las posiciones del array:
// FormattingOfArrayMapType.prw
#INCLUDE "TOTVS.CH"
#DEFINE INFORMATION1 1
#DEFINE INFORMATION2 2
#DEFINE INFORMATION3 3
Function FormattingOfArrayMapType()
Local aMultiDimensionalMapArray := { "A", "B", "C" }
Local aCommentedMapArray := { "A",; // Información 1
"B",; // Información 2
"C"} // Información 3
ConOut("Información 1: " + CValToChar(aMultiDimensionalMapArray[INFORMATION1]))
ConOut("Información 2: " + CValToChar(aMultiDimensionalMapArray[INFORMATION2]))
ConOut("Información 3: " + CValToChar(aMultiDimensionalMapArray[INFORMATION3]))
Return
Cadena de caracteres
Una cadena de caracteres (o string) se utiliza principalmente para tres objetivos:
- Nombres de campos, parámetros y tablas (datos en general).
- Identificadores.
- Frases, mensajes, palabras que tengan como objetivo final el usuario.
Para nombres de campos, parámetros, alias de tablas e identificadores, el formato recomendado es la letra capital homogénea en mayúsculas.
Ejemplos:
- "UA_CODIGO";
- SA1
- MV_CLIPAD
En todos los casos, los strings siempre deben atribuirse con la utilización de comillas.
Para frases, mensajes, palabras que tengan como objetivo final el usuario, se recomienda el uso del string completo, y si es necesario que haya contenidos variables en medio del mensaje, la utilización de la función I18N, como por ejemplo:
// I18NUse.prw
#INCLUDE "TOTVS.CH"
Function I18NUse()
Local nRandom1 := Randomize(1, 10)
Local nRandom2 := Randomize(1, 10)
ConOut(I18N("Los números: #1[first number]# e #2[second number]# se generaron randómicamente.", {nRandom1, nRandom2}))
Return
Salida:
Los números: 3 y 5 se generaron randómicamente.
<Colocar un enlace para la sesión de internacionalización, localización y traducción>
Funciones
En las funciones, tanto la declaración como la llamada deben realizarse utilizando la letra capitular heterogénea. No debe haber espacio entre el paréntesis y el parámetro, y debe haber un espacio adicional solamente después de la coma que divide los parámetros.
Cuando haya más de 8 parámetros recibidos. Deben separarse de 8 en 8, 8 en la línea de declaración de la función, 8 en la otra línea, alineados con los anteriores y así sucesivamente.
// FormattingOfFunction.prw
#INCLUDE "TOTVS.CH"
Function FewParameters(cPar1, cPar2, cPar3, cPar4, cPar5)
// Llama PlentyParameters
PlentyParameters( cPar1, cPar2, cPar3, cPar4, cPar5, cPar6, cPar7, cPar8 ,;
cPar9, cPar10, cPar11,cPar5, cPar6, cPar7, cPar8 )
Return
Function PlentyParameters( cPar1, cPar2, cPar3, cPar4, cPar5, cPar6, cPar7, cPar8 ,;
cPar9, cPar10, cPar11,cPar5, cPar6, cPar7, cPar8 )
// Llama FewParameters
FewParameters(cPar1, cPar2, cPar3, cPar4, cPar5)
Return
Clases
La declaración de clases sigue el mismo principio de la declaración de funciones, pero con algunos adicionales.
En el bloque de declaración de la clase, aunque no sea necesario sintácticamente, es importante informar y mantener actualizada la lista de los parámetros existentes, así como también, la información sobre el retorno.
// FormattingOfClasses.prw
#INCLUDE "TOTVS.CH"
Class FormattingOfClasses
Data cProperty1
Data cProperty2
Data cProperty3
Method New(cVar1, cVar2) // Constructor, retorna Self
Method MethodA(cVar1, cVar2) // Retorna numeric
Method MethodB() // Retorna string
ENDCLASS
Method New(cVar1, cVar2) Class FormattingOfClasses
Self:cProperty1 := ""
Self:cProperty2 := ""
Self:cProperty3 := ""
Return Self
Method MethodA(cVar1, cVar2) Class FormattingOfClasses
Return 0
Method MethodB() Class FormattingOfClasses
Return "ABC"
Queries
Como regla general para queries, siempre debe prestarse atención en el espacio entre los comandos y las comillas. De esta manera se evitan errores después de la reunión de todo el comando en una única string.
Construcción simples
Cuando la construcción de una query sea simple, utilice el formato horizontal de la misma manera como se utiliza en la construcción de funciones y clases. Por ejemplo:
// SimpleQuery.prw
#INCLUDE "TOTVS.CH"
Function SimpleQuery()
Local cQuery := ""
RpcSetEnv("99", "01")
cQuery := "SELECT A1_CGC,A1_LOJA,R_E_C_N_O_ " +;
" FROM " + RetSQLName("SA1") +;
" WHERE A1_FILIAL ='" + XFilial("SA1") + "' AND " +;
" A1_LOJA = '01' AND " +;
" D_E_L_E_T_=''" +;
" ORDER BY A1_NOME"
ConOut(cQuery)
Return
Construcción condicional
En la construcción condicional de queries es importante que se mantengan agrupadas en un bloque secuencial. No permita que procesamientos o comandos que se no se refieran al montaje de la query estén intercalados en el bloque de montaje de query.
// ConditionalQuery.prw
#INCLUDE "TOTVS.CH"
Function ConditionalQuery()
Local cQuery := ""
Local lOnlyNotDeleted := .T.
RpcSetEnv("99", "01")
cQuery := "SELECT A1_CGC,A1_LOJA,R_E_C_N_O_ " +;
" FROM " + RetSQLName("SA1") +;
" WHERE A1_FILIAL ='" + XFilial("SA1") + "' AND " +;
" A1_LOJA = '01' AND " +
If lOnlyNotDeleted
cQuery += " D_E_L_E_T_=''"
EndIf
cQuery += " ORDER BY A1_NOME"
ConOut(cQuery)
Return
Embedded SQL
El formato aplicado en el embedded SQL es igual al formato horizontal estándar y por ser un comando, debe tener la letra capital heterogénea:
// EmbeddedSQLQuery.prw
#INCLUDE "TOTVS.CH"
Function EmbeddedSQLQuery()
BeginSQL Alias cAliasTrb
SELECT R_E_C_N_O_ RECNOSN1
FROM %Table:SN1%
WHERE N1_FILIAL = %XFilial:SN1% AND
N1_CBASE >= %Exp:MV_PAR01% AND
N1_CBASE <= %Exp:MV_PAR02% AND
N1_ITEM >= %Exp:MV_PAR03% AND
N1_ITEM <= %Exp:MV_PAR04% AND
N1_GRUPO >= %Exp:MV_PAR05% AND
N1_GRUPO <= %Exp:MV_PAR06% AND
N1_AQUISIC >= %Exp:MV_PAR07% AND
N1_AQUISIC <= %Exp:MV_PAR08% AND
%Exp:cWhere% AND
%NotDel%
EndSQL
Return
Nombres largos
El lenguaje ADVPL soporta el tamaño máximo de 10 caracteres para nombres de funciones, métodos, variables y comandos de procesamiento previo. La única excepción es el nombre de clase que no tiene límite.
Para minimizar el impacto de esta limitación, no recomendamos que se abrevie el nombre, recomendamos que se invierta el nombre, para que la palabra que diferencia las dos funciones esté al inicio del nombre, por ejemplo:
En lugar de:
- OpNTaxRece() // Open No Tax Receipt (Abre comprobante no fiscal).
- ClBoNTaxRe() // Close Bound No Tax Receipt (Fecha comprobante no fiscal vinculado).
Utilizar:
- OpenNoTaxReceipt() // Open No Tax Receipt (Abre comprobante no fiscal).
- CloseBoundNoTaxReceipt() // Close Bound No Tax Receipt (Fecha comprobante no fiscal vinculado).
En lugar de:
- OpenNoTaxReceipt() // Abre comprobante no fiscal.
- OpenNoTaxReceiptBound()// Abre comprobante no fiscal vinculado.
Utilizar:
- OpenNoTaxReceipt() // Abre comprobante no fiscal.
- OpenBoundNoTaxReceipt()// Abre comprobante no fiscal vinculado.