martes, octubre 01, 2019
Imprimir en WEB
En la carpeta weapps del apache creé la carpeta pdfs donde genero las factura que genera el programa. Ese path lo guardo en la base de datos en una tabla de parámetros. Entonces cuando voy a imprimir la factura obtengo ese path y lo concateno con el nombre que le voy a poner al pdf y lo cargo en una variable para pasárselo como parámetro al reporte.
&archivopdf=Path+”NombreArchivoPDF.pdf”
ReFactura.Call(par1,par2, ...,&archivopdf) // Con esto genero el pdf en “C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\pdfs”
En otro campo de la tabla parámetros tengo guardada la Url en la cual voy a buscar el archivo pdf que necesito abrir en el navegador para imprimir, eso junto con el nombre del archivo lo concateno y lo guardo en una variable, que voy a utilizar en el Java Script para imprimirlo.
&url=Url+”NombreArchivoPDF.pdf” // Concateno la url al archivo “http://localhost:8080/pdfs/” +”NombreArchivoPDF.pdf”
JS.caption = '<script language="JavaScript">'
JS.caption += "var myWindow=window.open('"+ trim(&url) +"','','left=100,top=150,height=700,width=1024,dependent=yes,scrollbars=Yes,resizable=Yes,toolbar=no,menubar=no');"
JS.caption += 'myWindow.focus();'
JS.caption += 'myWindow.print();'
JS.caption += '</script>'
El JS abre la ventana para mostrar el pdf e inmediatamente lo manda a imprimir mostrando la vista previa de impresión. Obviamente Sustituir localhost y el puerto por el servidor web en el que se encuentre el sistema.
Existe Otra Alternativa:Tambien hay un plug-in de JQuery que trabaja en IE, Edge, Chrome y Firefox: https://github.com/posabsolute/jQuery-printPage-plugin
En Chrome y Edge se muestra una pantalla de seleccion para escojer la impresora. Este plug-in ha existido por una decada y se fue actualizado updated un par de años atras
Gracias a Pablo Plá Marzano del foro de GX.
viernes, mayo 04, 2018
Optimizando Tomcat7 en Linux CENTOS
Dispongo en la actualidad de un servidor con las siguientes caracteristicas:
1.- 2GB de Ram
2.- 100GB de disco.
Conocer el tamaño de memoria del servidor:
free -m cat /proc/meminfo
Conocer version del sistema operativo:
rpm --query centos-release
cat /etc/centos-release
cat /etc/os-release
cat /etc/system-release
cat /etc/redhat-release
He procedido a instalar Tomcat7 con OpenJdk7.
Al inicio se presentaba una serie de dificultades, el rendimiento no fue muy bueno, en virtud de ello se procedió a realizar los siguientes cambios.
Parámetros de la JVM
- -Djava.awt.headless=true
- -Xms256m
- -Xmx768m
- -XX:MaxPermSize=256m
- -DGEOEXPLORER_DATA
-Djava.awt.headless=true
Esta opción valor true le indica a Java que trabajaremos sin interfaz gráfica.-Xms256m -Xmx768m
Con estos parámetros definiremos el tamaño del heap o memoria que Java. Los objetos de Java residen en una zona llamada heap. El heap se crea cuando la JVM se inicia y puede aumentar o disminuir de tamaño mientras se ejecuta la aplicación. Cuando la pila se llena, se recoge la basura, se inicia el proceso del Garbage Collector. Durante la recogida de basura, los objetos que ya no se utilizan se borran, con lo que se crea espacio para los nuevos objetos.Algunas recomendación será que en producción es interesante que Xmx (Máximo tamaño del heap) y Xms (Mínimo tamaño del heap) sean idénticos.
-XX:MaxPermSize=256m
La JVM tiene un espacio permanente para alojar objetos, el Permanent Generation. Será el espacio dinde se alojan las clases y los métodos.Se ha deprecado esta opción en Java 8 cambiándola por el Metaspace del que podremos definir el > tamaño máximo que podrá ocupar de la memoria del servidor.
Aplicar parámetros a la JVM.
Antes de aplicar los parámetros, realizaremos la misma prueba anterior con JMeter para comprobar el rendimiento sin estos. Para ver las opciones con las que está trabajando tomcat podremos ejecutar:
ps -ef | grep tomcat7
Donde podremos observar que tiene una memoria máxima por defecto
Para aplicar los parámetros anteriores, podremos utilizar varios métodos.
Uno de ellos será definir un archivo setenv.sh en la carpeta $TOMCAT_HOME/bin con la siguiente estructura:
#!/bin/bash
export JAVA_OPTS="-Djava.awt.headless=true -Xms1024m -Xmx1024m"
service tomcat7 restart
Comprobamos las modificaciones.
ps -ef | grep tomcat7
Modificar Numero de Conexiones.
<Connector
port="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="600000"
redirectPort="8443"
enableLookups="false"
maxThreads="1500"
compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
compression="on"/>
Reiniciar el tomcat
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="600000"
redirectPort="8443"
enableLookups="false" maxThreads="1500"
compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
compression="on"/>
Fuente: https://www.enmimaquinafunciona.com/pregunta/2454/apache-tomcat-ahoga-despues-de-300-conexiones
Fuente: https://www.enmimaquinafunciona.com/pregunta/2454/apache-tomcat-ahoga-despues-de-300-conexiones
Referencias:
Optimizar el Tomcat
Optimizar Tomcat
miércoles, febrero 21, 2018
Configurar Generador client.cfg
Tomado de: Configurar CLIENT.CFG
Introducción
Muy a menudo, debe editar client.cfg para actualizar la información; por ejemplo, cuando pone una aplicación en producción y no conoce los datos de conexión, usuario, contraseña, etc.
Otro caso típico en el que debe editar este archivo es cuando está monitoreando el grupo de conexiones mientras 'ajusta' su configuración, cambiando el tamaño, los minutos de reciclaje.
Aunque se trata de un archivo de texto, un usuario que no lo conoce tiene dificultades para identificar las claves de las propiedades que desea modificar. Esta es la razón por la cual se implementó la utilidad de configuración del cliente. Permite actualizar client.cfg independientemente de GeneXus, utilizando una interfaz más amigable que permite identificar cada una de las opciones.
Descripción
Para entornos Windows, puede llamarlo desde GeneXus usando el 'Menú desarrollador' - menú 'Utilidades' - opción 'Configuración de cliente de aplicación'
También puede llamarlo manualmente; asegúrese de tener los archivos client.cfg, GxUtils.jar y gxclassr.zip en una carpeta específica. Luego, en una consola, ejecute el siguiente comando:
java -cp GxUtils.jar;.;gxclassr.zip;swt.jar com.genexus.ClientConfig
domingo, diciembre 17, 2017
Tomcat 7 y Genexus
Tomado de: Tomcat7 y Genexus Blog de configuracion de Genexus y Tomcat7 WebSAc Tomcat7 Consulta stackoverflow sobre tomcat7 Tomcat 7 tiene un cambio importante a nivel de seguridad que afecta la prototipación de aplicaciones generadas con Java. Para mostrar los servlets de los objetos GeneXus, se utiliza una clase llamada servlet invoker que permite ejecutar todos los servlets generados. En Tomcat 7, como cumple con la especificación de servlet 3.0, ya no se soporta dicho mecanismo de ejecución y los mismos deben ser declarados. Por defecto al prototipar con Tomcat 7 se detalla el siguiente error: 404 "resource not found" Se describe en este sac, algunos puntos a tener en cuenta para trabajar con Tomcat 7. Descripción Detallada Cuando se trabaja con Tomcat 7 se debe tener en cuenta lo siguiente: _ Asegurarse que la propiedad "use annotations for servlet definition" en web information se habilita (valor "Yes"). _ Utilizar la propiedad Java Package name y especificar un valor. A partir de Tomcat 7, todos los servlets se tienen que generar con un metatag llamado WebServlet. Cuando la webapp levanta, el tomcat recorre todas las clases de la aplicación para ver cuáles tiene ese tag para determinarlos como servlets a ejecutar. Es recomendable que todos los servlets tengan package; si los mismos tienen package, la aplicación es ejecutable. Por compatibilidad, si no se utiliza "Java package name", igualmente GeneXus creará en la WebApp un folder vacío, de nombre 'dummy' para que la aplicación sea ejecutable; de lo contrario, el error 404 "resource not found" se detalla en el browser. En algunos build de tomcat 7 ,como el (7.0.35), al hacer deploy de una aplicación que no utiliza el gam se genera un error HTTP 404 , dicho error genera este log en el tomcat: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/tomcat_error_foroJavaEnvironment]] Caused by: java.lang.NoClassDefFoundError: artech/security/api/gamrefreshtoken Este problema se ha debido a que en las clases standars (gxclassR.jar) se hace referencia por reflexión a servlets del gam, y en caso de no tener el jar del GAM ( artech.security-<DBMS>.jar ) en la aplicación se genera el error anterior. En el upgrade 2 se arreglan este error, y en el U1 se puede trabajar utilizando el work around descripto a continuación. Work Around Para evitar el error HTTP 404: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/tomcat_error_foroJavaEnvironment]] Caused by: java.lang.NoClassDefFoundError: artech/security/api/gamrefreshtoken hay que hacer 2 cosas. 1- entrar al archivo de configuración del tomcat Tomcat 7.0\conf\catalina.properties y en la propiedad tomcat.util.scan.DefaultJarScanner.jarsToSkip agregar el jar gxclassR.jar. Se puede agregar *.jar que mejora la performance, pero si existen otra aplicaciones distinta de genexus con servlets referenciados desde el jar que se deben levantar estas aplicaciones van a fallar. Esto es para evitar que se scanee el jar para buscar annotations. 2- Modificar el web.xml que esta en el web-inf de la aplicacion (\Tomcat 7.0\webapps\<carpetadelaAplicacionenTomcat>\WEB-INF) y quitar la siguientes lineas <servlet> <servlet-name>GXOAuthAccessToken</servlet-name> <servlet-class>com.genexus.webpanels.GXOAuthAccessToken</servlet-class> </servlet> <servlet-mapping> <servlet-name>GXOAuthAccessToken</servlet-name> <url-pattern>/oauth/access_token</url-pattern> </servlet-mapping> Este web.xml se genera cada vez que se corre la aplicación , así que cada ves que se corre la aplicación hay que modificarlo. Para evitar esto se puede modificar el web7.xml que esta en el target enviroment , si se modifica este web.xml solo se precisa modificarlo una vez dado que el otro web.xml se crea a partir de este , pero si se pasa a usar el gam hay que volver a escribir las lineas que se borraron. | |||||||||||||||||||||||||||
lunes, septiembre 04, 2017
Programas de Mensajeria.
Para temas de mensajeria interna es muy importante considerar estas alternativas libres.
* Openfire facil de instalar, ademas posee su propio cliente para los sistemas operativos Linux y Windows.
Mac (Spark): https://www.igniterealtime.org/projects/openfire/ * Rocket que tiene un muy buen conjunto de características y clientes nativos para IOS y android, esta basado en Node.js.
https://rocket.chat/
https://rocket.chat/docs Dirigirse a la parte de instalaciones, donde se detalla las alternativas
Para instalar revisar este LINK:
Como instalar Rocket
Como integrar con ZIMBRA
Blog de Jorge de la Cruz conocer de varios topicos
Instalando en Rocket Chat en Centos.
Tutorial Rocket Chat en Centos7 - Ingles
Instalar Rocket Chat en Centos7 - ingles
viernes, mayo 05, 2017
Imprmir HTML como Texto.
Tomado del Foro de genexus:
Al utilizar FCKEditor.
Procedure con main protocol Http
&HttpResp, es de tipo HttpResponse
&HttpResp.AddHeader('Content-type', 'text/html; charset=charset=ISO-8859-1')
&HttpResp.AddHeader('Content-Disposition', 'attachment;filename='+ 'Contrato_' + trim(&Nro.ToString()) + '.doc')
&HttpResp.AddHeader('Content-type', 'application/vnd.text')
&HttpResp.AddString('<HTML>')
&HttpResp.AddString('<HEAD>')
&HttpResp.AddString('<META content="text/html; charset=utf-8" http-equiv="Content-Type" />')
&HttpResp.AddString('<STYLE />')
&HttpResp.AddString('</HEAD>')
&HttpResp.AddString('<BODY>')
&Celda='<TABLE>'
do 'Next'
&Celda = &Datos // datos guardados con FCKEditor
do 'Next'
&Celda='</TABLE>'
do 'Next'
&HttpResp.AddString('</BODY>')
&HttpResp.AddString('</HTML>')
Sub 'Next'
&HttpResp.AddString(&Celda)
EndSub
&HttpResp, es de tipo HttpResponse
&HttpResp.AddHeader('Content-type', 'text/html; charset=charset=ISO-8859-1')
&HttpResp.AddHeader('Content-Disposition', 'attachment;filename='+ 'Contrato_' + trim(&Nro.ToString()) + '.doc')
&HttpResp.AddHeader('Content-type', 'application/vnd.text')
&HttpResp.AddString('<HTML>')
&HttpResp.AddString('<HEAD>')
&HttpResp.AddString('<META content="text/html; charset=utf-8" http-equiv="Content-Type" />')
&HttpResp.AddString('<STYLE />')
&HttpResp.AddString('</HEAD>')
&HttpResp.AddString('<BODY>')
&Celda='<TABLE>'
do 'Next'
&Celda = &Datos // datos guardados con FCKEditor
do 'Next'
&Celda='</TABLE>'
do 'Next'
&HttpResp.AddString('</BODY>')
&HttpResp.AddString('</HTML>')
Sub 'Next'
&HttpResp.AddString(&Celda)
EndSub
lunes, enero 23, 2017
Sincrum - Guia de estilo para el desarrollo en GeneXus
Gracias a Daniel Monza: Buenas prácticas con genexus
# Sincrum - Guia de estilo para el desarrollo en GeneXus
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 comenzando con la entidad en singular y siguiendo con el enumerado en plural sin abreviar estos.
// mal
DocumentoTipo
DocumentosTipos
DocTipos
// bien
DocumentoTipos (Venta,Compra,etc)
DocumentoModos (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.
// mal
CreCli
UpsertCliente
FechaCliente
// bien
ClienteUpsert
ClienteEliminar
ClienteFechaModificadoGet
ClienteFechaModificadoSet
DocumentoRecalculo
```
- 1.6 Utilizar [nomenclatura GIK](http://wiki.genexus.com/commwiki/servlet/wiki?1872,GIK) para nombrar atributos. En lo posible, intentar utilizar los nombres completos en lugar de 3 caracteres.
> 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 plural.
Las transacciones definen el nombre de las tablas en GeneXus. Se defien en plural ya que estas contienen N registros de la misma entidad.
// mal
Trn:Articulo
Trn:Cliente
// bien
Trn:Clientes
Trn:Articulos
```
- 2.1 Siempre que se pueda, utilizar tabuladores en lugar de "espacios". De esta forma, cada uno puede visializar la cantidad de espacioes que prefiera, ya que se configura en GeneXus. En los casos que no se pueda, y para definir un criterio, se utiliza una identación/tabulación de 3 espacios.
Esto es porque la mayoría de los comandos queda mas legibles con esta tabulación.
// mal
if &DocumentoTipo = DocumentoTipos.Venta
msg("Venta")
endif
// 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 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.1Evitar 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
if &HttpResponse = HttpMethods.Get
```
Structured Data Types
- 4.1 Utilizar New() en la creación de SDT en lugar de Clone().
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.1Utilizar [format](http://wiki.genexus.com/commwiki/servlet/wiki?8406,Format%20function) 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` o `TODO` 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 son `FIXME: -- necesita resolverse` or `TODO: -- 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.
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](http://wiki.genexus.com/commwiki/servlet/wiki?31605,Do%20Case%20command) siempre que se pueda a fín de sustituir [if](http://wiki.genexus.com/commwiki/servlet/wiki?8608,If+Command,) 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
```
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.
// mal
parm( in:&CliNom, in:&CliApe, in:&CliTel, in:&CliDir, in:&CliDOB)
// bien
parm( in:&sdtCliente )
```
Recursos
**Lectura interesante**
- [GeneXus Wiki](http://wiki.genexus.com/) - 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.
- Sincrum (http://sincrum.com)
Colaboradores
- Son bienvenidos a colaborar.
Licencia
Documento Original creado por Daniel Monza bajo licencia MIT](LICENSE)
basado en [la guia de Javascript de AirBNB](http://airbnb.io/javascript/)
# Sincrum - Guia de estilo para el desarrollo en GeneXus
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 comenzando con la entidad en singular y siguiendo con el enumerado en plural sin abreviar estos.
// mal
DocumentoTipo
DocumentosTipos
DocTipos
// bien
DocumentoTipos (Venta,Compra,etc)
DocumentoModos (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.
// mal
CreCli
UpsertCliente
FechaCliente
// bien
ClienteUpsert
ClienteEliminar
ClienteFechaModificadoGet
ClienteFechaModificadoSet
DocumentoRecalculo
```
- 1.6 Utilizar [nomenclatura GIK](http://wiki.genexus.com/commwiki/servlet/wiki?1872,GIK) para nombrar atributos. En lo posible, intentar utilizar los nombres completos en lugar de 3 caracteres.
> 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 plural.
Las transacciones definen el nombre de las tablas en GeneXus. Se defien en plural ya que estas contienen N registros de la misma entidad.
// mal
Trn:Articulo
Trn:Cliente
// bien
Trn:Clientes
Trn:Articulos
```
- 2.1 Siempre que se pueda, utilizar tabuladores en lugar de "espacios". De esta forma, cada uno puede visializar la cantidad de espacioes que prefiera, ya que se configura en GeneXus. En los casos que no se pueda, y para definir un criterio, se utiliza una identación/tabulación de 3 espacios.
Esto es porque la mayoría de los comandos queda mas legibles con esta tabulación.
// mal
if &DocumentoTipo = DocumentoTipos.Venta
msg("Venta")
endif
// 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 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.1Evitar 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
if &HttpResponse = HttpMethods.Get
```
Structured Data Types
- 4.1 Utilizar New() en la creación de SDT en lugar de Clone().
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.1Utilizar [format](http://wiki.genexus.com/commwiki/servlet/wiki?8406,Format%20function) 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` o `TODO` 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 son `FIXME: -- necesita resolverse` or `TODO: -- 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.
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](http://wiki.genexus.com/commwiki/servlet/wiki?31605,Do%20Case%20command) siempre que se pueda a fín de sustituir [if](http://wiki.genexus.com/commwiki/servlet/wiki?8608,If+Command,) 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
```
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.
// mal
parm( in:&CliNom, in:&CliApe, in:&CliTel, in:&CliDir, in:&CliDOB)
// bien
parm( in:&sdtCliente )
```
Recursos
**Lectura interesante**
- [GeneXus Wiki](http://wiki.genexus.com/) - 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.
- Sincrum (http://sincrum.com)
Colaboradores
- Son bienvenidos a colaborar.
Licencia
Documento Original creado por Daniel Monza bajo licencia MIT](LICENSE)
basado en [la guia de Javascript de AirBNB](http://airbnb.io/javascript/)
Suscribirse a:
Entradas (Atom)