Buenas Practicas de GeneXus !
Tabla de Contenidos
Tabla de Contenidos
- Definición de nombres
- Dominios enumerados
- Identación y espaciado
- Structured Data Types
- Strings
- Comentarios
- Comandos y funciones
- Parámetros
- Recursos
- Empresas que utilizan esta guia
- Traducciones
- Colaboradores
- Licencia
- Modificaciones al documento
Definición de nombres
- 1.1 Se debe ser descriptivo con los nombres.Se intenta que el nombre sea autodescriptivo.
// mal Proc: CliCre // bien Proc: ClienteCrear
- 1.2 Utilizar PascalCase al nombrar objetos, atributos y variables.
// mal clientecrear // bien ClienteCrear
- 1.3 No utilizar underscore al inicio o final en ningún tipo de objeto, atributo o variable.Esto puede hacer suponer a un programador proveniente de otros lenguajes que tiene algún significado de privacidad.
// mal &_CliNom = "John Doe" &CliNom_ = "John Doe" Proc: _ClienteCrear // bien &CliNom = "John Doe"
- 1.4 Nombrar los dominios enumerados sin abreviar, comenzando con la entidad en singular y siguiendo con el calificador enumerado también en singular. Los valores enumerados también se deben especificar en singular.Esto es para facilitar la definición de atributos y variables basadas en un dominio (GeneXus lo hará automáticamente).
// mal DocumentosTipo DocumentosTipos DocTipos // bien DocumentoTipo {Venta,Compra,etc} DocumentoModo {Credito, Débito}
- 1.5 Nombrar procedimientos relacionados mediante Entidad + Atributo(depende el caso) + Complemento + Acción.Esto permite agrupar los objetos de la misma entidad en la selección de objetos entre otros. Algunas acciones típicas son Get, Set, Load (para SDT), Insert, Utpdate, Delete, etc. La diferencia entre Set y Update es que Set refiere a un atributo y Update a una entidad.
// mal CreCli UpsertCliente FechaCliente // bien ClienteUpsert ClienteEliminar ClienteFechaModificadoGet ClienteFechaModificadoSet DocumentoRecalculo
- 1.6 Utilizar nomenclatura GIK para nombrar atributos. Se pueden crear atributos sin el límite de los 3 caracteres si el nombre no supera los 20 caracteres y mejora la comprensión.Estandard desde los inicios de GeneXus.
// mal CreCliFch FechaCreadoCliente // bien CliFchCre // mejor ClienteFechaCreado
- 1.7 Las transacciones deben tener el nombre de la entidad en singular.Se define así porque en la comunidad GeneXus está claro que queda mejor a la hora de trabaja por ejmeplo con Business Component. También es requerimiento de algunos patterns GeneXus para su correcta visualización (ej.: K2BTools).
// mal Trn:Articulos Trn:Clientes // bien Trn:Cliente Trn:Articulo
Identación y espaciado
- 2.1 Utilizar tabuladores (tab) en lugar de "espacios". De esta forma, cada uno puede visializar la cantidad de espacioes que prefiera, ya que se configura en GeneXus.La identación ofrece a los desarrolladores una mejor lectura del código fuente. Si tomamos una identación estandard, facilitará al resto entednder el código fuente.
// mal if &DocumentoTipo = DocumentoTipos.Venta msg("Venta") endif // mal if &DocumentoTipo = DocumentoTipos.Venta msg("Venta") endif // bien if &DocumentoTipo = DocumentoTipos.Venta msg("Venta") endif
- 2.2 Se deben identar las condiciónes y comandos dentro de un for each.
// mal for each where DocumentoTipo = DocumentoTipos.Venta ... endfor // mal for each defined by ClienteNombre ... endfor // bien for each where DocumentoTipo = DocumentoTipos.Venta ... endfor
- 2.3 Si en un for each se especifican where, defined by ú otros, dejar una línea en blanco antes del código.
// mal for each where DocumentoTipo = DocumentoTipos.Venta if DocTot > LimCreMto ... endif endfor // mal for each defined by ClienteNombre for each Documentos ... endfor endfor // bien for each where DocumentoTipo = DocumentoTipos.Venta if DocTot > LimCreMto ... endif endfor // bien for each defined by ClienteNombre for each Documentos ... endfor endfor
- 2.4 Dejar un espacio antes de cada parámetro.Hace a la sentencia más sencilla de leer.
// mal parm(in:PaiId,out:&PaiNom); // bien parm( in:PaiId, out:&PaiNom); // mal &Fecha = ymdtod(2017,01,01) // bien &Fecha = ymdtod( 2017, 01, 01)
Dominios enumerados
- 3.1 Evitar la utilización de textos/números fijos cuando pueden existir multiples valores.Simplificar la lectura y no necesitar recordar el texto específico de cada opción.
// mal if &HttpResponse = "GET" // bien // Crear un dominio enumerado HTTPMethods con los posibles valores ( POST, GET) if &HttpResponse = HTTPMethods.Get
Structured Data Types
- 4.1 Utilizar New() en la creación de SDT en lugar de Clone(). Incluso antes de utilizar el SDT por primera vez en lugar de al final (aunque GeneXus lo soporte).Queda claro que se está trabajando con un nuevo item.
// &Cliente SDT:Cliente // &Clientes lista de SDT:Cliente // mal for each Clientes &Cliente.CliNom = CliNom &Clientes.Add( &Cliente.Clone() ) endfor // bien for each Clientes &Cliente = new() &Cliente.CliNom = CliNom &Clientes.Add( &Cliente ) endfor
- 4.1 Desde que GeneXus permite definir variables como listas, evitar crear SDT del tipo lista.Al definir la variable del item particular, se lo marca como lista.
// mal SDT:Clientes : Lista ClienteItem CliNom // bien SDT:Cliente CliNom
Strings
- 5.1 Utilizar format para desplegar mensajes conteniendo datos.Si la aplicación se va a traducir en diferentes lenguajes no hay que re-programar los mensajes.
// mal &Msg = "El cliente Nro." + &CliId.ToString() + " se llama " + &CliNom // bien &Msg = format( "El cliente Nro. %1 se llama %2", &CliId.ToString(), &CliNom)
- 5.2 Utilizar !"" para strings que no deben ser traducidos.Un traductor puede modificar constantes o códigos específicos del sistema y pueden afectar el funcionamiento, por ejemplo parámetros.
// mal &ParVal = ParamGet( "GLOBAL ENCRYPT KEY") // bien &ParVal = ParamGet( !"GLOBAL ENCRYPT KEY")
Comentarios
- 6.1 Utilizar
/** ... */
para comentarios multi-línea.// mal // CrearCliente crea una nuevo cliente // según las variables: // &CliNom // &CliDir sub 'CrearCliente' // ... endsub // bien /** * CrearCliente crea una nuevo cliente * según las variables: * &CliNom * &CliDir */ sub 'CrearCliente' // ... endsub
- 6.2 Utilizar
//
para comentarios de una sola línea. Estos comentarios deben estar una línea antes del sujeto a comentar. Dejar una línea en blanco antes del comentarios a no ser que seal la pimer línea del bloque.// mal &CliNom = "John Doe" // Se asigna el nombre a la variable // bien // Se asigna el nombre a la variable &CliNom = "John Doe" // mal sub 'CrearCliente' msg( "Creando cliente", status ) // Se crea el cliente &ClienteBC = new() &ClienteBC.CliNom = "John Doe" &ClienteBC.Save() endsub // bien sub 'CrearCliente' msg( "Creando cliente", status ) // Se crea el cliente &ClienteBC = new() &ClienteBC.CliNom = "John Doe" &ClienteBC.Save() endsub // también está bien sub 'CrearCliente' // Se crea el cliente &ClienteBC = new() &ClienteBC.CliNom = "John Doe" &ClienteBC.Save() endsub
- 6.3 Comenzar todos los comentarios con un espacio para que sean sencillos de leer.
// mal //Está activo &IsActive = true // bien // Está activo &IsActive = true // mal /** *Se obtiene el nombre de la empresa *para luego desplegarlo */ &EmpNom = EmpresaNombreGet( &EmpId) // bien /** * Se obtiene el nombre de la empresa * para luego desplegarlo */ &EmpNom = EmpresaNombreGet( &EmpId)
- 6.4 Agregar pefijos en los comentarios con
FIXME
oTODO
ayudan a otros desarrolladores a entender rapidamente si se está ante un posible problema que necesita ser revisado o si se está sugiriendo una solución a un problema existente. Estos son diferentes a los comentarios regulares porque conllevan a acciones. Estas acciones sonFIXME: -- necesita resolverse
orTODO: -- necesita implementarse
.
- 6.5 Usar
// FIXME:
para marcar problemas.// FIXME: Revisar cuando &Divisor es 0 &Total = &Dividendo / &Divisor
- 6.6 Usar
// TODO:
para marcar implementaciones a realizar.// TODO: Implementar la subrutina sub "CrearCliente" endsub
Comandos y funciones
- 7.1 Utilizar minúsculas al nombrar comandos y funciones del sistema.Esto optimiza el desarrollo ya que los comandos y funciones provistas por el lenguaje se utilizan tan frecuentemente y no es necesario especificarlos en PascalCase.
// mal For Each Where CliCod = &CliCod Msg(CliNom) EndFor // bien for each where CliCod = &CliCod msg(CliNom) endfor // mal &Fecha = YmdToD( 2017, 01, 01) // bien &Fecha = ymdtod( 2017, 01, 01)
- 7.2 Utilizar do case siempre que se pueda a fín de sustituir if anidados. Dejar un espacio entre cada bloque de case.
// mal if &DocTipo = DocumentoTipos.Venta ... else if &DocTipo = DocumentoTipos.Compra ... endif endif // también mal do case case &DocTipo = DocumentoTipos.Venta ... case &DocTipo = DocumentoTipos.Compra ... endcase // bien do case case &DocTipo = DocumentoTipos.Venta ... case &DocTipo = DocumentoTipos.Compra ... otherwise ... endcase // también está bien - Cuando existen multiples case y la acción es de una sola línea. >This facilitates read all the options without having to scroll do case case &Action = Action.Update do 'DoUpdate' case &Action = Action.Insert do 'DoInsert' case &Action = Action.Regenerate do 'DoRegenerate' case &Action = Action.Clean do 'DoClean' case &Action = Action.Refresh do 'DoRefresh' case &Action = Action.Reload do 'DoReload' otherwise do 'UnexpectedAction' endcase
- 7.3 Utilizar clausula where en comandos for each en lugar de usar comandos "if", siempre que se trate de atributos de la tabla extendida.Con esto logramos trasladar la condición al DBMS y hacer que forme parte de la query select evitando trabajar con grandes volumenes de datos en el servidor de aplicación ó eventualmente en el cliente.
// mal for each Documentos if DocTipo = DocumentoTipos.Ventas ... endif endfor // bien for each where DocTipo = DocumentoTipos.Ventas ... endfor
- 7.4 Utilizar "when" en comandos for each para simplificar la query enviada al DBMS.
// mal for each Documentos where DocTipo = DocumentoTipos.Ventas where DocFch >= &FchIni or null(&FchIni) ... endfor // bien for each where DocTipo = DocumentoTipos.Ventas where DocFch >= &FchIni when not &FchIni.IsEmpty() ... endfor
Parámetros
- 8.1 Utilizar SDT en lugar de multiples parámetros.
La lectura queda confusa y cuando se modifican los parámetros hay que revisar todos los llamadores. Esto algunas veces no es posible, por ejemplo en webpanels.
```javascript
// mal
parm( in:&CliNom, in:&CliApe, in:&CliTel, in:&CliDir, in:&CliDOB)
// bien
parm( in:&sdtCliente )
```
Recursos
- GeneXus Wiki - GeneXus
- GeneXus Training - GeneXus
- GeneXus Developpers - GeneXus
Empresas que utilizan esta guia
Esta es una lista de las empresas que están utilizando esta guia de desarrollo. This is a list of organizations that are using this style guide. Haganos saber si su empresa utiliza esta guia o un fork de la misma y lo agregaremos.
Comentarios
Publicar un comentario