c# – ¿Qué estrategias usas para no escribir comentarios?

Si luego de leer el post anterior te has preguntado ¿Cómo evito escribir comentarios? te recomiendo que sigas leyendo.
Comentarios innecesarios
Comentarios innecesarios

1. ¿Qué debo hacer para dejar de escribir comentarios sin valor y qué solo generan ruido en el código?
Respuesta: Debes escribir nombres claros y fáciles de entender.

Nota: Se sugiere que las clases tengan como nombre un sustantivo y los métodos un verbo.

1.1 Clases:

Evil Code:

//Clase que genera reportes PDF
public class Reporte{}

//Clase que contiene funciones matemáticas
public class Calc{}

//Clase que contiene la lógica para caducar Polizas
public class ServCadPol{}

Clean Code

public class GeneradorReportePdf{}
 
public class Calculadora{}
 
public class ServicioCaducarPoliza{}

Nota: Cualquier clase que solo se llame: Util, Helper o Manager, quiere decir que no tiene una responsabilidad clara y hace muchas cosas a las vez.

1.2 Métodos:

Evil Code:

//Obtiene los codigos generados por fecha
public List<string> Obtener(Datetime fecha)
 
//Calcula los descuentos que se tiene que aplicar por fecha
public void Procesar(Datetime fecha)
 
//Caduca una poliza
public void Opera84784(RequestOpera84784 request)

Clean Code:

public List<string> ObtenerCodigosGeneradosPorFecha(Datetime fecha)
 
public void CaclcularDescuentosPorFecha(Datetime fecha)
 
public void CaducarPoliza(Poliza poliza)
1.3 Variables:

Evil Code:

//Nombre completo del usuario
string n;
 
//Fecha de regsitro
Datetime d;

//IGV
double i = 1.8;

Clean Code:

string nombreCompletoUsuario;
Datetime fechaRegistro;
double IGV;
2. ¿Qué debo hacer para dejar de usar regiones que encierren distintas funcionalidades dentro de clases o métodos?
Respuesta: Debes aplicar el Principio de Responsabilidad Única.

Nota: Cuando se usan regiones para ocultar muchas responsabilidades ocasionan que la cohesión de una clase disminuya. Recuerden alta cohesión y bajo acoplamiento.

2.1 Clases

Evil Code:

public class Util
{
	#region Encriptacion
	//Codigo
	#endregion

	#region Notificacion
	//Codigo
	#endregion

	#region Formato
	//Codigo
	#endregion

	#region Log
	//Codigo
	#endregion
}

Clean Code:

Por cada responsabilidad identificada se debe crear una clase para que haga exactamente una cosa y que la haga bien:

public class ServicioEncriptacion{}
public class ServicioNotificacion{}
public class ServicioLog{}
2.2 Métodos:

Evil Code:

//Caduca una poliza y notifica al administrador
public void Actualizar(Poliza poliza)
{ 
	//Llamada al servicio web del cliente para caducar una poliza
	ServicioWebPolizaExterno servicioPoliza = new ServicioWebPolizaExterno();
    RequestOpera105874 requestCaducarPoliza;
	//Código...
	servicioPoliza.Opera105874(requestCaducarPoliza);
	//Llamada a web service
	 
	//Envió de correo al responsable de la poliza
	ServicioNotificacion servicioNotificacion = new ServicioNotificacion();
    Mensaje mensajeResponsable;
	//Código...
	servicioNotificacion.EnviarNotificacion(mensajeResponsable);
	//Envió de correo

	//Log Traza 
	ServicioTraza servicioTraza = new ServicioTraza();
    Traza trazaPolizaCaducada;
	//Código...
	servicioTraza.Registrar(trazaPolizaCaducada);
	//Log Traza
}

Clean Code:

public void CaducarPoliza(Poliza poliza)
{
	CaducarPolizaServicioExterno(poliza);
	EnviarNotificacionResponsable(poliza);
	RegistroLogPoliza(poliza);
}

private void CaducarPolizaServicioExterno(Poliza poliza)
{
	ServicioWebPolizaExterno servicioPoliza = new ServicioWebPolizaExterno();
    RequestOpera105874 requestCaducarPoliza;
	//Código...
	servicioPoliza.Opera105874(requestCaducarPoliza);
}

private void EnviarNotificacionResponsable(Poliza poliza)
{
	ServicioNotificacion servicioNotificacion =  new ServicioNotificacion();
    Mensaje mensajeResponsable;
	//Código...
	servicioNotificacion.EnviarNotificacion(mensajeResponsable);
}

private void RegistroLogPoliza(Poliza poliza)
{
	ServicioTraza servicioTraza =  new ServicioTraza();
    Traza trazaPolizaCaducada;
	//Código...
	servicioTraza.Registrar(trazaPolizaCaducada);
}

Nota: Si los métodos resultantes se utilizan también en otras clases lo recomendable es crear una clase por cada responsabilidad para evitar repetir ese código, recuerden el principio DRY.

3. ¿Qué hago si el código es difícil de entender?
Respuesta: Debes dividir el código en distintos métodos.

Evil Code:

//Si el usuario existe, no esta bloqueado, no expiro su contraseña
//y esta habilitado para cambiar su contraseña
if(
(usuario != null && !string.IsNullOrEmpty(usuario.DistinguishedName) ) &&
!(((int)usuario.Propiedad["msDS-User-Account-Control-Computed"]) 
& 16/*flag AccountLockedOut*/ ) &&
!(((int)usuario.Propiedad["msDS-User-Account-Control-Computed"]) 
& 64/*flag PasswordCannotChange*/ ) &&
(((int)usuario.Propiedad["msDS-User-Account-Control-Computed"]) 
& 8388608/*flag PasswordExpired*/ )
)
{
	//Codigo
}
else
{
	//Codigo
}

Clean Code:

var usuarioPuedeCambiarContrasena = 
		UsuarioExiste(usuario) && 
		!UsuarioBloqueado(usuario) && 
		!UsuarioContrasenaExpiro(usuario) && 
		UsuarioPuedeCambiarContrasena(usuario);

if(usuarioPuedeCambiarContrasena )
{
	//Codigo
}
else
{
	//Codigo
}

const string AtributoControlCuentaAD ="msDS-User-Account-Control-Computed";

bool UsuarioExiste(Usuario usuario)
{
	return usuario != null && 
		!string.IsNullOrEmpty(usuario.DistinguishedName);
}

bool UsuarioPuedeCambiarContrasena(Usuario usuario)
{
	int flagNoPuedeCambiarContrasena = 64;
	return !(((int)usuario.Propiedad[AtributoControlCuentaAdam]) 
		& flagNoPuedeCambiarContrasena );
}

bool UsuarioBloqueado(Usuario usuario)
{
	int flagCuentaBloqueada = 16;
	return (((int)usuario.Propiedad[AtributoControlCuentaAdam]) 
		& flagCuentaBloqueada );
}

bool UsuarioContrasenaExpiro(Usuario usuario)
{
	int flagContrasenaExpiro = 8388608;
	return (((int)usuario.Propiedad[AtributoControlCuentaAdam]) 
		& flagContrasenaExpiro );
}
4. ¿Dónde puedo guardar los cambios hechos en el código y sobre todo que sean durables?
Respuesta: Debes usar un administrador de código fuente.

Evil Code:

//BUG: No se valido que la variable tenga un valor 10/12/2012
if(objeto != null) {}
 
//Agregado por laldazabal
if(objeto != null) {}

//Cambio 10/10/2001 - Se renombro el metodo
//Cambio 10/12/2012 - Se agrego un parametro nuevo
//Cambio 10/06/2014 - Se reemplazo el metodo, no funcionaba
servicioCorreo.EnviarNotificacionEnCadena();

Clean Code:

En estos caso se debe usar una herramienta de control de código fuente como: TFS, GitHub, Subversion, Mercurial, Visual SourceSafe, etc.

En mi caso uso el TFS para controlar las versiones, cada vez que se sube un nuevo archivo queda registrado con el usuario que hizo el check-in.

Tfs - View History - Archivo Agregado
Tfs – View History – Archivo Agregado

También nos ayuda a ver en el tiempo todos los cambios que han ocurrido, con esta funcionalidad ya no es necesario dejar código comentado, ya que podemos recuperar una versión anterior en cualquier momento.

Tfs - View History - Cambios
Tfs – View History – Cambios
Conclusión

Dejar de escribir comentarios en el código fuente no es difícil, solo debemos invertir un poco más de tiempo en definir nombres que sean claros y legibles. Aplicando principios de diseño, como el de responsabilidad única, nos permite volver al código fácil de leer y mantener. Finalmente, para controlar las versiones del código fuente debemos apoyarnos en herramientas como: TFS, Github, Subversion, etc.

Si te gusto este post entonces por favor ayúdame a difundirlo y logremos que el conocimiento se expanda, para lograr esto dale me gusta, compártelo en tus redes sociales a tus amigos o suscríbete a mi canal RSS, Gracias :).
Referencias:
Metal Tip:

Este artículo lo escribí escuchando la canción Desperate Cry de la banda de Sepultura de Brazil, les comparto el enlace.

Happy coding and Stay Heavy lml

Anuncios

12 comentarios en “c# – ¿Qué estrategias usas para no escribir comentarios?

      1. no esta mal para las clases de servicios del dominio o servicios de aplicacion el tener como nombre la combinacion Sustantivo-Verbo o Verbo-Sustantivo por ejemplo TransferirProductos, etc etc ….. buen post !!

        Le gusta a 1 persona

  1. las clases que pueden tener de nombre la combinacion Sustantivo-Verbo / Verbo-Sustantivo deben ser clases de servicio de aplicacion o de servicios del dominio por ejemplo TransferirProductos , etc etc

    Me gusta

    1. Hola CristianDC,
      tienes razón en lo que mencionas, cuando he usado el patrón CQS al asignarle un nombre a los comandos tenían la siguiente forma ‘Comando+Verbo+Sustantivo’, por ejemplo: ComandoIniciarSesion, ComandoCambiarContrasena

      Saludos

      Le gusta a 1 persona

  2. Hola,

    Me parecen en general buenos consejos. (No estoy deacuerdo con lo de Helper,Manager siempre y cuando formen parte de nombre al igual que lo hace Service, e.g. ContractManager).

    Una idea que me gusta aplicar es que nua variable que es bool, tenga su nombre en forma de pregunta.
    Por ejemplo:

    bool isGreen = true;
    // ….
    if (isGreen)
    // …

    Me gusta

    1. Hola, es correcto lo que mencionas el problema radica cuando el nombre de la clase solo es: Util, Helper o Manager, ya que no expresan mucho. La idea es usar un sustantivo que expresa su responsabilidad.

      Saludos

      Me gusta

  3. Si bien me gusta la mayoría, la sección de los condicionales no es para nada óptimo y son un montón de condiciones innecesarias que dependiendo de la aplicación esto podría ser un caos. Saludos desde Colombia! 😀

    Le gusta a 1 persona

    1. Hola Camilo,

      Lo recomendado para condicionales complejas es usar variables para almacenar el resultado o encapsularlas dentro de funciones. Acá podemos aplicar esta idea: usar código expresivo sobre comentarios.

      Saludos desde Lima – Peru 😉

      Me gusta

    1. Hola Willian, lo recomendable es escribir el nombre completo de la variable: nombreCompleto, estadoOrdenPagado, etc, muchas veces uno usa abreviaturas que solo el entiende: nbrC, estOrdPag. Recuerda que el código debe ser fácil de leer y al usar variables con nombres claros estas apoyando a que se cumpla ese objetivo. En el caso de acronimos si es permitido usarlos: IGV, IVA, etc.

      Me gusta

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s