SlideShare una empresa de Scribd logo
1 de 64
Descargar para leer sin conexión
Código
Limpio
Francisco J. Carabez
V1.0 Mar 11 2015
Código
LimpioLa disciplina es un puente entre las metas y los objetivos
-Jim Rohn
La solución es utilizar
nombres buenos y funciones cortas ,
en otras palabras, Código Limpio.
“Si no quiero entretenerme en ésa función,
recorriendo su código paso por paso,
para saber qué está intentando hacer”
CÓDIGO LIMPIO
¿QUÉ ES?
Variables y
Funciones con
nombres buenos
Que sean
pronunciables, que se
puedan buscar y que
tengan significado en
el entorno donde se
necesitan.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
Days,d are int
ClienteOC is int
PruductoIdString is string
AfeAmdms is DateTime
IF Days + 10 > 30
Info(“El documento tiene recargos”)
ELSE
AfeAmdms = AfectaBal(ClienteOC,ProductoIdString)
END
...
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
DiasDesdeElUltimoPago is int
ClienteOrdenDeCompra is int
ProductoId is string
FechaDeAfectacion is DateTime
CONSTANT
CTE_DiasDeGracia = 10
CTE_DiasPorPeriodo = 30
END
IF DiasDesdeElUltimoPago+CTE_DiasDeGracia > CTE_DiasPorPeriodo
NextTitle(“Saldo vencido”)
Info(“El documento no se puede procesar porque tiene recargos.”)
ELSE
FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId)
END
...
//No usar Espanglish.
//Evita números mágicos (los que “aparecen” sin lógica).
//Nombres de DOS a CUATRO palabras enteras. + (art. Adv.)
//¿Notación_Guiones_Bajos o NotaciónTipoCamello?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
Una is int
Palabra is int
Es is string
Confusa is DateTime
Iniciar() //Periodo, proceso?
Actualizar() //Saldo, Objeto?
Nombres_Buenos is int
Tienen_Dos_a_Cuatro_Palabras is int
IniciarCuentaDelCliente()
ActualizarContenidoDeVentana()
MasDeCincoPalabrasEsUnEstorbo is int
SieteEnanosBlancaNievesYLaMalvadaBruja is int
NoAbusarConNombresMuyLargosOPocosDescriptivos is string
ProcesoParaManipularLosDatosImportados()
ActualizarTablasYTemas() //¿Qué tiene de malo? Lo veremos..
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
IF gCuentasID > 0 THEN // Registro Modificar
gsHistorico = "0,1;1,0;1,1" //Puede ver lo vinculado y el históric
ELSE // Registro Nuevo
gsHistorico = "1,0;1,1" // Solo puede ver lo vinculado
END
Refrescar()
MyWindow..ReturnedValue = False
HReset(BAN_CU_Cuentas)
IF gCuentasID > 0 THEN
EDT_NumeroCuenta..State = Grayed
SetFocus(EDT_Descripcion)
HReadSeekFirst(BAN_CU_Cuentas,GUID,gCuentasID)
IF NOT HFound(BAN_CU_Cuentas) THEN
Error("No se encontró la cuenta.")
Close()
END
FileToScreen(WIN_BAN_CU_Cuentas_F)
ExecuteProcess(CBOX_ContieneFolios,trtChange)
MyWindow..Title = "Modificar Cuenta"
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
IF gCuentasID = CTE_DB_NUEVO THEN
gsHistorico = CTE_DB_VER_VINCULADOS
ELSE
gsHistorico = CTE_DB_VER_VINCULADOS+";"+CTE_DB_VER_HISTORICOS
END
RefrescarRegistrosEnTabla()
MyWindow..ReturnedValue = False
HReset(BAN_CU_Cuentas)
IF gCuentasID <> CTE_DB_NUEVO THEN
MyWindow..Title = "Modificar Cuenta"
EDT_NumeroCuenta..State = Grayed
HReadSeekFirst(BAN_CU_Cuentas,GUID,gCuentasID)
IF NOT HFound(BAN_CU_Cuentas) THEN
Error("No se encontró la cuenta.")
Close()
END
SetFocus(EDT_Descripcion)
FileToScreen(WIN_BAN_CU_Cuentas_F)
ExecuteProcess(CBOX_ContieneFolios,trtChange)
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
PROCEDURE DS_ActVale(nInsSubs is int)
// AGREGAMOS/ACTUALIZAMOS HEADER DEL VALE
nValeSubs is int = gaaValePosicion[garrInsumosDescarga[nInsSubs].nAlma
IF nValeSubs IN (0,"",-1) THEN
stLlenaVale is STValeHD
stLlenaVale.nGEN_ActorID = gstValeHD.nGEN_ActorID
stLlenaVale.nGEN_DocumentoID = gstValeHD.nGEN_DocumentoID
stLlenaVale.nGEN_Sucursal = gstValeHD.nGEN_Sucursal
stLlenaVale.sGEN_Notas = gstValeHD.sGEN_Notas
stLlenaVale.nGEN_CptoEntradas = gstValeHD.nGEN_CptoEntradas
stLlenaVale.nGEN_CptoSalidas = gstValeHD.nGEN_CptoSalidas
stLlenaVale.cyCostoTotal = garrInsumosDescarga[nInsSubs].cyCostoMo
stLlenaVale.nAlmacenID = garrInsumosDescarga[nInsSubs].nAlmacenID
stLlenaVale.nCptoTipoID = garrInsumosDescarga[nInsSubs].nTipo
nValeSubs = ArrayAdd(garrValesDescargar,stLlenaVale)
gaaValePosicion[garrInsumosDescarga[nInsSubs].nAlmacenID + "-" + g
ELSE
garrValesDescargar[nValeSubs].cyCostoTotal += garrInsumosDescarga[
END
S.R.P.
“Single Responsibility
Principle”
Un función deberá
tener una,
y sólo UNA,
responsabilidad
y deberá estar
encapsulada.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Funciones: Hacen UNA cosa y Regresan Valores. (Cuidar Contexto)
PROCEDURE SiExisteClienteID(LOCAL nClienteID is int = 0)
HReadSeekFirst(GEN_CU_Clientes,ClienteID,nClienteID)
IF HFound(GEN_CU_Clientes) THEN
RESULT True
ELSE
RESULT False
END
//Ejercicio: Calcular ahorro en el proyecto al utilizar lo anterior.
PROCEDURE EsPedidoParaEnviar (LOCAL nPedidoID is int = 0)
HReadSeekFirst(GEN_CU_ClientesPedidos,PedidoID,nPedidoID)
IF HFound(GEN_CU_ClientesPedidos) THEN
RESULT GEN_CU_ClientesPedidos.EsParaEnviar
ELSE
RESULT False
END
//Nota nombres de BOLEANOS: comienzan con “Si”+Verbo “Es”+Sustantivo
// HayExistenciaEnAlmacen(), SiHuboError(), EstaElClienteActivo()
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//PROCESOS: Realizan UNA Tarea.
PROCEDURE ProcesarBalanceDeCliente(LOCAL nClienteBalanceID is int=0)
IF SiExisteClientesID(gnCienteID) THEN
IF SiExisteClientesBalanceID(nClienteBalanceID) THEN
IF SiProcedeCorrimientoDeSaldos(gnCienteID) THEN
ClientesBalance.Debe = ConsultarCargos(gnCienteID)
ClientesBalance.Haber = ConsultarAbonos(gnCienteID)
RESULT HModify(ClientesBalance)
END
END
END
RESULT False
//Las tareas generalmente se componen de varias funciones.
//Nota: Manejar máximo TRES anidamientos “IF”.
//Evitar: usar variables GLOBALES (gnCienteID) dentro de funciones
//Evitar: Leer el contenido de controles dentro de funciones.
//Ejercicio: Como optimizar / limpiar el Código.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
PROCEDURE Guardar()
IF gDevCompraGUID > 0 THEN
HReadSeekFirst(COM_OP_DevCompra,GUID,gDevCompraGUID)
SiNoExiste("No se encontró la devolución de compra")
ScreenToFile()
HModify(COM_OP_DevCompra)
SiHuboError("No se pudo guardar la devolución de compra")
ELSE
HReset(COM_OP_DevCompra)
ScreenToFile(WIN_COM_OP_DevCompra_F)
COM_OP_DevCompra.GUID = GetGUID8()
HAdd(COM_OP_DevCompra)
SiHuboError("No se agregó la devolución de compra")
gDevCompraGUID = COM_OP_DevCompra.GUID
END
GuardaDetalle(COM_OP_DevCompra.GUID)
GuardarImpuestos(COM_OP_DevCompra.GUID)
PROCEDURE Proceso_GuardarOP(nOC_GUID)
GuardarEncabezadoOP(nOC_GUID)
GuardarDetalleOP(nOC_GUID)
GuardarImpuestosOP(nOC_GUID)
El código deberá
ser fácilmente
modificable
Estructurado de tal
manera que sea simple
hacer
cualquier
cambio
(mantenimiento).
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Nuevo Cambio: Ahora los días de gracia es una configuración Global.
//Nuevo Cambio: Los días del Período se tomarán del Período Activo.
DiasDesdeElUltimoPago is int
ClienteOrdenDeCompra is int
ProductoId is string
FechaDeAfectacion is DateTime
CONSTANT
CTE_DiasDeGracia = 10
CTE_DiasPorPeriodo = 30
END
IF DiasDesdeElUltimoPago+CTE_DiasDeGracia > CTE_DiasPorPeriodo
NextTitle(“Saldo vencido”)
Info(“El documento no se puede procesar porque tiene recargos.”)
ELSE
FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId)
END
...
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Nuevo Cambio: Ahora los días de gracia es una configuración Global.
//Nuevo Cambio: Los días del Período se tomarán del Período Activo.
// UN BUEN CÓDIGO COMIENZA CON UN BUEN DISEÑO.
DiasDesdeElUltimoPago is int
ClienteOrdenDeCompra is int
ProductoId is string
FechaDeAfectacion is DateTime
//CONSTANT
CTE_DiasDeGracia is int = Global_TraerDiasDeGracia()
CTE_DiasPorPeriodo is int = Local_TraerDiasDelPeriodoActivo()
//END
IF DiasDesdeElUltimoPago+CTE_DiasDeGracia > CTE_DiasPorPeriodo
NextTitle(“Saldo vencido”)
Info(“El documento no se puede procesar porque tiene recargos.”)
ELSE
FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId)
END
...
El código
deberá ser
extensible
¿Qué pasaría si en un
futuro hay nuevos
requerimientos
o diferentes
validaciones?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Nuevo Cambio: Ahora los Días de Gracia es por Cliente.
//Nuevo Req.: El Saldo Vencido se calculará según la Reforma Fiscal.
//Nuevo: Hacer Afectación en Días Laborables.
DiasDesdeElUltimoPago is int
ClienteOrdenDeCompra is int
ProductoId is string
FechaDeAfectacion is DateTime
//CONSTANT
CTE_DiasDeGracia is int = Global_TraerDiasDeGracia()
CTE_DiasPorPeriodo is int = Local_TraerDiasDelPeriodoActivo()
//END
IF DiasDesdeElUltimoPago+CTE_DiasDeGracia > CTE_DiasPorPeriodo
NextTitle(“Saldo vencido”)
Info(“El documento no se puede procesar porque tiene recargos.”)
ELSE
FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId)
END
...
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Nuevo Cambio: Ahora los Días de Gracia es por Cliente.
//Nuevo Req.: El Saldo Vencido se calculará según la Reforma Fiscal.
//Nuevo: Hacer Afectación en Días Laborables.
DiasDeVencido is int = TraerDiasDeVencido()
ClienteOrdenDeCompra is int
ProductoId is string
FechaDeAfectacion is DateTime
//CONSTANT
// CTE_DiasDeGracia is int = Global_TraerDiasDeGracia()
// CTE_DiasPorPeriodo is int = Local_TraerDiasDelPeriodoActivo()
//END
IF DiasDeVencido > 0
NextTitle(“Saldo con ” + DiasDeVencido + “ días de vencido”)
Info(“El documento no se puede procesar porque tiene recargos.”)
ELSE
FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId)
END
...
El código
deberá ser
legible
Exprésate con código,
como narrando una
pequeña historia,
que se pueda leer de
arriba hacia abajo.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Narración Tipo Secuencial. Notación Camello.
PosicionarRegistrosDeTablasDelProyecto()
SWITCH Proyectos.EtapaActual
CASE CTE_ETAPA_DefinirRequisitos
IF SiHayContratoFirmado() THEN
TransferirRecursosFinancieros()
NotificarALideresDeProyecto()
LiberarEtapaActual()
END
CASE CTE_ETAPA_RealizarDiseño
IF NOT HayTareasPendientes()
LiberarEtapaActual()
END
CASE CTE_ETAPA_ImplementarSistema
IF NOT HayFirmasPendientes() THEN
FelicitarYAgradecer()
ProcesarCierreDeProyecto()
END
END
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Narración Tipo Secuencial. Notación Guiones Bajos.
Posicionar_Registros_De_Tablas_Del_Proyecto()
SWITCH Proyectos.EtapaActual
CASE CTE_ETAPA_Definir_Requisitos
IF Si_Hay_Contrato_Firmado() THEN
Transferir_Recursos_Financieros()
Notificar_A_Lideres_De_Proyecto()
Liberar_Etapa_Actual()
END
CASE CTE_ETAPA_Realizar_Diseño
IF NOT Hay_Tareas_Pendientes() THEN
Liberar_Etapa_Actual()
END
CASE CTE_ETAPA_Implementar_Sistema
IF NOT Hay_Firmas_Pendientes() THEN
Felicitar_Y_Agradecer()
Procesar_Cierre_De_Proyecto()
END
END
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Narración Tipo IF-ELSE.
DiasDeVencido is int = TraerDiasDeVencido()
IF DiasDeVencido > 0
AgregarEnPaqueteParaBuro(DiasDeVencido)
IF EsCandidatoACarteraVencida() THEN
DispararAlertaAJuridico()
CambiarCalificacion()
BloquearLimiteDeCredito()
ELSE
DispararAlertaAtencionAClientes()
ProgramarNotificacionPorCorreo()
END
ActualizarDiasDeVencido()
VisualizarMontosTotales()
MySelf..Visible = True
ELSE
Info(“El documento está al corriente con los pagos.”)
ReturnToCapture(EDT_Monto)
END
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Narración Tipo IF-ELSE.
DiasDeVencido is int = TraerDiasDeVencido()
IF DiasDeVencido = 0
Info(“El documento está al corriente con los pagos.”) //más...
ReturnToCapture(EDT_Monto) //corto arriba.
ELSE
AgregarEnPaqueteParaBuro(DiasDeVencido)
IF EsCandidatoACarteraVencida() THEN
DispararAlertaAJuridico()
CambiarCalificacion()
BloquearLimiteDeCredito()
ELSE
DispararAlertaAtencionAClientes()
ProgramarNotificacionPorCorreo()
END
ActualizarDiasDeVencido()
VisualizarMontosTotales()
MySelf..Visible = True
END //Una Funcion un Return. ¿No se puede? Return al inicio
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Narración Tipo IF-ELSE. Comparar con anterior.
DiasDeVencido is int = TraerDiasDeVencido()
IF DiasDeVencido = 0
Info(“El documento está al corriente con los pagos.”) //más...
ReturnToCapture(EDT_Monto) //corto arriba.
END
AgregarEnPaqueteParaBuro(DiasDeVencido)
IF EsCandidatoACarteraVencida() THEN
DispararAlertaAJuridico()
CambiarCalificacion()
BloquearLimiteDeCredito()
ELSE
DispararAlertaAtencionAClientes()
ProgramarNotificacionPorCorreo()
END
ActualizarDiasDeVencido()
VisualizarMontosTotales()
MySelf..Visible = True
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
Refrescar()
MyWindow..ReturnedValue = False
HReset(BAN_CU_Cuentas)
IF gCuentasID > 0 THEN
EDT_NumeroCuenta..State = Grayed
SetFocus(EDT_Descripcion)
HReadSeekFirst(BAN_CU_Cuentas,GUID,gCuentasID)
IF NOT HFound(BAN_CU_Cuentas) THEN
Error("No se encontró la cuenta.")
Close()
END
FileToScreen(WIN_BAN_CU_Cuentas_F)
ExecuteProcess(CBOX_ContieneFolios,trtChange)
MyWindow..Title = "Modificar Cuenta“
ELSE
SetFocus(EDT_Descripcion)
MyWindow..Title = “Agregar Cuenta“
END
El código
deberá estar
probado
Y ésta pieza de código…
¿FUNCIONA?
Haz que funcione…
después mejórala…
después límpiala.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Código Muerto.
PROCEDURE CodigoMuerto(LOCAL nX is int = 0, LOCAL nY is int = 0)
nZ is int = nX/nY //Se realiza el cálculo pero no se utiliza.
RESULT nX*nY
//Código Inalcanzable.
PROCEDURE CodigoMuerto(LOCAL nX is int = 0, LOCAL nY is int = 0)
RESULT nX+nY
nZ is int = nX/nY //Jamás se llegará a ésta línea
//
nN is int = 2+1
IF nN = 4 THEN
nA = 2 //No se puede alcanzar ésta línea
END
//Código Redundante.
PROCEDURE CodigoRedundante(LOCAL nX is int = 0)
nY is int = nX*2 //Puede ser removida para evitar calcular dos veces
RESULT nX*2
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Debemos Probar TODAS las posibilidades y Verificar que funcionen.
Posicionar_Registros_De_Tablas_Del_Proyecto()
SWITCH Proyectos.EtapaActual
CASE CTE_ETAPA_Definir_Requisitos //Aquí
IF Si_Hay_Contrato_Firmado() THEN
Transferir_Recursos_Financieros()
Notificar_A_Lideres_De_Proyecto()
Liberar_Etapa_Actual()
END
CASE CTE_ETAPA_Realizar_Diseño //Aquí
IF NOT Hay_Tareas_Pendientes() THEN
Liberar_Etapa_Actual()
END
CASE CTE_ETAPA_Implementar_Sistema //Aquí
IF NOT Hay_Firmas_Pendientes() THEN
Felicitar_Y_Agradecer()
Procesar_Cierre_De_Proyecto()
END
END // ¿Qué pasaría con el ELSE? ¿Es Inalcanzable?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//Ejercicio: ¿Puedes localizar el BUG?
HExecuteQuery(QRY_TAC_OP_CuentaActiva_PorMesa)
HReadFirst(QRY_TAC_OP_CuentaActiva_PorMesa)
IF HFound(QRY_TAC_OP_CuentaActiva_PorMesa) THEN
nCuentaID = QRY_TAC_OP_CuentaActiva_PorMesa.GUID
END
HFreeQuery(QRY_TAC_OP_CuentaActiva_PorMesa)
HReadSeekFirst(Index_AreaServicio,Index_AreaServicio.GUID,gnAreaActiva
IF HFound(Index_AreaServicio) THEN
Open(WIN_TCH_MesaCambiarComensales,nCuentaID,nMesa,Index_AreaServic
Mesas_ActualizaMesa(Mesas_OP.gstDatosMesa.nMesaID)
END
//Procurar Llaves que reemplazan a Queries.
Evitar
los comentarios
Un programador de
verdad no comenta su
código.
Si fue difícil de escribir
será difícil de leer.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
//TODO: EVITAR comentarios NO es lo mismo que NO HACER comentarios.
//
//”No les digas a la gente que no hacer; diles que hacer y porque”
// Entonces... ¿Cuando hay que hacer comentarios?
//
//PRIMERO: Si hay que hacer un comentario es para EXPLICAR porque una
//pieza de código es como es, y no para describir que hace.
//Así evitamos comentarios que estorbarán cuando sean obsoletos.
//
//SEGUNDO: Si nos vemos TENTADOS a escribir un comentario tipo
// resumen de lo que un bloque de código hace; habrá que preguntarnos
// si ¿Estamos violando el principio de “Responsabilidad Única”?
// En ese caso es mejor sub-dividir el bloque en funciones pequeñas
// que se expliquen a sí mismas sin necesidad de comentarios.
//
//TERCERO: SÍ DEBEMOS Comentar SIEMPRE dentro de los objetos del IDE
// y evitarlos en el código. Pero sólo objetos que lo requieran.
//
//”El Código Bueno es en sí la mejor documentación.” —Steve McConnell
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
“Cuando mires al Código Oscuro
Cuidadoso debes ser...
Pues el Código Oscuro te mira a ti”
//Nietzsche Maestro Yoda
A continuación...
Otros tres principios JEDI
D.R.Y. & D.R.O.
Do not repeat yourself.
Do not repeat others.
No repitas dos veces
tu código.
No dupliques el código
de otros .
Horario:
Lunes a Jueves.
11 a.m. – 9 p.m.
Viernes. a Sábado.
11 a.m. – 9 p.m.
K.I.S.S.
Keep It Simple Stupid.
La explicación más
simple tiende a ser la
correcta.
La simplicidad es la máxima
sofisticación.
-Da Vinci
Y.A.G.N.I.
You Ain’t Gonna
Need It
Si no está en el
requerimiento,
NO está en el código.
Relación 80% / 20%.
GRISES VS VERDES
Código limpio
y bonito
¡No confundas
bonito con
bueno!
Entonces…
Qué carajos
Qué
carajos
CÓDIGO BUENO CÓDIGO MALO
Qué carajos
Ay, Compa…
Qué carajos
La única medida válida de la calidad
del código: “Qué Carajos” / minuto
REVISIÓN
DE
CÓDIGO
REVISIÓN
DE
CÓDIGO
Concluyendo:
Código Limpio: Leíble, mantenible y probado.
Código Funcional: Hace lo que debe hacer.
Código Bueno: Combinación de Limpio y Funcional.
s
CÓDIGO HEREDADO
¿QUÉ HACER CON LO ANTERIOR?
Teoría de la
“Ventana Rota”
Un ambiente
limpio y ordenado
propicia
orden y limpieza.
La Regla
“Boy Scout”
Deja el lugar
más limpio
que como
lo encontraste.
Imitar
“El ambiente”
Cuando a
Roma fueres…
Haz como vieres.
-Cervantes
LAS HERRAMIENTAS
DE APOYO
Mismas herramientas y materiales…
Diferentes resultados
NOMENCLATURA
EN ELEMENTOS DEL PROJECTO
Archivos Extensión Notas
ANI_ *.gif, *.png, *.avi, *.ani Animaciones
IMG_ *.jpg, *.png, *.gif Fondos, Adornos…
ICO_ *.ico, *.png, *.cur etc Botones, List, Tree…
CLA_ SET_ “Clases” y “Procedures”
CTRLTPL_ “Controles” Templates
WIN_ “Windows”
WINTPL_ “Windows” Templates
IW_ “Windows” Internal
RPT_ “Reportes”
RPTTPL_ “Reportes” Templates
QRY_ “Queries”
INDEX_ “Queries” en memoria
XML_ XSD_ “Xml” y “Xsd”
WS_ “Web Services”
NOMENCLATURA
PARA EL ANÁLISIS
ClientesNombres de Tablas
para
“Entidad Fuerte”
Proveedores
Almacenes
Designan una “entidad”
que existe en la realidad
(física) o en la mente
(conceptual).
Nombres en Plural.
Productos
Asociados
Maquinarias
Eventos
Servicios
VentasNombres de Tablas
para
“Entidad Débil”
Venta_Cotizaciones
Venta_Pedidos
Designan “entidades”
que pertenecen a
entidades fuertes y sin
ellas no tendrían sentido.
Nombres en Plural.
Entidad fuerte en Singular.
Venta_OCs
Venta_Facturas
Venta_NotasDeVenta
Venta_Devoluciones
Venta_CxCs
ClientesNombres de Tablas
para
“Entidad Asociativa”
Clientes_Direcciones
Designan “entidades”
que incorporan atributos
específicos a las entidades
fuertes.
Entidad fuerte en Plural
Entidad asociada en Plural.
Proveedores
Direcciones
Direccion_Telefonos
Proveedores_Direcciones
Asociados
Asociados_Direcciones
Clientes
ClienteClases
ClienteSatRegistros
Nombres de Tablas
para
“Atributos de entidad”
Hay atributos de tipo
“descripción”
Hay atributos de tipo
“Identificación”
Nombres Plural
Entidad en Singular
ClienteTipos
ClienteTarjetas
ClienteOrigenes
ClienteEngomados
NOMENC LATURA
PARA EL CODIGO FUENTE
DB_VentasPrefijos para NOMBRES
de objetos del análisis:
“DB_” “QRY_” “INDEX_”
DB_Venta_Cotizaciones
DB_Venta_Pedidos
-Facilita el autocompletar
del RAD.
-Discrimina nombre de
funciones.
*El nombre Lógico puede ser
diferente del Real.
DB_Venta_OCs
DB_Venta_Facturas
DB_Venta_NotasDeVenta
DB_Venta_Devoluciones
DB_Venta_CxCs
Prefijos para NOMBRES
de funciones:
“FL_” “FG_”
-Facilita el autocompletar
del RAD.
-Discrimina nombre de
Tablas.
*Ocultar funciones Globales
convirtiéndolas en privadas.
FG_AutorizarRecursos
PROCEDURE FG_AutorizarRecursos()
FG_TransferirRecursos ()
FG_NotificarAResponsables()
FG_ColocarTareaFiscal()
RESULT TRUE
FG_TransferirRecursos
PROCEDURE PRIVATE FG_TransferirRecursos()
FG_ValidarRecursosFinancieros()
FG_ActualizarRegistrosDelProyecto()
FG_TransferirRecursosDelBanco ()
RESULT TRUE
FL_ValidarTransferencia
PROCEDURE FL_ValidarTransferencia()
IF FL_ValidarDatosEnVentana() THEN
RESULT FG_AutorizarRecursos ()
END
Prefijos para
constantes y variables:
“CTE_”
-Facilita el autocompletar
del RAD.
-Discrimina nombre de
tablas y funciones.
*Habilitar la nomenclatura del
proyecto: prefijos
automáticos.
“Siempre programa
como si el tipo que
terminará haciendo el
mantenimiento de tu
código será un
psicópata violento que
sabe donde vives.”
-John Woods
FRANCISCO
CARABEZ
ANTHONY
HOPKINS
JODIE
FOSTER
CONFESIONES
DE UN PROGRAMADOR
PSICÓPATA
Descargar ésta presentación:
http://www.carabez.com/downloads/codigolimpio.zip
Más información y referencias:
http://es.wikipedia.org/wiki/Teor%C3%ADa_de_las_ventanas_rota
http://threepanelsoul.com/2012/11/19/on-legacy-code/
http://threepanelsoul.com/2013/12/16/on-perl/
http://www.osnews.com/story/19266/WTFs_m
http://www.slideshare.net/origamiaddict/clean-code-18905258
http://en.wikipedia.org/wiki/Single_responsibility_principle
http://pngimg.com http://www.dafont.com
http://www.psdgraphics.com
http://www.slideshare.net/AngelGarciaOlloqui/writing-clean-code
http://es.wikipedia.org/wiki/Categor%C3%ADa:Principios_de_programaci%C3%B3n
LIGAS
Para consultar:

Más contenido relacionado

Similar a Codigolimpio

Practica Seis Delphi
Practica Seis DelphiPractica Seis Delphi
Practica Seis DelphiJose Ponce
 
Manual de App
Manual de App Manual de App
Manual de App valeria-lg
 
7090112 Clase Transact Sql Server
7090112 Clase Transact Sql Server7090112 Clase Transact Sql Server
7090112 Clase Transact Sql ServerCorfapo
 
Guia didactica programacion estructurada unidad 4
Guia didactica programacion estructurada unidad 4Guia didactica programacion estructurada unidad 4
Guia didactica programacion estructurada unidad 4Sol Hernández
 
4 libro fundamentos _condicional_oficio_2003_para_publicars_slidesharedoc
4 libro fundamentos _condicional_oficio_2003_para_publicars_slidesharedoc4 libro fundamentos _condicional_oficio_2003_para_publicars_slidesharedoc
4 libro fundamentos _condicional_oficio_2003_para_publicars_slidesharedocEcler Mamani Vilca
 
Fundamentosdeprogramacion 2
Fundamentosdeprogramacion 2Fundamentosdeprogramacion 2
Fundamentosdeprogramacion 2agustin rojas
 
7.1. procedimientos almacenados
7.1.  procedimientos almacenados7.1.  procedimientos almacenados
7.1. procedimientos almacenadosJorge Luis Lopez M
 
Como crear un proyecto en visual Studio 2010
Como crear un proyecto en visual Studio 2010Como crear un proyecto en visual Studio 2010
Como crear un proyecto en visual Studio 2010a9788398
 

Similar a Codigolimpio (10)

Practica Seis Delphi
Practica Seis DelphiPractica Seis Delphi
Practica Seis Delphi
 
Manual de App
Manual de App Manual de App
Manual de App
 
7090112 Clase Transact Sql Server
7090112 Clase Transact Sql Server7090112 Clase Transact Sql Server
7090112 Clase Transact Sql Server
 
Guia didactica programacion estructurada unidad 4
Guia didactica programacion estructurada unidad 4Guia didactica programacion estructurada unidad 4
Guia didactica programacion estructurada unidad 4
 
4 libro fundamentos _condicional_oficio_2003_para_publicars_slidesharedoc
4 libro fundamentos _condicional_oficio_2003_para_publicars_slidesharedoc4 libro fundamentos _condicional_oficio_2003_para_publicars_slidesharedoc
4 libro fundamentos _condicional_oficio_2003_para_publicars_slidesharedoc
 
Fundamentosdeprogramacion 2
Fundamentosdeprogramacion 2Fundamentosdeprogramacion 2
Fundamentosdeprogramacion 2
 
Unidad 4
Unidad 4Unidad 4
Unidad 4
 
Sql
SqlSql
Sql
 
7.1. procedimientos almacenados
7.1.  procedimientos almacenados7.1.  procedimientos almacenados
7.1. procedimientos almacenados
 
Como crear un proyecto en visual Studio 2010
Como crear un proyecto en visual Studio 2010Como crear un proyecto en visual Studio 2010
Como crear un proyecto en visual Studio 2010
 

Codigolimpio

  • 2.
  • 3. Código LimpioLa disciplina es un puente entre las metas y los objetivos -Jim Rohn
  • 4.
  • 5. La solución es utilizar nombres buenos y funciones cortas , en otras palabras, Código Limpio. “Si no quiero entretenerme en ésa función, recorriendo su código paso por paso, para saber qué está intentando hacer” CÓDIGO LIMPIO ¿QUÉ ES?
  • 6. Variables y Funciones con nombres buenos Que sean pronunciables, que se puedan buscar y que tengan significado en el entorno donde se necesitan.
  • 7. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 Days,d are int ClienteOC is int PruductoIdString is string AfeAmdms is DateTime IF Days + 10 > 30 Info(“El documento tiene recargos”) ELSE AfeAmdms = AfectaBal(ClienteOC,ProductoIdString) END ...
  • 8. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 DiasDesdeElUltimoPago is int ClienteOrdenDeCompra is int ProductoId is string FechaDeAfectacion is DateTime CONSTANT CTE_DiasDeGracia = 10 CTE_DiasPorPeriodo = 30 END IF DiasDesdeElUltimoPago+CTE_DiasDeGracia > CTE_DiasPorPeriodo NextTitle(“Saldo vencido”) Info(“El documento no se puede procesar porque tiene recargos.”) ELSE FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId) END ... //No usar Espanglish. //Evita números mágicos (los que “aparecen” sin lógica). //Nombres de DOS a CUATRO palabras enteras. + (art. Adv.) //¿Notación_Guiones_Bajos o NotaciónTipoCamello?
  • 9. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 Una is int Palabra is int Es is string Confusa is DateTime Iniciar() //Periodo, proceso? Actualizar() //Saldo, Objeto? Nombres_Buenos is int Tienen_Dos_a_Cuatro_Palabras is int IniciarCuentaDelCliente() ActualizarContenidoDeVentana() MasDeCincoPalabrasEsUnEstorbo is int SieteEnanosBlancaNievesYLaMalvadaBruja is int NoAbusarConNombresMuyLargosOPocosDescriptivos is string ProcesoParaManipularLosDatosImportados() ActualizarTablasYTemas() //¿Qué tiene de malo? Lo veremos..
  • 10. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 IF gCuentasID > 0 THEN // Registro Modificar gsHistorico = "0,1;1,0;1,1" //Puede ver lo vinculado y el históric ELSE // Registro Nuevo gsHistorico = "1,0;1,1" // Solo puede ver lo vinculado END Refrescar() MyWindow..ReturnedValue = False HReset(BAN_CU_Cuentas) IF gCuentasID > 0 THEN EDT_NumeroCuenta..State = Grayed SetFocus(EDT_Descripcion) HReadSeekFirst(BAN_CU_Cuentas,GUID,gCuentasID) IF NOT HFound(BAN_CU_Cuentas) THEN Error("No se encontró la cuenta.") Close() END FileToScreen(WIN_BAN_CU_Cuentas_F) ExecuteProcess(CBOX_ContieneFolios,trtChange) MyWindow..Title = "Modificar Cuenta"
  • 11. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 IF gCuentasID = CTE_DB_NUEVO THEN gsHistorico = CTE_DB_VER_VINCULADOS ELSE gsHistorico = CTE_DB_VER_VINCULADOS+";"+CTE_DB_VER_HISTORICOS END RefrescarRegistrosEnTabla() MyWindow..ReturnedValue = False HReset(BAN_CU_Cuentas) IF gCuentasID <> CTE_DB_NUEVO THEN MyWindow..Title = "Modificar Cuenta" EDT_NumeroCuenta..State = Grayed HReadSeekFirst(BAN_CU_Cuentas,GUID,gCuentasID) IF NOT HFound(BAN_CU_Cuentas) THEN Error("No se encontró la cuenta.") Close() END SetFocus(EDT_Descripcion) FileToScreen(WIN_BAN_CU_Cuentas_F) ExecuteProcess(CBOX_ContieneFolios,trtChange)
  • 12. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 PROCEDURE DS_ActVale(nInsSubs is int) // AGREGAMOS/ACTUALIZAMOS HEADER DEL VALE nValeSubs is int = gaaValePosicion[garrInsumosDescarga[nInsSubs].nAlma IF nValeSubs IN (0,"",-1) THEN stLlenaVale is STValeHD stLlenaVale.nGEN_ActorID = gstValeHD.nGEN_ActorID stLlenaVale.nGEN_DocumentoID = gstValeHD.nGEN_DocumentoID stLlenaVale.nGEN_Sucursal = gstValeHD.nGEN_Sucursal stLlenaVale.sGEN_Notas = gstValeHD.sGEN_Notas stLlenaVale.nGEN_CptoEntradas = gstValeHD.nGEN_CptoEntradas stLlenaVale.nGEN_CptoSalidas = gstValeHD.nGEN_CptoSalidas stLlenaVale.cyCostoTotal = garrInsumosDescarga[nInsSubs].cyCostoMo stLlenaVale.nAlmacenID = garrInsumosDescarga[nInsSubs].nAlmacenID stLlenaVale.nCptoTipoID = garrInsumosDescarga[nInsSubs].nTipo nValeSubs = ArrayAdd(garrValesDescargar,stLlenaVale) gaaValePosicion[garrInsumosDescarga[nInsSubs].nAlmacenID + "-" + g ELSE garrValesDescargar[nValeSubs].cyCostoTotal += garrInsumosDescarga[ END
  • 13. S.R.P. “Single Responsibility Principle” Un función deberá tener una, y sólo UNA, responsabilidad y deberá estar encapsulada.
  • 14. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Funciones: Hacen UNA cosa y Regresan Valores. (Cuidar Contexto) PROCEDURE SiExisteClienteID(LOCAL nClienteID is int = 0) HReadSeekFirst(GEN_CU_Clientes,ClienteID,nClienteID) IF HFound(GEN_CU_Clientes) THEN RESULT True ELSE RESULT False END //Ejercicio: Calcular ahorro en el proyecto al utilizar lo anterior. PROCEDURE EsPedidoParaEnviar (LOCAL nPedidoID is int = 0) HReadSeekFirst(GEN_CU_ClientesPedidos,PedidoID,nPedidoID) IF HFound(GEN_CU_ClientesPedidos) THEN RESULT GEN_CU_ClientesPedidos.EsParaEnviar ELSE RESULT False END //Nota nombres de BOLEANOS: comienzan con “Si”+Verbo “Es”+Sustantivo // HayExistenciaEnAlmacen(), SiHuboError(), EstaElClienteActivo()
  • 15. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //PROCESOS: Realizan UNA Tarea. PROCEDURE ProcesarBalanceDeCliente(LOCAL nClienteBalanceID is int=0) IF SiExisteClientesID(gnCienteID) THEN IF SiExisteClientesBalanceID(nClienteBalanceID) THEN IF SiProcedeCorrimientoDeSaldos(gnCienteID) THEN ClientesBalance.Debe = ConsultarCargos(gnCienteID) ClientesBalance.Haber = ConsultarAbonos(gnCienteID) RESULT HModify(ClientesBalance) END END END RESULT False //Las tareas generalmente se componen de varias funciones. //Nota: Manejar máximo TRES anidamientos “IF”. //Evitar: usar variables GLOBALES (gnCienteID) dentro de funciones //Evitar: Leer el contenido de controles dentro de funciones. //Ejercicio: Como optimizar / limpiar el Código.
  • 16. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 PROCEDURE Guardar() IF gDevCompraGUID > 0 THEN HReadSeekFirst(COM_OP_DevCompra,GUID,gDevCompraGUID) SiNoExiste("No se encontró la devolución de compra") ScreenToFile() HModify(COM_OP_DevCompra) SiHuboError("No se pudo guardar la devolución de compra") ELSE HReset(COM_OP_DevCompra) ScreenToFile(WIN_COM_OP_DevCompra_F) COM_OP_DevCompra.GUID = GetGUID8() HAdd(COM_OP_DevCompra) SiHuboError("No se agregó la devolución de compra") gDevCompraGUID = COM_OP_DevCompra.GUID END GuardaDetalle(COM_OP_DevCompra.GUID) GuardarImpuestos(COM_OP_DevCompra.GUID) PROCEDURE Proceso_GuardarOP(nOC_GUID) GuardarEncabezadoOP(nOC_GUID) GuardarDetalleOP(nOC_GUID) GuardarImpuestosOP(nOC_GUID)
  • 17. El código deberá ser fácilmente modificable Estructurado de tal manera que sea simple hacer cualquier cambio (mantenimiento).
  • 18. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Nuevo Cambio: Ahora los días de gracia es una configuración Global. //Nuevo Cambio: Los días del Período se tomarán del Período Activo. DiasDesdeElUltimoPago is int ClienteOrdenDeCompra is int ProductoId is string FechaDeAfectacion is DateTime CONSTANT CTE_DiasDeGracia = 10 CTE_DiasPorPeriodo = 30 END IF DiasDesdeElUltimoPago+CTE_DiasDeGracia > CTE_DiasPorPeriodo NextTitle(“Saldo vencido”) Info(“El documento no se puede procesar porque tiene recargos.”) ELSE FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId) END ...
  • 19. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Nuevo Cambio: Ahora los días de gracia es una configuración Global. //Nuevo Cambio: Los días del Período se tomarán del Período Activo. // UN BUEN CÓDIGO COMIENZA CON UN BUEN DISEÑO. DiasDesdeElUltimoPago is int ClienteOrdenDeCompra is int ProductoId is string FechaDeAfectacion is DateTime //CONSTANT CTE_DiasDeGracia is int = Global_TraerDiasDeGracia() CTE_DiasPorPeriodo is int = Local_TraerDiasDelPeriodoActivo() //END IF DiasDesdeElUltimoPago+CTE_DiasDeGracia > CTE_DiasPorPeriodo NextTitle(“Saldo vencido”) Info(“El documento no se puede procesar porque tiene recargos.”) ELSE FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId) END ...
  • 20. El código deberá ser extensible ¿Qué pasaría si en un futuro hay nuevos requerimientos o diferentes validaciones?
  • 21. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Nuevo Cambio: Ahora los Días de Gracia es por Cliente. //Nuevo Req.: El Saldo Vencido se calculará según la Reforma Fiscal. //Nuevo: Hacer Afectación en Días Laborables. DiasDesdeElUltimoPago is int ClienteOrdenDeCompra is int ProductoId is string FechaDeAfectacion is DateTime //CONSTANT CTE_DiasDeGracia is int = Global_TraerDiasDeGracia() CTE_DiasPorPeriodo is int = Local_TraerDiasDelPeriodoActivo() //END IF DiasDesdeElUltimoPago+CTE_DiasDeGracia > CTE_DiasPorPeriodo NextTitle(“Saldo vencido”) Info(“El documento no se puede procesar porque tiene recargos.”) ELSE FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId) END ...
  • 22. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Nuevo Cambio: Ahora los Días de Gracia es por Cliente. //Nuevo Req.: El Saldo Vencido se calculará según la Reforma Fiscal. //Nuevo: Hacer Afectación en Días Laborables. DiasDeVencido is int = TraerDiasDeVencido() ClienteOrdenDeCompra is int ProductoId is string FechaDeAfectacion is DateTime //CONSTANT // CTE_DiasDeGracia is int = Global_TraerDiasDeGracia() // CTE_DiasPorPeriodo is int = Local_TraerDiasDelPeriodoActivo() //END IF DiasDeVencido > 0 NextTitle(“Saldo con ” + DiasDeVencido + “ días de vencido”) Info(“El documento no se puede procesar porque tiene recargos.”) ELSE FechaDeAfectacion=AfectarBalance(ClienteOrdenDeCompra,ProductoId) END ...
  • 23. El código deberá ser legible Exprésate con código, como narrando una pequeña historia, que se pueda leer de arriba hacia abajo.
  • 24. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Narración Tipo Secuencial. Notación Camello. PosicionarRegistrosDeTablasDelProyecto() SWITCH Proyectos.EtapaActual CASE CTE_ETAPA_DefinirRequisitos IF SiHayContratoFirmado() THEN TransferirRecursosFinancieros() NotificarALideresDeProyecto() LiberarEtapaActual() END CASE CTE_ETAPA_RealizarDiseño IF NOT HayTareasPendientes() LiberarEtapaActual() END CASE CTE_ETAPA_ImplementarSistema IF NOT HayFirmasPendientes() THEN FelicitarYAgradecer() ProcesarCierreDeProyecto() END END
  • 25. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Narración Tipo Secuencial. Notación Guiones Bajos. Posicionar_Registros_De_Tablas_Del_Proyecto() SWITCH Proyectos.EtapaActual CASE CTE_ETAPA_Definir_Requisitos IF Si_Hay_Contrato_Firmado() THEN Transferir_Recursos_Financieros() Notificar_A_Lideres_De_Proyecto() Liberar_Etapa_Actual() END CASE CTE_ETAPA_Realizar_Diseño IF NOT Hay_Tareas_Pendientes() THEN Liberar_Etapa_Actual() END CASE CTE_ETAPA_Implementar_Sistema IF NOT Hay_Firmas_Pendientes() THEN Felicitar_Y_Agradecer() Procesar_Cierre_De_Proyecto() END END
  • 26. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Narración Tipo IF-ELSE. DiasDeVencido is int = TraerDiasDeVencido() IF DiasDeVencido > 0 AgregarEnPaqueteParaBuro(DiasDeVencido) IF EsCandidatoACarteraVencida() THEN DispararAlertaAJuridico() CambiarCalificacion() BloquearLimiteDeCredito() ELSE DispararAlertaAtencionAClientes() ProgramarNotificacionPorCorreo() END ActualizarDiasDeVencido() VisualizarMontosTotales() MySelf..Visible = True ELSE Info(“El documento está al corriente con los pagos.”) ReturnToCapture(EDT_Monto) END
  • 27. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Narración Tipo IF-ELSE. DiasDeVencido is int = TraerDiasDeVencido() IF DiasDeVencido = 0 Info(“El documento está al corriente con los pagos.”) //más... ReturnToCapture(EDT_Monto) //corto arriba. ELSE AgregarEnPaqueteParaBuro(DiasDeVencido) IF EsCandidatoACarteraVencida() THEN DispararAlertaAJuridico() CambiarCalificacion() BloquearLimiteDeCredito() ELSE DispararAlertaAtencionAClientes() ProgramarNotificacionPorCorreo() END ActualizarDiasDeVencido() VisualizarMontosTotales() MySelf..Visible = True END //Una Funcion un Return. ¿No se puede? Return al inicio
  • 28. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Narración Tipo IF-ELSE. Comparar con anterior. DiasDeVencido is int = TraerDiasDeVencido() IF DiasDeVencido = 0 Info(“El documento está al corriente con los pagos.”) //más... ReturnToCapture(EDT_Monto) //corto arriba. END AgregarEnPaqueteParaBuro(DiasDeVencido) IF EsCandidatoACarteraVencida() THEN DispararAlertaAJuridico() CambiarCalificacion() BloquearLimiteDeCredito() ELSE DispararAlertaAtencionAClientes() ProgramarNotificacionPorCorreo() END ActualizarDiasDeVencido() VisualizarMontosTotales() MySelf..Visible = True
  • 29. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 Refrescar() MyWindow..ReturnedValue = False HReset(BAN_CU_Cuentas) IF gCuentasID > 0 THEN EDT_NumeroCuenta..State = Grayed SetFocus(EDT_Descripcion) HReadSeekFirst(BAN_CU_Cuentas,GUID,gCuentasID) IF NOT HFound(BAN_CU_Cuentas) THEN Error("No se encontró la cuenta.") Close() END FileToScreen(WIN_BAN_CU_Cuentas_F) ExecuteProcess(CBOX_ContieneFolios,trtChange) MyWindow..Title = "Modificar Cuenta“ ELSE SetFocus(EDT_Descripcion) MyWindow..Title = “Agregar Cuenta“ END
  • 30. El código deberá estar probado Y ésta pieza de código… ¿FUNCIONA? Haz que funcione… después mejórala… después límpiala.
  • 31. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Código Muerto. PROCEDURE CodigoMuerto(LOCAL nX is int = 0, LOCAL nY is int = 0) nZ is int = nX/nY //Se realiza el cálculo pero no se utiliza. RESULT nX*nY //Código Inalcanzable. PROCEDURE CodigoMuerto(LOCAL nX is int = 0, LOCAL nY is int = 0) RESULT nX+nY nZ is int = nX/nY //Jamás se llegará a ésta línea // nN is int = 2+1 IF nN = 4 THEN nA = 2 //No se puede alcanzar ésta línea END //Código Redundante. PROCEDURE CodigoRedundante(LOCAL nX is int = 0) nY is int = nX*2 //Puede ser removida para evitar calcular dos veces RESULT nX*2
  • 32. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Debemos Probar TODAS las posibilidades y Verificar que funcionen. Posicionar_Registros_De_Tablas_Del_Proyecto() SWITCH Proyectos.EtapaActual CASE CTE_ETAPA_Definir_Requisitos //Aquí IF Si_Hay_Contrato_Firmado() THEN Transferir_Recursos_Financieros() Notificar_A_Lideres_De_Proyecto() Liberar_Etapa_Actual() END CASE CTE_ETAPA_Realizar_Diseño //Aquí IF NOT Hay_Tareas_Pendientes() THEN Liberar_Etapa_Actual() END CASE CTE_ETAPA_Implementar_Sistema //Aquí IF NOT Hay_Firmas_Pendientes() THEN Felicitar_Y_Agradecer() Procesar_Cierre_De_Proyecto() END END // ¿Qué pasaría con el ELSE? ¿Es Inalcanzable?
  • 33. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //Ejercicio: ¿Puedes localizar el BUG? HExecuteQuery(QRY_TAC_OP_CuentaActiva_PorMesa) HReadFirst(QRY_TAC_OP_CuentaActiva_PorMesa) IF HFound(QRY_TAC_OP_CuentaActiva_PorMesa) THEN nCuentaID = QRY_TAC_OP_CuentaActiva_PorMesa.GUID END HFreeQuery(QRY_TAC_OP_CuentaActiva_PorMesa) HReadSeekFirst(Index_AreaServicio,Index_AreaServicio.GUID,gnAreaActiva IF HFound(Index_AreaServicio) THEN Open(WIN_TCH_MesaCambiarComensales,nCuentaID,nMesa,Index_AreaServic Mesas_ActualizaMesa(Mesas_OP.gstDatosMesa.nMesaID) END //Procurar Llaves que reemplazan a Queries.
  • 34. Evitar los comentarios Un programador de verdad no comenta su código. Si fue difícil de escribir será difícil de leer.
  • 35. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 //TODO: EVITAR comentarios NO es lo mismo que NO HACER comentarios. // //”No les digas a la gente que no hacer; diles que hacer y porque” // Entonces... ¿Cuando hay que hacer comentarios? // //PRIMERO: Si hay que hacer un comentario es para EXPLICAR porque una //pieza de código es como es, y no para describir que hace. //Así evitamos comentarios que estorbarán cuando sean obsoletos. // //SEGUNDO: Si nos vemos TENTADOS a escribir un comentario tipo // resumen de lo que un bloque de código hace; habrá que preguntarnos // si ¿Estamos violando el principio de “Responsabilidad Única”? // En ese caso es mejor sub-dividir el bloque en funciones pequeñas // que se expliquen a sí mismas sin necesidad de comentarios. // //TERCERO: SÍ DEBEMOS Comentar SIEMPRE dentro de los objetos del IDE // y evitarlos en el código. Pero sólo objetos que lo requieran. // //”El Código Bueno es en sí la mejor documentación.” —Steve McConnell
  • 36. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 “Cuando mires al Código Oscuro Cuidadoso debes ser... Pues el Código Oscuro te mira a ti” //Nietzsche Maestro Yoda A continuación... Otros tres principios JEDI
  • 37. D.R.Y. & D.R.O. Do not repeat yourself. Do not repeat others. No repitas dos veces tu código. No dupliques el código de otros . Horario: Lunes a Jueves. 11 a.m. – 9 p.m. Viernes. a Sábado. 11 a.m. – 9 p.m.
  • 38. K.I.S.S. Keep It Simple Stupid. La explicación más simple tiende a ser la correcta. La simplicidad es la máxima sofisticación. -Da Vinci
  • 39. Y.A.G.N.I. You Ain’t Gonna Need It Si no está en el requerimiento, NO está en el código. Relación 80% / 20%. GRISES VS VERDES
  • 40. Código limpio y bonito ¡No confundas bonito con bueno! Entonces…
  • 41. Qué carajos Qué carajos CÓDIGO BUENO CÓDIGO MALO Qué carajos Ay, Compa… Qué carajos La única medida válida de la calidad del código: “Qué Carajos” / minuto REVISIÓN DE CÓDIGO REVISIÓN DE CÓDIGO
  • 42. Concluyendo: Código Limpio: Leíble, mantenible y probado. Código Funcional: Hace lo que debe hacer. Código Bueno: Combinación de Limpio y Funcional. s
  • 43. CÓDIGO HEREDADO ¿QUÉ HACER CON LO ANTERIOR?
  • 44.
  • 45. Teoría de la “Ventana Rota” Un ambiente limpio y ordenado propicia orden y limpieza.
  • 46. La Regla “Boy Scout” Deja el lugar más limpio que como lo encontraste.
  • 47. Imitar “El ambiente” Cuando a Roma fueres… Haz como vieres. -Cervantes
  • 48.
  • 50. Mismas herramientas y materiales… Diferentes resultados
  • 52. Archivos Extensión Notas ANI_ *.gif, *.png, *.avi, *.ani Animaciones IMG_ *.jpg, *.png, *.gif Fondos, Adornos… ICO_ *.ico, *.png, *.cur etc Botones, List, Tree… CLA_ SET_ “Clases” y “Procedures” CTRLTPL_ “Controles” Templates WIN_ “Windows” WINTPL_ “Windows” Templates IW_ “Windows” Internal RPT_ “Reportes” RPTTPL_ “Reportes” Templates QRY_ “Queries” INDEX_ “Queries” en memoria XML_ XSD_ “Xml” y “Xsd” WS_ “Web Services”
  • 54. ClientesNombres de Tablas para “Entidad Fuerte” Proveedores Almacenes Designan una “entidad” que existe en la realidad (física) o en la mente (conceptual). Nombres en Plural. Productos Asociados Maquinarias Eventos Servicios
  • 55. VentasNombres de Tablas para “Entidad Débil” Venta_Cotizaciones Venta_Pedidos Designan “entidades” que pertenecen a entidades fuertes y sin ellas no tendrían sentido. Nombres en Plural. Entidad fuerte en Singular. Venta_OCs Venta_Facturas Venta_NotasDeVenta Venta_Devoluciones Venta_CxCs
  • 56. ClientesNombres de Tablas para “Entidad Asociativa” Clientes_Direcciones Designan “entidades” que incorporan atributos específicos a las entidades fuertes. Entidad fuerte en Plural Entidad asociada en Plural. Proveedores Direcciones Direccion_Telefonos Proveedores_Direcciones Asociados Asociados_Direcciones
  • 57. Clientes ClienteClases ClienteSatRegistros Nombres de Tablas para “Atributos de entidad” Hay atributos de tipo “descripción” Hay atributos de tipo “Identificación” Nombres Plural Entidad en Singular ClienteTipos ClienteTarjetas ClienteOrigenes ClienteEngomados
  • 58. NOMENC LATURA PARA EL CODIGO FUENTE
  • 59. DB_VentasPrefijos para NOMBRES de objetos del análisis: “DB_” “QRY_” “INDEX_” DB_Venta_Cotizaciones DB_Venta_Pedidos -Facilita el autocompletar del RAD. -Discrimina nombre de funciones. *El nombre Lógico puede ser diferente del Real. DB_Venta_OCs DB_Venta_Facturas DB_Venta_NotasDeVenta DB_Venta_Devoluciones DB_Venta_CxCs
  • 60. Prefijos para NOMBRES de funciones: “FL_” “FG_” -Facilita el autocompletar del RAD. -Discrimina nombre de Tablas. *Ocultar funciones Globales convirtiéndolas en privadas. FG_AutorizarRecursos PROCEDURE FG_AutorizarRecursos() FG_TransferirRecursos () FG_NotificarAResponsables() FG_ColocarTareaFiscal() RESULT TRUE FG_TransferirRecursos PROCEDURE PRIVATE FG_TransferirRecursos() FG_ValidarRecursosFinancieros() FG_ActualizarRegistrosDelProyecto() FG_TransferirRecursosDelBanco () RESULT TRUE FL_ValidarTransferencia PROCEDURE FL_ValidarTransferencia() IF FL_ValidarDatosEnVentana() THEN RESULT FG_AutorizarRecursos () END
  • 61. Prefijos para constantes y variables: “CTE_” -Facilita el autocompletar del RAD. -Discrimina nombre de tablas y funciones. *Habilitar la nomenclatura del proyecto: prefijos automáticos.
  • 62. “Siempre programa como si el tipo que terminará haciendo el mantenimiento de tu código será un psicópata violento que sabe donde vives.” -John Woods FRANCISCO CARABEZ ANTHONY HOPKINS JODIE FOSTER CONFESIONES DE UN PROGRAMADOR PSICÓPATA
  • 63.
  • 64. Descargar ésta presentación: http://www.carabez.com/downloads/codigolimpio.zip Más información y referencias: http://es.wikipedia.org/wiki/Teor%C3%ADa_de_las_ventanas_rota http://threepanelsoul.com/2012/11/19/on-legacy-code/ http://threepanelsoul.com/2013/12/16/on-perl/ http://www.osnews.com/story/19266/WTFs_m http://www.slideshare.net/origamiaddict/clean-code-18905258 http://en.wikipedia.org/wiki/Single_responsibility_principle http://pngimg.com http://www.dafont.com http://www.psdgraphics.com http://www.slideshare.net/AngelGarciaOlloqui/writing-clean-code http://es.wikipedia.org/wiki/Categor%C3%ADa:Principios_de_programaci%C3%B3n LIGAS Para consultar: