Revisión de código administrado

Enero de 2007

Publicado: 26 de Febrero de 2007

John D'Addamio
Microsoft Corporation

Este artículo se aplica a:
.NET Framework

Resumen: En este artículo se incluyen recomendaciones para la revisión de código administrado. Algunas prácticas son comunes a la revisión de código administrado y no administrado. Otras son exclusivas de la revisión de código administrado. No es necesario ser un revisor experimentado de código administrado.

En esta página

Introducción Introducción
Instrucciones relacionadas recomendadas Instrucciones relacionadas recomendadas
Prácticas recomendadas Prácticas recomendadas
Conclusión Conclusión

Introducción

La revisión de código administrado es más fácil que la de código no administrado. En algunos aspectos, la revisión de código administrado es más fácil que la de otro tipo de código. El compilador comprueba los tipos, lo que evita la asignación accidental de datos incompatibles a un objeto. El compilador también comprueba si se han usado variables que no se han inicializado. Estas y otras comprobaciones de compilación evitan un gran número de errores que teníamos que buscar al realizar revisiones de código. Además, las comprobaciones de tiempo de ejecución detectarán otros problemas comunes y contendrán el daño mediante el inicio de una excepción. En otros aspectos, el código administrado agrega algunos problemas que no existen en otros lenguajes, como los elementos XML y los archivos de recursos del propio archivo de origen

En este documento se presentan recomendaciones para la revisión de código administrado. Si bien se da por sentado que le resulta familiar al menos un lenguaje administrado, como C# o VB.NET, no es necesario ser un revisor experimentado de código administrado.

Instrucciones relacionadas recomendadas

Existen muchas instrucciones relacionadas en MSDN. Si bien el fin de muchas es proporcionar instrucciones de diseño, obviamente pueden aplicarse también a las revisiones de código. A continuación incluimos unas cuantas:

  1. Instrucciones de diseño de .NET

  2. Instrucciones de nomenclatura

  3. Instrucciones de tipos de conversión

Prácticas recomendadas

Uso de FxCop para implantar estándares de codificación

FxCop es una herramienta de análisis de código que comprueba la conformidad de los ensamblados de código administrado de .NET con las Instrucciones de diseño de .NET indicadas anteriormente. FxCop ofrece reglas estándar de análisis de código y le permite personalizar las reglas de su proyecto. La supresión de advertencias de FxCop también se permite en el código fuente. Puede obtener más información o descargar FxCop y su documentación, sin costo, de la página FxCop Team Page (en inglés).

Ejecución de FxCop en el código que se está revisando

Defina una configuración de generación estándar que ejecute el análisis de código de FxCop que debe implementar cada proyecto. Como parte de una revisión de código, compruebe que el proyecto ha implementado correctamente su configuración de generación de FxCop estándar y que el código que se está revisando pase la evaluación de FxCop mediante la creación de la configuración de FxCop

Comprobación de la supresión de errores de FxCop en el código fuente

Busque en el código en proceso de revisión mensajes de FxCop suprimidos. Puede usar Ctrl + F para buscar en el proyecto actual "CodeAnalysis". Si encuentra cualquier supresión de FxCop, compruebe que son legítimamente necesarias y que la razón de la supresión se explica de forma clara en comentarios. Ocasionalmente, quizá compruebe que la supresión no es necesaria, pero que la persona escribió el código no ha sabido cómo corregir el error. Por ejemplo, la siguiente supresión es innecesaria

// FxCop doesn't like the "\n\n" so we're suppressing the error message here. 
[System.Diagnostics.CodeAnalysis.SuppressMessage ("Microsoft.Globalization", 
"CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = 
"System.Windows.Forms.TextBoxBase.AppendText(System.String)")] 
this.resultsTextBox.AppendText ("\n\n" + Strings.contextErrorMessage);

Un cambio sencillo de código, como se muestra aquí, evita el error de FxCop.

this.resultsTextBox.AppendText( Environment.NewLine + 
Environment.NewLine + Strings.contextErrorMessage);

Revisión de la lógica

Por supuesto, los puntos principales de la revisión de código son la búsqueda de desperfectos en la lógica (errores) y la implantación de los estándares de codificación del equipo. El uso de FxCop para implantar los estándares de codificación le permitirá dedicar más tiempo a revisar la lógica del código.

.NET Framework tiene muchas clases y cada una, muchos métodos, lo que puede resultar complicado. No se espera que nadie conozca todas las clases o métodos. Use libremente las descripciones de IntelliSense para las clases o métodos.

Si no puede entender lo que el código hace a partir de los comentarios existentes y las descripciones de IntelliSense de las clases o los métodos, el código no tiene suficientes comentarios. Si piensa que la lógica no hace lo que pretende el autor, o bien la lógica contiene errores o el código no tiene suficientes comentarios que la aclaren.

Creación

Es recomendable crear el código en todas las configuraciones del proyecto. Quizás el autor se haya olvidado de crearlo en todas las configuraciones. Si no se crea en todas configuraciones, debe solicitar al autor que corrija los errores antes de enviar el código

Por ejemplo, es común definir la configuración de lanzamiento para excluir las pruebas unitarias. Si se realizan cambios en una firma de método pero no se actualizan las pruebas unitarias, el código se crearía correctamente en la configuración de lanzamiento pero no en la configuración de depuración

Búsqueda de pruebas unitarias

Al revisar código nuevo, espere que las pruebas unitarias se presenten a la vez que el código funcional. Suele resultar demasiado fácil dejarlo para más tarde.

Al revisar los cambios de código, puede que sea necesario contar con pruebas unitarias nuevas o revisadas. Ejecute las pruebas unitarias existentes y cualquiera que se haya enviado con la revisión de código. Si no se superan las pruebas unitarias, solicite que el autor actualice el código funcional y/o las pruebas unitarias, para que finalmente se superen.

Búsqueda de la validación de parámetros

Es una práctica recomendada para que un método valide sus parámetros de entrada. Si un parámetro no es válido, el método debe llevar a cabo una acción apropiada. Por ejemplo, se debe comprobar si un parámetro de cadena es un objeto

Null o es igual a String.Empty. Quizás en una situación en la que String.IsNullOrEmpty devuelve true, el inicio de una excepción (por ejemplo, ArgumentException o ArgumentNullException) resulte una acción apropiada. Sin embargo, en otra situación, puede que el método simplemente regrese al autor de la llamada sin llevar a cabo ninguna acción.

Al revisar código, busque los valores de parámetro que puedan causar algún comportamiento no deseado. Los valores "incorrectos" quizás sean tan obvios como en el ejemplo de cadena que se muestra a continuación, aunque quizás sean menos manifiestos. Por ejemplo, imagine una cadena que se supone que representa datos numéricos entre 0,0 y 100,0. Puede que el código desee realizar alguna validación además de la comprobación nula, como la reducción de espacios en blanco a la derecha y a la izquierda, convirtiendo así la cadena a formato numérico y validando que el valor se encuentra en el rango esperado

Comentarios

Elementos XML necesarios

Cada definición de clase y todos los miembros públicos deben tener etiquetas summary de XML para describir la clase o el miembro. Esto permite que los usuarios de la clase vean la descripción al modificar el código. La etiqueta de XML parameter es también necesaria, cuando corresponde. En Visual Studio 2005, los editores de código C# y VB insertarán automáticamente las etiquetas summary y parameter, si escribe /// y ''' (respectivamente) en una línea en blanco encima de la definición de clase o método. Esto resulta muy útil, ya que no tiene que escribir las definiciones de etiquetas XML correctamente. Sólo tiene que escribir las descripciones.

Si su equipo usa encabezados XML más elaborados para las definiciones de clase o miembro (por ejemplo, algunos equipos requieren encabezados XML que describan el historial de cambios, incluyendo la descripción del cambio, autor y fecha), compruebe que los encabezados están presentes y que se han introducido los datos apropiados.

Validación de todos los elementos XML

Cerciórese de que todos los elementos XML están bien constituidos. Esto es importante, ya que las herramientas que manejan comentarios XML en el código fuente requieren un código XML bien constituido que funcione correctamente.

Elimine cualquier elemento XML generado automáticamente que esté vacío, si el equipo no lo necesita. Por ejemplo,VB genera automáticamente elementos returns y remarks que se pueden eliminar en muchos casos.

Comentarios adicionales

Compruebe que el código tiene suficientes comentarios adicionales para describir el uso, la lógica o el comportamiento de los elementos del código.

Calidad de los comentarios

Los comentarios deben ser claros y describir exactamente el código asociado. Existen varias situaciones comunes en las que los comentarios no coinciden con el código. Téngalas en cuenta. Por ejemplo, si se cambia el código existente en un módulo, la actualización de los comentarios a veces se pasa por alto. O, si se adapta una sección de código de otra aplicación a un propósito actual, puede que los comentarios del código original no sean apropiados o exactos.

Constantes de cadena

Archivos de recursos de cadena

Los literales de cadena se deben empaquetar en un archivo de recursos de cadena. Éste reúne las cadenas en un lugar, de forma que resulta más sencillo aplicar cambios al texto de la cadena. El uso de archivos de recursos de cadena permite también la localización y la globalización. La creación y el uso de archivos de recursos de cadena solía ser algo incómodo. Sin embargo, la Herramienta de refactorización de recursos puede ayudarle con este problema, al menos para los proyectos de C# y VB. Por ejemplo, los literales de cadena de la instrucción siguiente:

private static string snippetSchemaPathBegin = 
Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles%"), 
@"\Microsoft Visual Studio 8\Xml\Schemas");

pueden, gracias a la Herramienta de refactorización de recursos, cambiarse rápidamente a lo siguiente:

private static string snippetSchemaPathBegin = 
Path.Combine(Environment.ExpandEnvironmentVariables( Strings.ProgramFiles), 
Strings.MicrosoftVisualStudio8XmlSchemas);

Rutas de acceso y nombres de archivo

Al revisar código, busque referencias a los literales de cadena o archivos de recursos de cadena que contengan rutas de acceso de archivos incluidas en el código. Use siempre variables de entorno, las API de .NET que ofrezcan un nombre de ruta (por ejemplo, System.Windows.Forms.Application.ExecutablePath, que devuelve la ruta de acceso del archivo ejecutable que ha iniciado la aplicación) o una entrada de archivo de configuración para hacer referencia a rutas de acceso. Los usuarios suelen instalar programas en unidades que no son C y, de vez en cuando, personalizan la ubicación de instalación en otros aspectos.

De forma parecida, los nombres de archivo de aplicación no se deben definir en una referencia a un literal o archivo de recursos de cadena. Las alternativas aceptables son un archivo de configuración, variables de entorno o una entrada del usuario, como un parámetro de una aplicación de consola o un cuadro de diálogo de archivo en una aplicación de WinForms. Cualquiera de estas alternativas le permite más flexibilidad al usuario a la hora de usar su aplicación

En el ejemplo siguiente, se muestran varias prácticas incorrectas, incluida una variable pública y una ruta de acceso no modificable

public static readonly string SnippetSchemaPathBegin = @"C:\Program 
Files\Microsoft Visual Studio 8\Xml\Schemas\";

La instrucción se podría reescribir mediante una propiedad pública y la variable de entorno SystemDrive, como se muestra a continuación.

public string SnippetSchemaPathBegin { get { return 
snippetSchemaPathBegin; } } private static string snippetSchemaPathBegin = 
Environment.ExpandEnvironmentVariables("%SystemDrive%" + @"\Program 
Files\Microsoft Visual Studio 8\Xml\Schemas");

De forma parecida, se podría usar la variable de entorno ProgramFiles, como se muestra a continuación.

private static string snippetSchemaPathBegin = 
Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"), @"Microsoft 
Visual Studio 8\Xml\Schemas");

Convenciones de nomenclatura

Nombres

En general, los nombres deben ser legibles y deben describir claramente el elemento. Por lo tanto, intente usar abreviaturas en los nombres, nombres cortos o nombres no descriptivos al realizar revisiones de código. Es recomendable que los nombres de función y método empiecen con un verbo, con el fin de denotar la acción que realizan en sus objetos. De forma similar, los nombres de variable y propiedad deben ser sustantivos, ya que se trata de objetos. Por ejemplo, si escribiera una clase para objetos de geometría plana, como un círculo, podría definir propiedades denominadas CenterPoint y Radius. Entre los nombres de función de dicha clase se podrían incluir CalculateCircumference y CalculateArea.

Convenciones de mayúsculas y minúsculas en los nombres

Compruebe que el código fuente sigue las convenciones de mayúsculas y minúsculas recomendadas en la sección acerca de los estilos de mayúsculas y minúsculas de la documentación de instrucciones de nomenclatura recomendada anteriormente. En otras palabras, use camelCasing (la primera letra del nombre está en minúsculas y la primera letra de cada palabra posterior del nombre en mayúsculas) para parámetros, variables locales y variables privadas o protegidas de una clase. Use PascalCasing (la primera letra de cada palabra del nombre está en mayúsculas) para prácticamente todo lo demás, incluidos los nombres de clase, métodos, propiedades, declaraciones de tipo y valores enum.

No acepte la notación húngara

No se recomienda la notación húngara para el código administrado. La notación húngara es difícil de usar correctamente, así como difícil de leer. Las dificultades de lectura de la notación húngara pueden también confundir la lógica. Algunos usuarios usan la notación húngara como uno de los hábitos aprendidos al codificar C o C++. Búsquela en las revisiones de código.

Excepciones

Inicio de excepciones

Si el código inicia una excepción, asegúrese de que el tipo de excepción es apropiado y que el mensaje identifica claramente el problema que ha provocado que el código inicie la excepción. Ponga tanta información de depuración en el mensaje de excepción como sea posible. Esto ayudará a diagnosticar el problema, ya proceda de un seguimiento de la pila o de un archivo de registro.

Intercepción de excepciones

Si el código que está revisando llama a un método que es probable que inicie una excepción, compruebe que el código maneja la excepción y que hace algo razonable al manejarlo. Por ejemplo, File.Open inicia varias excepciones comunes, incluidas FileNotFoundException y UnauthorizedAccessException. Sería razonable interceptar esas excepciones y mostrar un mensaje de error al usuario.

Definición de excepciones

Si el código de un ensamblado define las excepciones, defina los tipos comúnmente usados en una clase de excepciones global para el ensamblado. Defina las excepciones exclusivas de una clase en la propia clase.

Formato

Use regiones para organizar el código

Al revisar código, contemple un correcto uso de las regiones para mejorar la legibilidad del código. Las regiones suelen infrautilizarse, aunque a veces se usan demasiado.

Las regiones ayudan a organizar lógicamente el código y mejoran la legibilidad de los archivos grandes, ya que se pueden contraer las regiones innecesarias y consultar sólo la parte de código que se necesita en ese momento. Contraer las regiones facilita también el desplazamiento a través de archivos grandes para encontrar una región de interés. Sin embargo, tenga cuidado al usar las regiones anidadas. El hecho de contraer una región exterior podría esconder las regiones interiores y hacer más difícil encontrar una región de interés.

Entre los lugares comunes donde usar regiones se incluyen las zonas cercanas a los datos privados de una clase, constructores, propiedades públicas, métodos privados y métodos públicos. En un proyecto de prueba, las regiones se usan generalmente para agrupar las pruebas. Por ejemplo, una región podría agrupar las pruebas unitarias para uno de los métodos de la clase.

Use líneas en blanco para separar las definiciones

El uso de líneas en blanco entre definiciones del mismo nivel mejora la legibilidad. Sin embargo, no use más de dos líneas en blanco consecutivas.

Varios

Sin variables públicas

Compruebe que las variables de datos de una clase se declaran como privadas. Si elige permitir el acceso a los datos, defina una propiedad pública o protegida para facilitarle acceso al usuario.

Valores devueltos

Los métodos que devuelven un valor deben usar la instrucción de devolución, en vez de asignarle un valor al nombre del método.

Sin instrucciones GoTo

Las instrucciones GoTo son innecesarias. Ocasionalmente, se puede crear un caso para usarlas en circunstancias especiales, pero deberían dispararse las alarmas al verlas en una revisión de código.

Constantes numéricas

Casi todas las herramientas de depuración muestran constantes numéricas en hexadecimal, de forma predeterminada. Por lo tanto, defina las constantes numéricas en hexadecimal para los identificadores de ventana, los identificadores de control, etc., de forma que no tenga que convertirlos de decimal a hexadecimal durante la depuración.

Conclusión

En este documento se han incluido recomendaciones para la revisión de código administrado. Algunas prácticas son comunes a la revisión de código administrado y no administrado. Otras son exclusivas de la revisión de código administrado.

Mostrar: