Estandar de Desarrollo y Buenas Practicas Con C# y SQL
Estandar de Desarrollo y Buenas Practicas Con C# y SQL
Estandar de Desarrollo y Buenas Practicas Con C# y SQL
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Introducción.
Este documento está basado en las buenas prácticas definidas y recomendadas por expertos desarrolladores,
así como por Microsoft y Metodologías Agiles que deberán de cumplirse en el la Fabrica de Software de Engine
Core
Específicamente, este documento contiene:
1. Objetivo.
La utilización y seguimiento de los estándares definidos en este documento debe de dar como resultado
efectos positivos en:
2. Alcance.
Este documento aplica a todos los lenguajes de programación, sin embargo, los ejemplos mencionados en este
documento están enfocados a lenguajes de programación como C-Sharp, Java Script y Transact SQL, muchas de
las recomendaciones descritas pueden ser usadas independientemente del lenguaje en el que se esté
trabajando, se incluyen algunos comentarios acerca de prácticas comunes y problemas conocidos de C#, las
cuales se describen en forma breve.
Una regla puede romperse sólo ante razones justificadas, discutidas, con previa autorización del responsable
del producto, y en caso que no pueda aplicarse ninguna alternativa razonable. El autor de la excepción,
obligatoriamente debe documentar el código explicando la causa de la violación de la regla
Negrita Texto con énfasis adicional que debe ser considerado importante.
Uno de los aspectos más importantes dentro de la estandarización de código fuente y uso de las buenas practicas
tiene que ver con el mantener un buen nivel de cumplimiento de buenas prácticas, al finalizar un Sprint (en la
retrospectiva), debes realizar reuniones de revisión de código para asegurar que cada uno está siguiendo las
reglas definidas en este documento. Tres tipos de revisiones de código son recomendadas:
a. Peer Review: Revisión por un Par – Donde otro miembro del equipo revisa el código asegurándose
de que el código sigue los estándares de codificación y cumple los requerimientos. Este nivel de
revisión puede incluir además algunas pruebas unitarias. Cada archivo en el proyecto debe pasar por
este proceso.
c. Revisión Grupal – Aleatoriamente se selecciona uno o más archivos y se conduce una revisión de
grupo finalizado un Sprint. Distribuye una copia impresa de los archivos a todos los miembros con
previa anticipación antes de la reunión. Permite que la lean y que lleguen con puntos de discusión.
En la reunión para la revisión grupal, usa un proyecto para desplegar el contenido del archivo en la
pantalla. Navega por cada una de las secciones del código y permite que cada miembro dé sus
sugerencias en cómo esa pieza de código podría ser escrita de mejor manera. (Nunca olvides apreciar
al desarrollador por el buen trabajo y asegúrate de que no se sienta ofendido por el “ataque de
grupo”)
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
1. Tipos de Codificación.
Existen varios tipos de metodologías y convenciones para la notación de código fuente como Pascal o Camell
entre otros, los cuales definiremos a continuación:
Notación Pascal – El primer carácter de todas las palabras se escribe en Mayúsculas y los otros caracteres
en minúsculas.
Ejemplo: ColorDeFondo
public class HolaMundo(string MensajeCompleto)
* Notación de Camell – El primer carácter de todas las palabras, excepto de la primera palabra se escribe
en Mayúsculas y los otros caracteres en minúsculas.
Ejemplo: colorDeFondo
El tipo de notación que deberá de usarse sin excepción alguna es Pascal Case
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Correcto:
string direccion;
int usuario;
Incorrecto:
string nom;
string dir;
int pass;
Evitar el uso de nombres como i, a, s, t, es mejor usar nombres descriptivos a excepción de iteración en los
ciclos.
for (int i = 0; i < numTotal; i++)
Variables Local: Estas deberán de ser declaradas sin un prefijo guion bajo.
string VariableLocal;
4. Tipos Implícitos.
Cuando se declare una variable, si esta tiene asignado un valor que es totalmente reconocible u obvio, o cuando
el tipo exacto no es importante se podrá usar el tipo var, de lo contrario se deberá de declarar de forma explícita
el tipo de variable que se estará recibiendo, el uso del tipo var deberá de estar restringido para información
estática y no dinámica.
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
6. Uso de prefijos.
Cuando se trate de variables tipo boolean se debe de usar el prefijo “es”.
private bool esValido
namespace eCore.ERP.Usuarios;
2. Comentarios
Los comentarios deben de estar al mismo nivel que el código.
Correcto:
//Este es un comentario de ejemplo que está alineado
MessageBox.Show(MensajeCompleto);
Incorrecto:
//Este es un comentario de ejemplo que NO está alineado
MessageBox.Show(MensajeCompleto);
Las llaves ({}) deben estar en el mismo nivel que el código fuera de las llaves.
boolean EsMayorDeEdad = false;
3. Separador
Usar una línea en blanco como separador para dos grupos lógicos de código y deberá de haber solo una línea en
blanco para separar dos métodos dentro de una clase.
public class clase1(string Parametro1)
{ …
{ …
}
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
4. Llaves.
Las llaves deben de estar siempre en líneas separadas y no en la misma línea de las sentencias if, for, while,
switch, etc, esto facilita la lectura y compresión del código.
Correcto:
if (!existeError)
Incorrecto:
if (!existeError ) {…}
if (!existeError ) {…}
6. Uso de #region.
Usa #region para hacer una agrupación lógica de los sectores de código, esto permitirá la identificación
rápida.
Mantén privadas las variables globales a la clase, las propiedades y los métodos deberán de ubicarse en la
parte superior del archivo y los elementos públicos en la parte inferior
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
1. Métodos largos.
Se debe de evitar escribir métodos muy largos en la medida de lo posible, típicamente un método
deberá de tener entre 1 y 40 líneas de código, si el método contiene más de 40 líneas de código se
deberá de considerar el re factorizarlo en métodos separados.
2. Nombres Descriptivos.
El nombre de los métodos deberá de describir de forma clara lo que ejecutara, si el nombre del método
es suficientemente claro, no habrá que documentar la explicación de su función.
Correcto:
void CrearUsuario ( DataTable UsuarioDetalle )
{ …
Incorrecto:
void SalvaDetalle (DataTable DetEmp)
{ …
}
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
3. Código atómico.
El método deberá de tener solo una tarea o fin, no se debe de combinar tareas en un solo método por más
pequeñas que estas sean.
Correcto:
// Crea Usuario
EnviaCorreo(uuidUsuario, CorreoContenido);
Incorrecto:
// Crea Usuario
// Tarea 1
// Crea usuario
// Tarea 2
// Envía un correo activación de cuenta
// Tarea N
}
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Siempre verifica valores inesperados, por ejemplo, si estas usando un parámetro con 2 posibles valores,
nunca asumas que si uno no concuerda entonces la única posibilidad es el otro valor.
Correcto:
if (TipoMiembro == Usuario.Registrado )
{
// Usuario registrado
}
else if ( TipoMiembro == Usuario.Invitado )
{
// Usuario invitado
}
else
{
// Usuario no esperado, se genera una excepción controlada
throw new Exception ( “Error “ + Usuario.ToString())
}
Incorrecto:
if ( tipoMiembro == usuario.registrado )
{
// Usuario registrado
}
else
{
// Usuario invitado
// Si nosotros creamos un nuevo tipo de usuario en el futuro,
// este código no funcionara de forma adecuada, no te darás cuenta
}
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
6. Comparaciones explicitas
Se considera una mala práctica evaluar o comparar una expresión boleana contra expresiones true o
false.
Correcto:
if (VariableBoleana)
Incorrecto:
if ( VariableBoleana == false)
if ( VariableBoleana != false)
7. Uso de Return.
Un método solo deberá de tener una entrada y una salida de tal forma que el uso de la directiva return
debe de estar al final del método, no es recomendable tener múltiples return en la rutina de código.
No se deben de usar cadenas de texto en código, es preferible usar archivos de recursos externos a la
funcionalidad del código, por ejemplo, un catálogo de errores.
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Cuando se hagan comparaciones entre cadenas, es importante convertir las cadenas a minúsculas o
mayúsculas antes de compararlas para que el resultado se asegure que pueda coincidir.
if (Nombre.ToLower() == “juan” )
{ …
}
Correcto:
if (Nombre == String.Empty)
{ …
}
if (Nombre.Lenght == 0)
{ …
}
Incorrecto:
if (Nombre == “” )
{
…
}
Correcto:
enum TipoProveedorBaseDatos
{
SqlClient,
OracleClient,
Odbc
}
Incorrecto:
void dataAccessLayer ( string tipoProveedorBD )
{
switch (tipoProveedorBD)
{
case “sqlClient”:
// Haz algo
break;
case “oracleClient”:
// Haz algo
break;
case “odbc”:
// Haz algo
break;
default:
// Haz algo
break;
}
}
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Correcto:
BtnGuardaUsuario_Click(Object sender, EventArgs e) Handles btnGuardaUsuari.Click
{
GuardarUsuario();
}
Incorrecto:.
Correcto:
public string GeneraMensaje (string[] Lineas)
{
StringBuilder Mensaje = new StringBuilder();
for (int i = 0; I < Lineas.Lenght; i++)
{
Mensaje.Append(Lineas[i]);
}
return Mensaje.ToString();
}
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Incorrecto:
public string GeneraMensaje (string[] Lineas)
{
string Mensaje = string.Empty;
for (int i = 0; i < Lineas.Lenght; i++)
{
Mensaje += Lineas[i]
}
return Mensaje;
}
Correcto:
public Form2()
{
this.Click += (s, e) =>
{
MessageBox.Show(((MouseEventArgs)e).Location.ToString());
};
}
Incorrecto:
public Form2()
{
this.Click += new EventHandler(Form1_Click);
}
Este segmento de código regresara un True, algo no esperado por que 10 siempre es True.
var x = 0;
if ( x = 10 )
Este segmento de código regresara un False, algo no esperado por que 0 siempre es False.
var x = 0;
if ( x = 0 )
var x = 10;
switch(x) {
case 10: alert("Hello");
}
var x = 10;
switch(x) {
case “10”: alert("Hello");
}
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
var x = 10;
var y = 5;
var x = 10;
var y = “5”;
var x = 10;
var y = document.getElementById("campoConValor5");
if (z == 0.3) // La comparación nos dará un false ya que los dos números no son iguales
La recomendación es manejar los valores en entero multiplicándolos por una constante 10 y tratarlos
Correcto:
var persona = [];
persona [0] = "Juan";
persona [1] = "Montes";
persona [2] = 32;
var x = persona.length; // person.length regresara el valor 3
var y = persona [0]; // persona[0] regresara el valor “Juan”
Incorrecto:
var persona = [];
persona [“nombre”] = "Juan";
persona [“apellidoPaterno”] = "Montes";
persona [“edad”] = 32;
var x = persona.length; // person.length regresara el valor 0
var y = persona [0]; // persona[0] regresara el valor undefined
Correcto:
numeroPersonas = arr.length;
for ( i = 0; i < numeroPersonas; i++) {
Incorrecto:
for (i = 0; i < arr.length; i++) {
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Correcto:
obj = document.getElementById("texto");
obj.innerHTML = "Hola Mundo";
obj style.color = “red”;
Incorrecto:
document.getElementById("texto").innerHTML = "Hola Mundo";
document.getElementById("texto").style.color = “red”;
Correcto:
document.getElementById("nombreCompleto").innerHTML = nombre + " " + apellidoPaterno + “ “ + apellidoMaterno
Incorrecto:
var nombreCompleto = nombre + " " + apellidoPaterno + “ “ + apellidoMaterno;
document.getElementById("nombreCompleto ").innerHTML = nombreCompleto;
Correcto:
Correcto:
var o = {
nombres: 'Gonzalo',
apellidos: 'Chacaltana',
algunaFuncion : function() {
console.log(this.nombres);
};
Incorrecto:
o.nombres = 'Gonzalo';
o.apellidos = 'Perez';
o.algunaFuncion = function() {
console.log(this.nombres);
}
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Incorrecto:
12. Omitir el uso de la palabra clave var varias veces para la declaración de múltiples.
variables
Correcto:
var edad = 14, peso = 56, talla = 166;
Incorrecto:
var edad = 14;
var peso = 56;
var talla = 166;
13. Siempre deberá de finalizar una línea de código con punto y coma “;”
Siempre que se finalice una línea de código deberá de colocar un punto y coma “;” cuando la función
de la línea de comando concrete su función, esto evitara muchos errores y hará más fácil la ubicación
de un error.
Correcto:
var cadenaEjemplo = 'cadena de ejemplo;
function obtenUsuario() {
return 'Pedro Lopez';
}
Incorrecto:
var cadenaEjemplo = 'cadena de ejemplo
function obtenUsuario() {
Si desea probar si existe un objeto, esto generará un error si el objeto no está definido:
Correcto:
if (typeof myObj !== "undefined" && myObj !== null)
Incorrecto:
if (myObj !== null && typeof myObj !== "undefined")
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Estas son algunas de las palabras reservadas de Objetos, Propiedades y Métodos en JavaScript.
7. Base de Datos
1. Uso de SELECT *
No se debe de usar la sentencia “SELECT * FROM TABLA”, el traer todas las columnas de una tabla provoca un
desbordamiento de IOPS en un servidor de base de datos, se debe de traer única y exclusivamente la
información indispensable
El motivo de esta mejor práctica es que cuando SQL Server recibe una consulta, como una declaración
Select, lo primero que hace es compilarla, crear un plan de ejecución, y finalmente ejecutarlo; todos
estos pasos consumen tiempo, cuando se invoca un procedimiento almacenado, este procedimiento
almacenado puede ser compilado si es la primera vez que es llamado, o si cambian las estadísticas que le
afecten, pero en caso contrario no es compilado y es almacenado en el caché; el plan de ejecución
también es almacenado en el caché. El llamar un procedimiento almacenado ahorra tiempo de ejecución
y recursos
4. UNION vs JOIN.
Usar la cláusula Join con estándar ANSI. Para unir tablas es mejor usar la cláusula Join que
hacer una unión por medio de la cláusula Where. A pesar de que a partir de SQL Server 7.0 las
uniones de tablas usando Where pueden ser traducidas por el plan de ejecución a uniones
explícitas, el hecho es que el compilador es quien hace esa conversión, lo cual le toma tiempo y
recursos
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
7. Uso WITH(NOLOCK).
Cuando se ejecute una consulta de tipo Selección se deberá de hacer siempre usando la
sentencia WITH(NOLOCK), esto hace que la consulta no tenga que esperar a que la tabla se
libere de afectaciones, pudiendo recuperar los datos con una fotografía del momento que se
ejecutó, por otro lado mitiga interbloqueos entre proceso
BEGIN TRANSACTION;
BEGIN TRY
—sentencia
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK;
SELECT ERROR_MESSAGE();
END CATCH;
SELECT MIN(Salary) FROM Employees WHERE EmpID IN ( SELECT TOP 2 EmpID FROM Employees
ORDER BY Salary DESC )
La misma consulta puede ser re-escrita usando una tabla derivada, como se muestra a
continuación, y será el doble de rápida que la consulta anterior.
SELECT MIN(Salary) FROM ( SELECT TOP 2 Salary FROM Employees ORDER BY Salary DESC ) AS
A
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
Se debe intentar evitar el uso de caracteres comodín al inicio de una palabra al hacer una
búsqueda usando el identificador LIKE, ya que eso ocasiona un rastreo en el índice (index
scan), lo cual se contrapone con el objetivo de usar índices. El primero de los siguientes
códigos genera un rastreo en el índice, mientras que el segundo genera una búsqueda en el
índice (index seek).
También se deben evitar las búsquedas utilizando operadores de no igualdad (<> y NOT) ya
que éstos resultan en rastreos de índices y tablas.
16. VARCHAR(MAX).
Los campos que sean de tipo cadena, deberán de tener una constante como máximo de
caracteres que se pueden admitir, está restringido usar la directiva MAX.
8. Arquitectura.
2. No tercerizar componentes.
Evitar al máximo elementos de “terceros” en el entorno de desarrollo o arquitecturas, ya que comprometen la
escalabilidad futura, pues esos “terceros” no saben cómo Microsoft orientará su próxima estrategia de desarrollo
y puede comprometer el proyecto. Por ejemplo Microsoft ahora apuesta ahora por jQuery, por lo que los otros
actores (Dojo, MooTools, Prototype…) pueden quedar fuera de juego. Hay que adoptar aquellos frameworks
que Microsoft adopte claramente o podríamos quedar fuera del juego, la historia está llena de casos tecnológicos
con grandes expectativas, como por ejemplo Adobe Flash, Microsoft ha apostado por HTML5.
5. Encapsular código.
Se debe de separar la aplicación en múltiples ensamblados y métodos, esto permitirá la re utilización de código
de forma sencilla, y dejara organizado el sistema por funcionalidades más específicas.
7. KAIZEN
Metodología de calidad en la empresa y en el trabajo, en su vertiente para los desarrolladores IT nos
dice: “A los informáticos nos gusta la tecnología, nos imaginamos grandes catedrales de
arquitecturas”. Olvidemos las catedrales, recordemos a KISS.
El principio de responsabilidad única nos indica que debe existir un solo motivo por el cual
la clase debe ser modificada, o sea, que la clase debe tener un solo propósito. Es el principio
más fácil de violar.
b. OCP (Open-Closed Principle):
El principio Abierto/Cerrado indica que las clases deben estar abiertas para la extensión
y cerradas para la modificación, o sea, que una clase debe poder ser extendida sin tener
que modificar el código de la clase.
El principio de sustitución de Liskov indica que las clases derivadas (hijas) pueden ser sustituidas
por sus clases base. Se promueve que la herencia se realice en forma transparente, o sea, no se
debe implementar métodos que no existan en sus clases base ya que de lo contrario se rompe el
principio.
“De OCP y LSP se deduce que las clases base (abstractas o no) modelan el aspecto
general y las clases heredadas modelan el comportamiento local.”
d. ISP (Interface Segregation Principle):
El principio de segregación de interfaces indica que hay que hacer interfaces de grano fino que
son específicos de clientes, dicho de otra forma, muchas interfaces muy especializadas son
preferibles a una interfaz general en la que se agrupen todas las interfaces.
El principio de inversión de dependencias indica que las abstracciones no deben depender de los
detalles, los detalles deben depender de las abstracciones.
ENGINE CORE Ciudad de México
01 de octubre de 2019
CONVENCIÓN DE ESTANDARES
9. Taxonomiza
Como llamar a los conceptos de una forma convencional y que todos los involucrados conozcan, por ejemplo,
EMail o CorreoElectronico lo correcto es general un diccionario de términos que diga.
10. Sé ACID (Atomicity, consistency, isolation, and durability) con los datos
Atomicidad: es la propiedad que asegura que la operación se ha realizado o no, y por lo tanto ante
un fallo del sistema no puede quedar a medias.
Consistencia: Integridad. Es la propiedad que asegura que sólo se empieza aquello que se puede
acabar. Por lo tanto, se ejecutan aquellas operaciones que no van a romper las reglas y directrices
de integridad de la base de datos.
Aislamiento: es la propiedad que asegura que una operación no puede afectar a otras. Esto asegura
que la realización de dos transacciones sobre la misma información sean independientes y no
generen ningún tipo de error.
Durabilidad: es la propiedad que asegura que una vez realizada la operación, ésta persistirá y
no se podrá deshacer aunque falle el sistema.