Documento Buenas Practicas

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 56

Documento buenas prácticas de

desarrollo de software en .NET


Documento de buenas prácticas .Net Página 2 de 56

Tabla de contenido
1 Introducción .................................................................................................................7
1.1 Propósito ..................................................................................................................7
1.2 Alcance .....................................................................................................................7
1.3 Acrónimos y términos ..............................................................................................7
1.3.1 Acrónimos.........................................................................................................7
1.3.2 Términos ...........................................................................................................7
1.4 Audiencia destino .....................................................................................................7
1.5 Estructura del documento........................................................................................7
2 Introducción a las buenas prácticas del desarrollo en .Net C# ....................................8
3 Convenciones de nomenclatura ...................................................................................9
3.1 Nombres descriptivos...............................................................................................9
3.2 Nomenclatura PascalCase Vs CamelCase .............................................................. 10
3.3 Evitar el uso de abreviaturas ambiguas ................................................................ 12
3.4 Utilizar nombres de archivos descriptivos ............................................................ 12
4 Estructura del proyecto ............................................................................................. 13
4.1 Organizar el proyecto en capas ............................................................................. 14
4.1.1 Capa de Presentación (UI) ............................................................................. 14
4.1.2 Capa de Lógica de Negocio (Business Logic) ................................................. 14
4.1.3 Capa de Acceso a Datos (Data Access) .......................................................... 14
4.1.4 Capa de Infraestructura................................................................................. 14
4.2 Pruebas unitarias ................................................................................................... 15
4.2.1 Aseguran la calidad del software .................................................................. 15
4.2.2 Facilitan el mantenimiento del código .......................................................... 15
4.2.3 Promueven un diseño modular y desacoplado ............................................. 15
4.2.4 Mejoran la colaboración y la productividad del equipo................................ 15
4.2.5 Impulsan la refactorización segura ............................................................... 15
4.3 Control de versiones ............................................................................................. 17
4.3.1 Utilizar un sistema de control de versiones .................................................. 17

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 3 de 56

4.3.2 Estructurar el repositorio .............................................................................. 17


4.3.3 Commits frecuentes y significativos .............................................................. 17
4.3.4 Utilizar ramas para nuevas funcionalidades ................................................. 17
4.3.5 Realizar pruebas y revisión de código ........................................................... 18
4.3.6 Utilizar etiquetas para versiones ................................................................... 18
4.3.7 Documentar los cambios ............................................................................... 18
4.3.8 Mantener un repositorio limpio .................................................................... 18
5 Patrones de Diseño ................................................................................................... 19
5.1 Factory Method ..................................................................................................... 19
5.1.1 Ejemplos ........................................................................................................ 20
5.1.2 Casos de Uso.................................................................................................. 21
5.2 Builder ................................................................................................................... 22
5.2.1 Ejemplos ........................................................................................................ 23
5.2.2 Casos de Uso.................................................................................................. 23
5.3 Facade ................................................................................................................... 24
5.3.1 Ejemplos ........................................................................................................ 25
5.3.2 Casos de Uso.................................................................................................. 25
5.4 Strategy ................................................................................................................. 26
5.4.1 Ejemplos ........................................................................................................ 27
5.4.2 Casos de Uso.................................................................................................. 28
5.5 Mediator ................................................................................................................ 28
5.5.1 Ejemplos ........................................................................................................ 29
5.5.2 Casos de Uso.................................................................................................. 30
6 Manejo de Excepciones ............................................................................................. 32
7 Seguridad................................................................................................................... 33
7.1.1 Validación de entrada de datos..................................................................... 33
7.1.2 Uso de parámetros seguros .......................................................................... 33
7.1.3 Autenticación y autorización ......................................................................... 33
7.1.4 Protección de contraseñas y datos confidenciales ....................................... 33
7.1.5 Gestión adecuada de sesiones ...................................................................... 33

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 4 de 56

7.1.6 Actualización y parcheo regular .................................................................... 33


7.1.7 Auditoría y registro de eventos ..................................................................... 33
7.1.8 Pruebas de seguridad .................................................................................... 34
7.1.9 Educación y conciencia de seguridad ............................................................ 34
8 Optimización de rendimiento ................................................................................... 35
8.1 Almacenamiento en cache de forma activa .......................................................... 35
8.2 Evitar llamadas de bloqueo ................................................................................... 35
8.3 Devolución de colecciones grandes ...................................................................... 35
8.4 Minificar los recursos del cliente........................................................................... 35
9 Documentación de código......................................................................................... 37
10 Expresiones Lambda .................................................................................................. 39
11 Uso de LinQ (Language Integrated Query) ................................................................ 40
12 Programación orientada a objetos ............................................................................ 42
12.1 Mantenibilidad y extensibilidad ........................................................................ 42
12.2 Reutilización de código...................................................................................... 42
12.3 Flexibilidad y modularidad ................................................................................ 42
13 Evitar duplicidad de código ....................................................................................... 44
14 Uso de interfaces....................................................................................................... 46
15 Patron de diseño Singleton ...........................................¡Error! Marcador no definido.
16 Patrón de diseño Factory ..............................................¡Error! Marcador no definido.
17 Inyección de dependencias ....................................................................................... 47
18 Bloque Using.............................................................................................................. 49
Introducción ........................................................................................................................ 50
19 Utilizar nombres de recursos significativos ............................................................... 50
20 Metodos Http adecuados .......................................................................................... 50
21 Códigos de estados.................................................................................................... 52
22 Versionado del api ..................................................................................................... 53
23 Utilizar autenticación y autorización ......................................................................... 54
23.1 Utilización de token OAuth ............................................................................... 54
23.2 Utilización de JWT ............................................................................................. 55

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 5 de 56

24 Referencias ................................................................................................................ 56
24.1 Convenciones de código de C# comunes .......................................................... 56

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
HISTORIAL DE VERSIONES Y REVISIONES

Versión Fecha Acción Estado Descripción Responsable

Descripción de valores para el campo Acción

C – Creación del documento D – Distribución del documento M – Modificaciones del documento

R – Revisión del documento A – Aprobación del documento.


1 Introducción

1.1 Propósito

El propósito de este documento es compartir la información necesaria para afianzar las


buenas prácticas en el desarrollo de aplicaciones con lenguaje de programación .NET

1.2 Alcance

El presente documento tiene como objetivo establecer un conjunto de buenas prácticas de


desarrollo en el entorno de desarrollo .NET utilizando el lenguaje C#. Estas prácticas están diseñadas
para mejorar la calidad del código, aumentar la eficiencia del desarrollo y facilitar el mantenimiento
del software.

1.3 Acrónimos y términos

Para mayor detalle de las definiciones de los acrónimos y términos mencionados en este
documento consulte el glosario de términos el cual se encuentra almacenado en el Repositorio de
Documentación, proceso DP_DefinicionProceso.

1.3.1 Acrónimos
• No Aplica

1.3.2 Términos
• No aplica

1.4 Audiencia destino

Este documento va dirigido a colaboradores, practicantes, aprendices y externos que vayan a


desarrollar cualquier aplicación o proyecto basado en estas tecnologías.

1.5 Estructura del documento

En este documento estaremos tratando los siguientes temas:


• Convenciones de nomenclatura
• Estructura del proyecto
• Manejo de excepciones
• Seguridad
• Rendimiento
• Pruebas unitarias
• Documentación
• Mantenibilidad
Documento de buenas prácticas .Net Página 8 de 56

2 Introducción a las buenas prácticas del desarrollo en .Net C#


Durante el proceso de desarrollo de software, existen mil maneras de realizar una
misma funcionalidad. Sin embargo, con el único objetivo de estandarizar la forma de escribir
un buen código, reducir la cantidad de errores, problemas e inconvenientes, y ser claros y
concisos con las funcionalidades desarrolladas, se realiza este documento como manual de
buenas prácticas en el desarrollo de software.
En particular, este manual se enfoca en las buenas prácticas de desarrollo en .NET C#.
Se centra en proporcionar directrices para estructurar proyectos de manera coherente,
escribir código limpio y modular, aplicar principios de programación orientada a objetos,
realizar pruebas unitarias efectivas y gestionar el control de versiones de manera adecuada.
Independientemente de los frameworks específicos utilizados dentro de la plataforma .NET,
este manual ofrece pautas generales para desarrollar aplicaciones de alta calidad. Al seguir
estas buenas prácticas, podrás mejorar la calidad del código, facilitar su mantenimiento y
colaborar eficientemente con otros miembros del equipo.
En resumen, este manual de buenas prácticas de desarrollo en .NET C# tiene como
objetivo establecer estándares y proporcionar orientación para escribir un código de
calidad, reducir errores y problemas, y fomentar la claridad y la eficiencia en el proceso de
desarrollo de software.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 9 de 56

3 Convenciones de nomenclatura
3.1 Nombres descriptivos.
Los nombres de métodos clases y variables deben ser claros, fáciles de entender y
descriptivos en su estructura, con el fin de facilitar a cualquier lector del código el rápido
entendimiento de este.
Por ejemplo:
Nombre significativo para la variable fechaCaducidad

Se observa el nombre significativo fecha de caducidad, el cual sin dar mucho contexto
representa una fecha en la que caduca algún producto o proceso de tipo de dato DateTime.
Nombre significativo para una función, al igual que el ejemplo anterior, se puede
tener un nombre que represente claramente el resultado de una función, por ejemplo:
Nombre significativo para la función calcularPromedio

En el ejemplo se observa fácilmente que el nombre de la función realizará una


operación de promedio y retornará el cálculo de su valor.
Al igual que los anteriores casos, también podemos utilizar nombres significativos en
clases u objetos de nuestro código, en el siguiente ejemplo se muestra el nombre
significativo para una clase.
Ejemplo:
Nombre significativo para la clase Usuario:

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 10 de 56

Como se ha venido mencionando, en el anterior ejemplo se observa que la clase


representará los datos comunes de un usuario de cualquier aplicación, y observamos que
basta con leer el nombre de la clase para entender lo que nos quiere representar la misma.
Otro punto importante es la utilización de constantes, las cuales también deben estar
definidas bajo este principio, por ejemplo, se tiene el nombre significativo para una
constante de la velocidad de la luz la cual se representa de la siguiente manera:

Al igual que en los anteriores casos, el nombre nos representa de manera clara y
concisa lo que queremos almacenar en dicha variable.
Además, al igual que hemos declarado variables, contantes, funciones y clases,
también es necesario nombrar los parámetros de forma significativa, en el siguiente
ejemplo tenemos una función que retornara los años transcurridos dada una fecha inicial
hasta hoy, la cual maneja un principio de nombres representativos tanto en la función como
en sus parámetros.

3.2 Nomenclatura PascalCase Vs CamelCase


La nomenclatura PascalCase es una convención de nomenclatura utilizada en el
desarrollo de software como buen práctica, donde las palabras dentro de un nombre se
capitalizan y no se utilizan espacios ni guiones bajos. Esta convención facilita la legibilidad y
comprensión del código.
Por ejemplo:

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 11 de 56

En este ejemplo, se utiliza PascalCase para el nombre de la clase "Producto". Cada


palabra dentro del nombre se capitaliza, lo que facilita la identificación de la clase y su
distinción de otras.
Otro ejemplo sería, usar nombres de métodos

En este caso, se aplica PascalCase al nombre del método "CalcularTotalFactura".


Nuevamente, cada palabra dentro del nombre se capitaliza, lo que ayuda a comprender
rápidamente la funcionalidad del método.
Por otra parte, la nomenclatura CamelCase es una convención de nomenclatura
utilizada en el desarrollo de software en .NET C#, donde la primera letra de la primera
palabra se escribe en minúscula y las primeras letras de las palabras siguientes se
capitalizan. No se utilizan espacios ni guiones bajos. Esta convención también mejora la
legibilidad y comprensión del código.
Como ejemplo se tiene que los nombres de variables y parámetros deben llevar dicha
convención.

En este ejemplo, se utiliza CamelCase para los nombres de las variables "edadUsuario"
y "nombreCompleto". La primera letra es minúscula y las primeras letras de las palabras
siguientes se capitalizan. Esto ayuda a distinguir y entender rápidamente el propósito de las
variables.
También, es posible realizar nombramiento de propiedades con esta nomenclatura

En este caso, se aplica CamelCase a los nombres de las propiedades


"direccionEntrega" y "cantidadProductos". Al igual que en el ejemplo anterior, la primera
letra es minúscula y las primeras letras de las palabras siguientes se colocan en mayúscula.
Esto permite identificar y utilizar las propiedades de manera clara en el código.
En resumen: La nomenclatura PascalCase se utiliza para nombres de clases, métodos
y algunas propiedades. Mientras que la nomenclatura CamelCase se utiliza comúnmente
para nombres de variables, parámetros y otros elementos. Al seguir esta convención, se
mantiene la legibilidad y se facilita la comprensión del código. Además, se mantiene una
consistencia en la escritura de los nombres, lo que contribuye a la calidad y mantenimiento
del software.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 12 de 56

3.3 Evitar el uso de abreviaturas ambiguas


Debido a la legibilidad y comprensión del código es recomendable no utilizarlas al
momento de codificar ya que las abreviaturas pueden dificultar la comprensión del código,
especialmente para nuevos integrantes del equipo o para aquellos que no estén
familiarizados con las abreviaturas específicas utilizadas. Esto puede llevar a confusiones y
malinterpretaciones en la lectura del código.
Otro factor importante que nos lleva a evitar el uso de abreviaturas es la
mantenibilidad del código. A medida que el software evoluciona y se realizan
modificaciones o mejoras, el mantenimiento del código se vuelve más fácil y eficiente
siempre y cuando se utilicen nombres descriptivos y claros en lugar de abreviaturas. Las
abreviaturas pueden generar confusión sobre la funcionalidad o el propósito de un
elemento en el código, lo que dificulta su modificación o mantenimiento en el futuro.
Por ejemplo:

La abreviatura "mgr" puede ser confusa y no brinda información clara sobre la


naturaleza del atributo "mgrName". Otros desarrolladores pueden interpretarlo
incorrectamente, lo que dificulta la comprensión y el mantenimiento del código.
Otro ejemplo sería, el uso de abreviaturas ambiguas

La abreviatura "db" puede ser ambigua y no indica claramente que se trata de una
conexión a una base de datos. Esto puede llevar a confusiones y malentendidos al leer y
modificar el código.

3.4 Utilizar nombres de archivos descriptivos


La utilización de nombres descriptivos para carpetas y archivos dentro de los
proyectos ayuda a entender lo que el desarrollador quiere realizar al momento de crear un
proyecto. Esta recomendación proporciona información clara y concisa sobre el contenido
y el propósito de cada archivo.
Por ejemplo
• Nombres de archivos para clases:
Supongamos que tienes una clase que representa un modelo de usuario. Un buen
enfoque sería utilizar un nombre de archivo que describa la clase y su propósito:

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 13 de 56

Usuario.cs: Archivo que contiene la definición de la clase "Usuario".


De esta manera, otros desarrolladores pueden identificar rápidamente el contenido
del archivo y entender su función en el proyecto.
• Nombres de archivos para interfaces:
Si tienes una interfaz que define un contrato para la autenticación de usuarios, puedes
utilizar un nombre descriptivo para el archivo
IAutenticacion.cs: Archivo que contiene la definición de la interfaz "IAutenticacion".
Al utilizar un nombre de archivo descriptivo, es más fácil comprender qué
funcionalidad proporciona la interfaz y cómo se puede utilizar.
• Nombres de archivos para vistas:
En el caso de las vistas en ASP.NET MVC, es importante utilizar nombres de archivos
que reflejen el contenido y la funcionalidad de la vista. Por ejemplo:
Inicio.cshtml: Archivo que representa la vista de inicio de la aplicación.
Un nombre de archivo descriptivo ayuda a identificar rápidamente la vista
correspondiente a una determinada funcionalidad en el proyecto.
• Nombres de archivos para archivos de configuración:
Cuando se trata de archivos de configuración, es recomendable utilizar nombres
descriptivos que indiquen su propósito y contenido. Por ejemplo:
appsettings.json: Archivo de configuración de la aplicación.
Al utilizar un nombre de archivo descriptivo, se facilita la localización y comprensión
de los archivos de configuración en el proyecto.

4 Estructura del proyecto


Contar con una buena estructura al momento crear un proyecto es una practica que
muchas veces dejamos a un lado, este proceso se debe realizar desde el momento en que
levantamos la información del proyecto y diseñamos la solución. Para esta práctica es
recomendable organizar proyectos por capas con el fin de organizar y separar

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 14 de 56

responsabilidades, tener proyectos de pruebas unitarias y demás pruebas por separado y


contar con un excelente sistema de control de versiones.

4.1 Organizar el proyecto en capas


Organizar el proyecto en capas además de considerarse un abuena práctica, se
convierte hoy en día en una necesidad. Esta práctica, consiste en dividir el código en capas
lógicas y separadas, donde cada capa tiene una responsabilidad específica.
Comúnmente, los proyectos de desarrollo de software se dividen en las siguientes
capas:

4.1.1 Capa de Presentación (UI)


Esta capa es responsable de la interacción con el usuario y la presentación de la
interfaz de usuario. Puede incluir elementos como formularios, páginas web, controladores
de API, vistas, etc. Es importante que esta capa se mantenga lo más delgada posible,
delegando la lógica de negocio a las capas inferiores.

4.1.2 Capa de Lógica de Negocio (Business Logic)


En esta capa se encuentra la lógica de negocio de la aplicación. Aquí se definen las
reglas y los procesos que gobiernan la funcionalidad del software. Se encarga de procesar
la entrada de la capa de presentación y generar la salida correspondiente. Puede incluir
servicios, controladores, validaciones, reglas de negocio, etc.

4.1.3 Capa de Acceso a Datos (Data Access)


Esta capa es responsable de interactuar con la fuente de datos, como una base de
datos, un servicio web o cualquier otro almacenamiento persistente. Aquí se encuentran
los componentes de acceso a datos, como repositorios, entidades, contextos de base de
datos, consultas, etc.

4.1.4 Capa de Infraestructura


Esta capa proporciona servicios comunes y funcionalidades compartidas en todo el
proyecto. Puede incluir servicios de autenticación, registro, manejo de excepciones,
servicios de correo electrónico, etc. La capa de infraestructura permite separar la lógica
específica del dominio de las funcionalidades generales y facilita la reutilización de código.

Es importante tener en cuenta que esta es solo una sugerencia de cómo organizar el
proyecto en capas. La estructura exacta puede variar según las necesidades y complejidad
del proyecto. Además, es recomendable utilizar principios de diseño sólidos, como el
Principio de Responsabilidad Única (SRP) y la Inyección de Dependencias (DI), o modelos
como MVC, para mantener una separación adecuada entre las capas y facilitar la prueba y
la escalabilidad del software.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 15 de 56

4.2 Pruebas unitarias


Las pruebas unitarias son consideradas una buena práctica de desarrollo en .NET C#.
Se trata de pruebas automatizadas que verifican el comportamiento y la funcionalidad de
unidades individuales de código, como métodos o clases, de forma aislada.
Las pruebas unitarias son importantes por lo siguiente:

4.2.1 Aseguran la calidad del software


Las pruebas unitarias permiten detectar errores y problemas en el código
tempranamente. Al probar cada unidad de forma aislada, se pueden identificar y solucionar
problemas antes de que se propaguen a otras partes del sistema. Esto mejora la calidad del
software y reduce los errores en etapas posteriores del desarrollo.

4.2.2 Facilitan el mantenimiento del código


Las pruebas unitarias actúan como una especie de documentación para el código. Al
escribir pruebas claras y concisas, se comprende mejor cómo se espera que funcione una
unidad de código. Además, cuando se realizan cambios en el código, las pruebas unitarias
actúan como una salvaguarda para asegurar que las modificaciones no rompan el
comportamiento esperado.

4.2.3 Promueven un diseño modular y desacoplado


Al escribir pruebas unitarias, se requiere descomponer el código en unidades más
pequeñas y enfocadas. Esto fomenta un diseño modular y desacoplado, donde las
dependencias entre las unidades son claras y controladas. Como resultado, se obtiene un
código más mantenible y flexible.

4.2.4 Mejoran la colaboración y la productividad del equipo


Las pruebas unitarias facilitan la colaboración en equipos de desarrollo. Los miembros
del equipo pueden comprender rápidamente cómo utilizar una unidad de código y cómo
interactúa con otras unidades, lo que facilita la integración del trabajo y reduce los
conflictos. Además, las pruebas unitarias permiten detectar rápidamente cualquier
regresión en el código, lo que agiliza los procesos de revisión y resolución de problemas.

4.2.5 Impulsan la refactorización segura


Las pruebas unitarias brindan confianza al realizar refactorizaciones en el código. Al
modificar o mejorar una unidad de código, las pruebas unitarias aseguran que el
comportamiento previamente probado se mantenga intacto. Esto permite realizar cambios
sin temor a introducir errores inadvertidos.
En resumen, las pruebas unitarias son una práctica esencial en el desarrollo de
software en .NET C#. Proporcionan confianza en la calidad del código, mejoran su
mantenibilidad, promueven un diseño modular y desacoplado, facilitan la colaboración en
equipos y permiten realizar refactorizaciones seguras. Al invertir tiempo en escribir pruebas

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 16 de 56

unitarias efectivas, se obtiene un código más robusto y confiable, así como un proceso de
desarrollo más eficiente.
Por ejemplo:
Supongamos que tienes una clase llamada Calculadora que contiene métodos para
realizar operaciones aritméticas simples sumar y restar. Vamos a escribir pruebas unitarias
para verificar el comportamiento de estos métodos.

A continuación, escribiremos pruebas unitarias utilizando NUnit para validar el


comportamiento de los métodos Sumar() y Restar():

En este ejemplo, hemos creado una clase de pruebas CalculadoraTests y hemos


decorado la clase con el atributo [TestFixture] para indicar que contiene pruebas unitarias.
Luego, hemos escrito dos métodos de prueba, uno para probar el método Sumar() y otro
para probar el método Restar().

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 17 de 56

Dentro de cada método de prueba, seguimos el patrón AAA (Arrange, Act, Assert). En
la sección "Arrange", configuramos el escenario de prueba, creando una instancia de la clase
Calculadora. En la sección "Act", llamamos al método que queremos probar y almacenamos
el resultado. En la sección "Assert", verificamos si el resultado obtenido coincide con el
resultado esperado utilizando los métodos de aserción proporcionados por NUnit, en este
caso Assert.AreEqual().
Para ejecutar estas pruebas, necesitarías tener NUnit instalado y configurado en tu
entorno de desarrollo. Luego, puedes ejecutar las pruebas y verificar si pasan
correctamente.
Las pruebas unitarias en este ejemplo validan que los métodos Sumar() y Restar() de
la clase Calculadora funcionen según lo esperado. Si las pruebas pasan, podemos tener
confianza en que estos métodos se comportan correctamente. Si alguna prueba falla,
podemos investigar y corregir el problema antes de que se propague a otras partes del
código.

4.3 Control de versiones


Realizar un buen control de versiones es esencial para el desarrollo de software
colaborativo y para mantener un historial de cambios y control sobre el código fuente.
Es por esta razón que se recomienda tener en cuenta las siguientes recomendaciones.

4.3.1 Utilizar un sistema de control de versiones


Elige una herramienta de control de versiones como Git, SVN o Mercurial para
gestionar tu código fuente. Git es ampliamente utilizado y ofrece una gran cantidad de
funcionalidades y flexibilidad.

4.3.2 Estructurar el repositorio


Organiza tu repositorio de forma coherente. Utiliza una estructura de ramas que
refleje tu flujo de trabajo, como tener una rama principal (master/main) para la versión
estable del código y ramas de desarrollo (develop) para nuevas características y una rama
de QA para correcciones de errores. También considera tener ramas adicionales para tareas
específicas o versiones de preproducción.

4.3.3 Commits frecuentes y significativos


Realiza commits de forma frecuente y asegúrate de que cada commit sea significativo.
Divide los cambios en commits lógicos y atómicos, enfocados en una tarea o funcionalidad
específica. Proporciona mensajes de commit descriptivos y claros para facilitar la
comprensión de los cambios realizados.

4.3.4 Utilizar ramas para nuevas funcionalidades


Para trabajar en nuevas funcionalidades, crea una rama separada desde la rama de
desarrollo principal. Esto permite un desarrollo paralelo sin afectar la rama principal. Una

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 18 de 56

vez que la funcionalidad esté completa, realiza una solicitud de extracción (pull request)
para fusionar los cambios en la rama principal después de una revisión y prueba adecuadas.

4.3.5 Realizar pruebas y revisión de código


Antes de fusionar cambios en la rama principal, asegúrate de realizar pruebas
exhaustivas y revisar el código de manera colaborativa. Esto ayuda a identificar errores y
mejorar la calidad del código antes de que se integren los cambios.

4.3.6 Utilizar etiquetas para versiones


Utiliza etiquetas (tags) para marcar versiones importantes del software. Esto permite
un seguimiento fácil de las versiones publicadas y la capacidad de volver a versiones
específicas en caso de necesidad.

4.3.7 Documentar los cambios


Acompaña cada versión o etiqueta con notas de lanzamiento que describan los
cambios realizados. Esto ayuda a comunicar los cambios a otros miembros del equipo y a
los usuarios del software.

4.3.8 Mantener un repositorio limpio


Elimina ramas obsoletas y realiza tareas periódicas de mantenimiento en tu
repositorio para mantenerlo limpio y eficiente.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 19 de 56

5 Patrones de Diseño

Un patrón de diseño describe un problema recurrente en el diseño y proporciona una


solución general que se puede adaptar y aplicar a diferentes contextos. Los patrones de
diseño no son códigos o fragmentos de códigos concretos, sino más bien plantillas o guías
que pueden ser implementadas en diversos lenguajes de programación.
Los patrones de diseño se clasifican en diferentes categorías según su propósito y
comportamiento, como patrones de creación, patrones estructurales y patrones de
comportamiento. Algunos ejemplos populares incluyen el patrón Singleton, el patrón
Factory, el patrón Observer y el patrón Strategy.
Si habláramos de beneficios podríamos indicar los siguientes:
• Modularidad
• Reutilización de Código
• Mantenibilidad
• Escalabilidad
• Facilidad de comprensión del diseño
Es importante tener en cuenta que los patrones de diseño son soluciones probadas y
recomendadas para problemas comunes en el diseño de software. Son abstracciones de
experiencias y conocimientos acumulados en el desarrollo de software. Estos patrones
proporcionan un enfoque estructurado y reutilizable para resolver problemas específicos
durante el proceso de diseño de software.
A continuación daremos un vistazo a algunos patrones de diseño donde se incluirán
aspectos básicos de su funcionamiento y ejemplos de uso de los mismos:

5.1 Factory Method


El patrón de diseño Factory Method es un patrón creacional que proporciona una
forma de crear objetos sin especificar explícitamente su clase concreta. En lugar de ello,
define una interfaz común (o una clase base abstracta) que encapsula la lógica de creación
de objetos. Cada subclase concreta implementa ese método de fábrica para crear objetos
de un tipo específico.
Este patrón funciona de la siguiente forma:
• Define una interfaz o una clase base abstracta: Comienza por definir una
interfaz o una clase base abstracta que declare el método de fábrica. Este
método puede tener un nombre genérico como "Create" y devuelve un objeto
de una interfaz común o de una clase base abstracta.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 20 de 56

• Implementa subclases concretas: Crea subclases que hereden de la interfaz o


clase base abstracta y proporciona implementaciones concretas del método
de fábrica. Cada subclase es responsable de crear un tipo específico de objeto.
• Utiliza el Factory Method: En el código cliente, en lugar de crear objetos
directamente utilizando la palabra clave "new", utiliza el método de fábrica
para crear los objetos. El cliente solo necesita conocer la interfaz o la clase
base abstracta, sin preocuparse por los detalles de la implementación
concreta.
• Personaliza la creación de objetos: Cada subclase concreta puede personalizar
la creación de objetos según sus propias necesidades y lógica. Esto permite
una mayor flexibilidad y extensibilidad en el proceso de creación de objetos.

El patrón Factory Method permite encapsular la lógica de creación de objetos en las


subclases, lo que facilita la adición de nuevos tipos de objetos sin modificar el código
existente. Además, proporciona un código cliente desacoplado de las clases concretas, lo
que permite una mayor flexibilidad y mantenibilidad.

5.1.1 Ejemplos

• Creación de objetos en un juego


Imagina que estás desarrollando un juego y necesitas crear diferentes tipos de
enemigos. Puedes utilizar el Factory Method para tener una clase base abstracta llamada
Enemy y subclases concretas como Zombie, Alien y Robot que heredan de ella. El método
de fábrica en cada subclase concreta se encargaría de crear instancias de enemigos
específicos. Esto permite que el código cliente (por ejemplo, el controlador del juego) cree
enemigos sin conocer la implementación concreta, utilizando simplemente el método de
fábrica en la clase Enemy.

• Creación de objetos de persistencia de datos


En una aplicación que utiliza una capa de persistencia de datos, como un repositorio,
puedes aplicar el Factory Method para crear instancias de diferentes implementaciones de
repositorio, como SqlServerRepository, MySqlRepository y PostgreSQLRepository. Cada
subclase concreta tendría su propio método de fábrica que devuelve la instancia
correspondiente del repositorio. Esto permite que el código cliente solicite un repositorio
sin preocuparse por los detalles de la implementación de la base de datos subyacente.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 21 de 56

• Creación de generadores de informes


Supongamos que estás desarrollando una aplicación que genera informes en
diferentes formatos, como PDF, CSV y HTML. Puedes aplicar el Factory Method para tener
una interfaz o clase base abstracta llamada ReportGenerator, y luego implementar
subclases concretas como PdfReportGenerator, CsvReportGenerator y
HtmlReportGenerator. Cada subclase concreta tendría su propio método de fábrica para
crear instancias de generadores de informes específicos. De esta manera, el código cliente
puede solicitar un generador de informes sin conocer la implementación concreta,
utilizando simplemente el método de fábrica en la interfaz o clase base abstracta
ReportGenerator.

5.1.2 Casos de Uso

A continuación señalamos algunas situaciones en las que puede ser apropiado utilizar
el patrón Factory Method:

• Creación de objetos polimórficos: Cuando necesitas crear objetos de


diferentes subclases que implementan una misma interfaz o heredan de una
clase base común. El Factory Method permite que el código cliente trabaje con
la interfaz o clase base abstracta, y las subclases concretas se encargan de
crear objetos de su tipo específico.
• Desacoplamiento del código cliente: Cuando deseas evitar que el código
cliente dependa directamente de las clases concretas para crear objetos. En
su lugar, el código cliente interactúa con el método de fábrica para obtener
instancias de los objetos necesarios, lo que facilita la sustitución de
implementaciones concretas y la extensibilidad del sistema.
• Extensibilidad del código: Cuando anticipas la necesidad de agregar nuevos
tipos de objetos en el futuro. El Factory Method permite agregar nuevas
subclases que implementen la interfaz o hereden de la clase base abstracta sin
modificar el código existente. Esto facilita la incorporación de nuevas
funcionalidades o tipos de objetos sin afectar el código cliente.
• Encapsulación de la lógica de creación: Cuando la lógica de creación de objetos
es compleja y deseas encapsularla en una clase dedicada. El Factory Method
permite encapsular la lógica de creación en las subclases, lo que mejora la
legibilidad y mantenibilidad del código al separar las responsabilidades de
creación de objetos del resto del código.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 22 de 56

5.2 Builder

El patrón de diseño Builder es un patrón creacional que se utiliza para construir


objetos complejos paso a paso. Permite separar el proceso de construcción de un objeto de
su representación final, lo que permite la creación de diferentes variaciones del mismo
objeto utilizando un único proceso de construcción.
Así funciona el patrón Builder:
• Define una interfaz o una clase base abstracta: Comienza definiendo una
interfaz o una clase base abstracta que describe los pasos para construir el
objeto y los métodos para acceder al objeto resultante. Esto se conoce como
el Builder.
• Implementa el Builder: Crea una o varias clases concretas que implementen la
interfaz o hereden de la clase base abstracta. Cada clase Builder se encargará
de construir un tipo específico de objeto y seguirá los pasos definidos en la
interfaz o clase base abstracta.
• Crea una clase Director (opcional): El Director puede ser una clase separada
que utiliza un objeto Builder para construir el objeto final. El Director puede
seguir un orden específico de pasos o proporcionar una lógica adicional para
la construcción del objeto.
• Cliente utiliza el Builder: El código cliente utiliza el Builder para construir el
objeto paso a paso, invocando los métodos del Builder según sea necesario. El
cliente puede interactuar directamente con el Builder o a través del Director
si se utiliza.
• Obtiene el objeto final: Una vez que se han invocado todos los pasos
necesarios, el cliente solicita al Builder el objeto final construido. El Builder
devuelve el objeto completo y listo para ser utilizado.

El patrón Builder permite crear objetos complejos paso a paso, separando la lógica de
construcción de la representación final del objeto. Esto proporciona flexibilidad para crear
diferentes variaciones de un objeto utilizando un único proceso de construcción. Además,
el patrón Builder puede mejorar la legibilidad y mantenibilidad del código, especialmente
cuando se trabaja con objetos con muchas configuraciones y opciones.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 23 de 56

5.2.1 Ejemplos

• Construcción de objetos HTML:


Imagina que estás desarrollando una biblioteca para generar contenido HTML de
manera programática. Puedes utilizar el patrón Builder para construir objetos HTML
complejos, como elementos de formulario o tablas, paso a paso. Cada paso del Builder
podría corresponder a la configuración de atributos, etiquetas anidadas o contenido del
elemento HTML. Al finalizar, el Builder podría devolver el objeto HTML completo para su
posterior procesamiento o renderizado.

• Creación de objetos de configuración:


En muchas aplicaciones, es común tener objetos de configuración con múltiples
opciones y configuraciones. Puedes utilizar el patrón Builder para construir objetos de
configuración paso a paso, estableciendo las diferentes opciones y propiedades según sea
necesario. Esto proporciona un enfoque estructurado y claro para la creación de objetos de
configuración complejos, evitando el uso de constructores con muchos parámetros o
configuraciones confusas.

• Creación de objetos de pedidos personalizados:


Supongamos que estás construyendo un sistema de pedidos en línea donde los
usuarios pueden personalizar los artículos que desean comprar. Puedes utilizar el patrón
Builder para construir objetos de pedidos personalizados paso a paso. Cada paso del Builder
podría representar la selección de opciones y características específicas del pedido, como
el tipo de producto, el tamaño, el color, las opciones adicionales, etc. Al finalizar, el Builder
devolvería el objeto de pedido completo y personalizado para su procesamiento.

5.2.2 Casos de Uso

A continuación señalamos algunas situaciones en las que puede ser apropiado utilizar
el patrón Builder:
• Creación de objetos con múltiples configuraciones: Cuando necesitas crear
objetos que tienen muchas configuraciones opcionales o diferentes
variaciones. En lugar de tener un constructor con una lista larga de parámetros
o múltiples constructores sobrecargados, el patrón Builder te permite
construir el objeto paso a paso, configurando solo las opciones necesarias.
• Creación de objetos inmutables: Si deseas construir objetos inmutables, es
decir, objetos cuyos estados no se pueden modificar después de la creación,
el patrón Builder puede ser útil. Puedes utilizar el Builder para establecer los

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 24 de 56

valores necesarios durante la construcción y luego devolver un objeto


inmutable una vez que se completa la construcción.
• Simplificación de la creación de objetos complejos: Si el proceso de
construcción de un objeto implica la creación de subobjetos, configuración de
dependencias o interacciones complejas entre diferentes partes del objeto, el
patrón Builder puede ayudar a simplificar y encapsular esa lógica de
construcción compleja.
• Mejora de la legibilidad y mantenibilidad del código: Cuando el código de
creación de objetos se vuelve confuso o difícil de mantener debido a la
cantidad de parámetros o configuraciones involucradas, el patrón Builder
puede proporcionar una estructura clara y organizada para la construcción de
objetos, mejorando la legibilidad y mantenibilidad del código.

5.3 Facade

El patrón de diseño Facade (Fachada) es un patrón estructural que proporciona una


interfaz simplificada para interactuar con un subsistema más complejo o conjunto de clases.
Su objetivo principal es proporcionar una interfaz de nivel superior que oculte la
complejidad interna del sistema y facilite su uso.
Así funciona el patrón Facade:
• Identifica un subsistema complejo: El primer paso es identificar un subsistema
que tenga múltiples componentes o clases interrelacionadas. Este subsistema
puede ser complejo y requerir una interacción detallada para utilizarlo.
• Crea una clase Fachada: Luego, se crea una clase Fachada que actúa como una
interfaz simplificada para el subsistema. La Fachada encapsula la funcionalidad
y las interacciones del subsistema y proporciona métodos simples y cohesivos
que el cliente puede utilizar para realizar tareas comunes.
• Interacción con el subsistema: La clase Fachada se encarga de coordinar y
orquestar las interacciones con el subsistema subyacente. Puede comunicarse
con diferentes componentes del subsistema, llamar a sus métodos y
proporcionar una interfaz más coherente y fácil de usar para el cliente.
• Cliente utiliza la Fachada: El cliente interactúa con la Fachada en lugar de
interactuar directamente con el subsistema complejo. El cliente no necesita
conocer los detalles internos del subsistema, ya que la Fachada se encarga de
manejar esas complejidades. Simplemente llama a los métodos
proporcionados por la Fachada para realizar las tareas deseadas.

Al utilizar el patrón Facade, se logran varios beneficios. En primer lugar, la Fachada


proporciona una interfaz más sencilla y coherente para el cliente, lo que facilita su uso y
reduce la complejidad. Además, ayuda a aislar al cliente de los detalles internos del

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 25 de 56

subsistema, lo que permite cambios en el subsistema sin afectar al cliente. También


promueve una mejor estructura y organización del código, ya que la lógica compleja del
subsistema se encapsula dentro de la Fachada.

5.3.1 Ejemplos

• Biblioteca de funciones complejas:


Imagina que estás trabajando en una biblioteca de funciones complejas, donde hay
múltiples componentes y clases interrelacionadas. Puedes utilizar el patrón Facade para
crear una interfaz simplificada que exponga solo las funciones más utilizadas y necesarias
para los clientes. La Fachada actuaría como un punto de entrada único y ocultaría la
complejidad interna del subsistema, permitiendo a los clientes utilizar la biblioteca de
manera más sencilla.

• API para servicios externos:


Si estás desarrollando una aplicación que se integra con múltiples servicios externos,
como proveedores de pago, servicios de envío, redes sociales, etc., puedes utilizar el patrón
Facade para crear una API que simplifique la interacción con estos servicios. La Fachada se
encargaría de manejar las diferentes llamadas y configuraciones necesarias para cada
servicio, proporcionando una interfaz coherente y fácil de usar para el cliente.

• Sistema de arranque de una aplicación:


En una aplicación compleja, puede haber múltiples componentes y pasos de
inicialización que deben ejecutarse correctamente para que la aplicación funcione
correctamente. Puedes utilizar el patrón Facade para crear una Fachada de inicialización
que maneje todos los pasos necesarios en el orden adecuado. La Fachada se encargaría de
interactuar con los componentes internos y asegurarse de que la inicialización se realice de
manera correcta y coherente, ocultando esa complejidad al cliente.

5.3.2 Casos de Uso

A continuación señalamos algunos momentos en los que sería apropiado utilizar el


patrón Facade:

• Cuando se desea proporcionar una interfaz simplificada a un subsistema


complejo: Si tienes un subsistema compuesto por múltiples componentes o

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 26 de 56

clases interrelacionadas y quieres simplificar su uso, puedes utilizar el patrón


Facade. La Fachada proporciona una interfaz coherente y simplificada que
oculta la complejidad interna del subsistema, lo que facilita su utilización por
parte de los clientes.
• Cuando se desea reducir la dependencia del cliente respecto al subsistema: Si
el cliente necesita interactuar directamente con varios componentes del
subsistema y eso genera una dependencia compleja y acoplada, el patrón
Facade puede ayudar a reducir esa dependencia. La Fachada actúa como una
capa intermedia entre el cliente y el subsistema, encapsulando las
interacciones complejas y proporcionando una interfaz más sencilla y
unificada.
• Cuando se necesita simplificar la migración o actualización del subsistema: Si
el subsistema está en constante evolución y puede sufrir cambios en su
estructura interna, el patrón Facade puede ser útil. Al utilizar una Fachada, el
cliente interactúa únicamente con la interfaz proporcionada por la Fachada, lo
que aísla al cliente de los cambios internos del subsistema. Esto facilita la
migración o actualización del subsistema sin afectar al cliente.
• Cuando se busca mejorar la legibilidad y mantenibilidad del código: Si el código
relacionado con el subsistema se ha vuelto complejo y difícil de entender
debido a la cantidad de componentes y clases involucrados, el patrón Facade
puede ayudar a mejorar la legibilidad y mantenibilidad del código. Al
proporcionar una Fachada que encapsula la lógica y las interacciones del
subsistema, se obtiene un código más claro y estructurado.

5.4 Strategy

El patrón de diseño Strategy (Estrategia) es un patrón de comportamiento que


permite definir una familia de algoritmos intercambiables y encapsularlos de manera que
sean independientes de los clientes que los utilizan. El objetivo principal del patrón Strategy
es permitir que los algoritmos varíen de forma independiente de los objetos que los utilizan.
Así funciona el patrón Strategy:
• Identificación del comportamiento variable: En primer lugar, debes identificar
el comportamiento que varía en tu sistema y que deseas encapsular. Este
comportamiento podría ser un algoritmo, una forma de procesamiento o
cualquier otra operación que pueda tener diferentes variantes.
• Creación de una interfaz común: A continuación, debes crear una interfaz o
clase abstracta que defina un contrato común para todos los algoritmos o
variantes. Esta interfaz será implementada por las diferentes estrategias
concretas.
• Implementación de las estrategias concretas: Crea clases concretas que
implementen la interfaz común, representando diferentes estrategias o

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 27 de 56

variantes del comportamiento. Cada estrategia encapsula una


implementación específica del algoritmo o comportamiento variable.
• Uso del contexto: El cliente utiliza un objeto de contexto que tiene una
referencia a la estrategia actual. El contexto puede ser una clase separada o
un método en la clase cliente. El contexto es responsable de invocar el
algoritmo adecuado de la estrategia actual.
• Cambio dinámico de la estrategia: El cliente puede cambiar dinámicamente la
estrategia utilizada en el contexto en tiempo de ejecución. Esto permite
intercambiar fácilmente entre diferentes variantes del comportamiento sin
afectar al cliente.

Al utilizar el patrón Strategy, puedes lograr varios beneficios. En primer lugar,


obtienes una mayor flexibilidad y extensibilidad, ya que puedes agregar nuevas estrategias
sin modificar el código existente. Además, el patrón Strategy promueve un código más
limpio y mantenible, ya que cada estrategia se encapsula de forma independiente y se
puede probar y mantener por separado. También permite un mejor cumplimiento del
principio de Open/Closed (abierto/cerrado), ya que puedes introducir nuevas estrategias
sin modificar el código existente.

5.4.1 Ejemplos

• Ordenamiento de datos:
Imagina que estás desarrollando una aplicación que necesita ordenar una lista de
elementos, pero la forma de ordenar puede variar según las necesidades del usuario.
Puedes utilizar el patrón Strategy para implementar diferentes estrategias de
ordenamiento, como ordenamiento por burbuja, ordenamiento por inserción o
ordenamiento rápido. Cada estrategia implementaría el algoritmo de ordenamiento
correspondiente y se podría seleccionar dinámicamente la estrategia adecuada según la
preferencia del usuario.

• Procesamiento de archivos:
Supongamos que estás creando una herramienta de procesamiento de archivos que
puede realizar diferentes operaciones, como compresión, encriptación o conversión de
formatos. Utilizando el patrón Strategy, puedes implementar cada una de estas operaciones
como una estrategia separada. El usuario puede seleccionar la estrategia deseada y la
herramienta aplicará la operación correspondiente al archivo, sin preocuparse por los
detalles de implementación específicos.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 28 de 56

• Cálculo de impuestos:
En una aplicación financiera, es posible que debas realizar cálculos de impuestos
sobre diferentes tipos de transacciones, como ventas, compras o inversiones. Cada tipo de
transacción puede tener reglas de cálculo de impuestos específicas. Utilizando el patrón
Strategy, puedes implementar cada regla de cálculo de impuestos como una estrategia
separada. Al procesar una transacción, se selecciona la estrategia de cálculo de impuestos
correspondiente al tipo de transacción y se realiza el cálculo adecuado.

5.4.2 Casos de Uso

El patrón de diseño Strategy es apropiado utilizarlo en las siguientes situaciones:

• Cuando tienes múltiples variantes de un algoritmo o comportamiento: Si


tienes diferentes implementaciones de un algoritmo o comportamiento y
necesitas elegir entre ellos en tiempo de ejecución, el patrón Strategy es útil.
Te permite definir cada variante como una estrategia y seleccionar la
estrategia adecuada según tus necesidades.
• Cuando quieres evitar la proliferación de condicionales: Si tu código contiene
una serie de condicionales para manejar diferentes variantes de un
comportamiento, puedes usar el patrón Strategy para evitar una lógica
complicada y difícil de mantener. En su lugar, puedes encapsular cada variante
en una estrategia separada y utilizar el patrón Strategy para seleccionar y
ejecutar la estrategia correcta.
• Cuando deseas permitir cambios flexibles y extensibles en el comportamiento:
El patrón Strategy te permite cambiar o agregar nuevas estrategias sin
modificar el código existente. Esto significa que puedes adaptar fácilmente el
comportamiento de tu sistema en función de los requisitos cambiantes sin
afectar a otras partes del código.
• Cuando quieres separar el comportamiento del objeto cliente: Utilizando el
patrón Strategy, puedes separar el comportamiento específico de un objeto
cliente y colocarlo en estrategias independientes. Esto promueve una mejor
organización y estructura del código, y facilita las pruebas y el mantenimiento.

5.5 Mediator

El patrón de diseño Mediator (Mediador) es un patrón de comportamiento que


promueve la comunicación indirecta y el acoplamiento flexible entre componentes de un

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 29 de 56

sistema. Su objetivo es definir un objeto mediador que coordine las interacciones entre
varios objetos sin que estos se conozcan directamente.
Así funciona el patrón Mediator:
• Mediador: El patrón Mediator se basa en la existencia de un objeto mediador
central que controla y coordina las interacciones entre los componentes del
sistema. El mediador es responsable de conocer a todos los componentes y
sus respectivas interfaces de comunicación.
• Componentes: Los componentes son objetos que interactúan entre sí, pero en
lugar de comunicarse directamente, se comunican a través del mediador. Cada
componente tiene una referencia al mediador y utiliza métodos del mediador
para enviar y recibir mensajes.
• Comunicación indirecta: En lugar de los componentes comunicándose
directamente entre sí, envían mensajes al mediador, quien se encarga de
dirigir el mensaje al componente adecuado. Esto reduce el acoplamiento entre
componentes, ya que no necesitan conocerse entre sí, solo necesitan conocer
al mediador.
• Desacoplamiento: El patrón Mediator promueve un desacoplamiento entre
los componentes. Cada componente solo necesita conocer al mediador y no
necesita conocer los detalles internos de los demás componentes. Esto facilita
la extensibilidad y el mantenimiento del sistema, ya que los cambios en un
componente no afectan directamente a otros componentes.
• Centralización del control: El mediador asume la responsabilidad de coordinar
las interacciones entre los componentes. Puede manejar la lógica de negocios,
tomar decisiones basadas en la información recibida de los componentes y
dirigir las respuestas apropiadas a los destinatarios adecuados.

El patrón Mediator es útil cuando tienes un conjunto de objetos que necesitan


interactuar entre sí, pero deseas evitar el acoplamiento directo entre ellos. También es útil
cuando se requiere una comunicación estructurada y centralizada. Al utilizar un mediador,
puedes simplificar las interacciones y mejorar la escalabilidad y mantenibilidad del sistema.

5.5.1 Ejemplos

• Sistema de chat en tiempo real:


Imagina que estás desarrollando un sistema de chat en tiempo real donde varios
usuarios pueden comunicarse entre sí. Utilizando el patrón Mediator, puedes implementar
un objeto mediador central que se encargue de recibir y distribuir los mensajes entre los
diferentes usuarios. Cada usuario enviaría sus mensajes al mediador, y este se encargaría
de dirigirlos a los usuarios destinatarios correspondientes. Esto evita que los usuarios
tengan que conocerse entre sí y simplifica la comunicación en el sistema de chat.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 30 de 56

• Sistema de tráfico en una ciudad:


En un sistema de simulación de tráfico de una ciudad, hay diferentes componentes
que interactúan entre sí, como los vehículos, los semáforos, los peatones, etc. Utilizando el
patrón Mediator, puedes crear un mediador central que coordine y controle la interacción
entre estos componentes. El mediador puede ser responsable de decidir cuándo los
semáforos deben cambiar, cómo los vehículos deben interactuar en los cruces, cómo los
peatones deben cruzar la calle de manera segura, etc. Esto simplifica la lógica de interacción
y evita un acoplamiento directo entre los componentes del sistema de tráfico.

• Aplicación de subasta en línea:


En una aplicación de subasta en línea, tienes diferentes usuarios que participan como
compradores y vendedores. Utilizando el patrón Mediator, puedes implementar un
mediador central que coordine y controle las ofertas y las negociaciones entre los
participantes. El mediador puede recibir las ofertas de los compradores, notificar a los
vendedores sobre las ofertas recibidas, gestionar la aceptación o el rechazo de las ofertas,
y comunicar los resultados a los participantes. Esto permite una comunicación estructurada
y centralizada entre los compradores y vendedores, evitando un acoplamiento directo entre
ellos.

5.5.2 Casos de Uso

El patrón de diseño Mediator es apropiado utilizarlo en las siguientes situaciones:

• Cuando tienes un conjunto de objetos que necesitan comunicarse entre sí,


pero deseas evitar el acoplamiento directo entre ellos. El patrón Mediator
promueve la comunicación indirecta a través de un objeto mediador central,
lo que reduce la dependencia entre los objetos y facilita el mantenimiento y la
extensibilidad del sistema.
• Cuando los objetos se vuelven difíciles de mantener debido a las interacciones
complicadas entre ellos. Si la lógica de comunicación entre los objetos se
vuelve compleja y difícil de seguir, el patrón Mediator puede ayudar al
centralizar la comunicación y reducir la complejidad del código.
• Cuando necesitas agregar nuevas funcionalidades sin modificar los objetos
existentes. Si deseas introducir nuevas funcionalidades o cambiar la forma en
que los objetos interactúan entre sí, el patrón Mediator te permite agregar
nuevas estrategias o reglas de comunicación en el mediador sin afectar
directamente a los objetos existentes.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 31 de 56

• Cuando deseas promover la reutilización de componentes. El patrón Mediator


permite encapsular la comunicación entre los componentes en un objeto
mediador reutilizable. Esto significa que puedes utilizar el mismo mediador en
diferentes contextos y con diferentes conjuntos de objetos, lo que fomenta la
reutilización y modularidad del código.
• Cuando se requiere una comunicación estructurada y centralizada. El patrón
Mediator proporciona un punto central de control para las interacciones entre
los objetos. Esto permite una comunicación estructurada y controlada, lo que
puede ser útil en situaciones donde se requiere una coordinación cuidadosa
entre los componentes.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 32 de 56

6 Manejo de Excepciones
Una de las buenas prácticas en un desarrollo de software de excelente calidad, es el
manejo y control de las excepciones o comúnmente llamados control de errores. Según
Microsoft, “una aplicación diseñada correctamente controla los errores y excepciones para
evitar que está se bloquee”.
Es importante conocer y saber en qué bloques de código se deben utilizar estos
controles ya que no en todos los casos es provechoso realizar esta práctica, en pocas
palabras, no todo el código debe llevar un control de excepciones.
También es importante que las excepciones controlan errores que pueda suceder en
tiempo de ejecución mas no errores de sintaxis o mala argumentación de los métodos.
En el siguiente ejemplo se utilizará la buena práctica de control de errores y
excepciones utilizando Try – Cathc- Finally

Es importante tener en cuenta que cada una de las capas del desarrollo realizado debe
contar con su respectivo método de capturar las excepciones y realizar la respectiva
transmisión o registro de estos, es necesario que ninguna capa se quede con el error.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 33 de 56

7 Seguridad
Aplicar buenas prácticas de seguridad en el desarrollo de software en .NET es
fundamental para proteger la aplicación y los datos sensibles de posibles amenazas, es por
esta razón que al momento de desarrollar software es recomendable contar con los
siguientes ítems:

7.1.1 Validación de entrada de datos


Siempre valida y filtra cualquier entrada de datos recibida de usuarios, fuentes
externas o servicios web. Utiliza técnicas como la validación de tipo, longitud, formato y
contenido para prevenir ataques de inyección de código malicioso, como SQL Injection y
Cross-Site Scripting (XSS).

7.1.2 Uso de parámetros seguros


Al interactuar con bases de datos, utiliza parámetros y consultas parametrizadas en
lugar de concatenar cadenas para formar consultas SQL. Esto ayuda a prevenir ataques de
inyección SQL.

7.1.3 Autenticación y autorización


Implementa un sólido sistema de autenticación y autorización para controlar el
acceso a la aplicación y a los recursos protegidos. Utiliza métodos de autenticación seguros,
como el uso de hashes y salting para almacenar contraseñas.

7.1.4 Protección de contraseñas y datos confidenciales


Almacena las contraseñas de forma segura utilizando técnicas de hash y salt. Además,
cifra los datos confidenciales en reposo y en tránsito utilizando algoritmos de cifrado
fuertes.

7.1.5 Gestión adecuada de sesiones


Utiliza tokens de sesión seguros y establece tiempo de expiración razonables para
evitar ataques de sesión y garantizar la privacidad de los usuarios.

7.1.6 Actualización y parcheo regular


Mantén el software actualizado con las últimas versiones y parches de seguridad
proporcionados por Microsoft. Esto ayuda a proteger contra vulnerabilidades conocidas.

7.1.7 Auditoría y registro de eventos


Implementa un mecanismo de registro de eventos y actividades importantes en la
aplicación. Esto facilita la detección y respuesta a intentos de intrusión o actividades
sospechosas.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 34 de 56

7.1.8 Pruebas de seguridad


Realiza pruebas de seguridad periódicas, como pruebas de penetración y análisis de
vulnerabilidades, para identificar posibles debilidades en la aplicación y tomar medidas
correctivas.

7.1.9 Educación y conciencia de seguridad


Fomenta una cultura de seguridad entre los desarrolladores y el equipo de desarrollo.
Proporciona capacitación sobre buenas prácticas de seguridad, conciencia sobre las últimas
amenazas y promueve la adhesión a políticas y estándares de seguridad.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 35 de 56

8 Optimización de rendimiento
Una de las buenas prácticas y necesidades de cualquier desarrollo de software es la
optimización de rendimiento, un desarrollo de software que cuenta con esta buena práctica
se puede considerar como un desarrollo de alta calidad

8.1 Almacenamiento en cache de forma activa


El almacenamiento en cache usa memoria del servidor para almacenar datos en la
memoria cache con el fin de evitar llamados una y otra vez a una misma subrutina o proceso
existente en nuestro desarrollo de software.

8.2 Evitar llamadas de bloqueo


Uno de los problemas de rendimiento más comunes en las aplicaciones de ASP.NET
Core ocurre cuando se realizan llamadas bloqueantes a un proceso asincrónico. Esto puede
llevar a la escasez hilos o de subprocesos y a una degradación en los tiempos de respuesta
de estos.
Es importante evitar bloquear la ejecución asincrónica llamando a métodos como
Task.Wait o Task<TResult>.Result. También se deben evitar bloqueos en rutas de acceso
comunes del código.
Las aplicaciones de ASP.NET Core funcionan mejor cuando están diseñadas para
ejecutar código en paralelo. Además, no se debe llamar a Task.Run y esperar
inmediatamente, ya que ASP.NET Core ya ejecuta código de aplicación en los subprocesos
del grupo de subprocesos de manera eficiente. Llamar a Task.Run solo agregaría
programación adicional innecesaria. Incluso si el código bloquea un subproceso, Task.Run
no lo evita.

8.3 Devolución de colecciones grandes


Una página web o una aplicación, no debe cargar grandes cantidades de datos al
mismo tiempo, es importante analizar si la cantidad de datos a manipular es demasiado
grande, posiblemente podamos tener problemas de rendimiento de nuestra aplicación y
posibles bloqueos.
Por esta razón se recomienda agregar una paginación al momento de exponer la
información, con el fin de mitigar este riesgo, ya que con esta práctica se estaría limitando
el número de registros manipulados en un mismo instante.

8.4 Minificar los recursos del cliente


Al momento de publicar nuestras aplicaciones en servidores, a menudo se entregan
varios archivos de Javascript, Css o de imágenes, que pueden afectar el rendimiento de la
aplicación, es por esto por lo que se recomienda realizar agrupación de varios archivos en
uno e incluir las versiones minificadas de las herramientas o framework utilizados.
En definitiva, el rendimiento es un aspecto fundamental que afecta la calidad del
programa. Para mejorar el rendimiento de un software, es importante aplicar técnicas de

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 36 de 56

optimización de código. Estas técnicas incluyen la eliminación de bucles anidados y la


reducción de llamadas innecesarias a funciones, lo que ayuda a agilizar la ejecución del
programa. Además, es recomendable utilizar herramientas de Profiling que permiten
identificar cuellos de botella en el código, es decir, secciones que ralentizan el desempeño.
Al identificar estos puntos críticos, es posible realizar ajustes y mejoras para lograr un
rendimiento óptimo. Otro aspecto relevante es evitar la duplicación de código, ya que esta
práctica aumenta la complejidad y dificulta el mantenimiento del software. Para evitar
duplicaciones, se pueden utilizar técnicas como la extracción de métodos y la creación de
funciones genéricas, lo que promueve la reutilización y simplificación del código. En
resumen, al aplicar estas técnicas y utilizar herramientas adecuadas, se puede lograr un
programa eficiente y de alta calidad.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 37 de 56

9 Documentación de código
El proceso de documentación de código es muy importante ya que nos ayuda a
entender mas lo que el desarrollador quiso realizar en cada una de la funciones, clases o
métodos, es un complemento al nombramiento significativo que se mencionó en el anterior
capítulo.
Es necesario realizar este proceso de forma adecuada realizando comentarios dentro
las líneas de código de manera que esta información pueda resultar útil para quien lee o
analiza el código desarrollado, una buena documentación facilita el desarrollo colaborativo
o en equipo y el mantenimiento del desarrollo a corto o largo plazo.

En el anterior ejemplo se utilizan los comentarios para definir correctamente el objeto


empleado durante todo su ciclo de vida del objeto, desde la creación de la clase, donde se

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 38 de 56

describe claramente lo que se quiere realizar, pasando por la declaración de las variables
del objeto, su respetivo constructor y los métodos para obtener los datos.
Esta documentación se puede generar a través de herramientas de documentación
como Sandcastle o VisualStudio por medio de la opción de build documentation.
Generalmente estas documentaciones se generan utilizando plugins descargables desde el
nugget package de la aplicación.
Actualmente existen herramientas como SHFB Sandcastle Help File Builder, Doxygen
o DocFX, los cuales pueden ayudar al proceso de documentación tanto para proyectos de desarrollo
web como para proyectos de web api, para el caso de DocFX.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 39 de 56

10 Expresiones Lambda
Una expresión lambda se utiliza para crear una función anónima, normalmente se
utiliza para simplificar la escritura del código. Una expresión lambda puede tener cualquiera
de las siguientes dos formas.
(input-parameters) => expresión
Las expresiones lambda son especialmente útiles en combinación con LINQ.
Por ejemplo:
Expresión Lambda para ordenar una lista de números

En el ejemplo anterior se observa una variable de tipo lista llamada números que
contiene un grupo de números entre cero y nueve generados de manera aleatoria, y por
otra parte se desea crear una función que organice los números de menor a mayor, pero en
este caso dicha función no será creada como tal, sino que se utilizará una expresión lambda
para realizar dicha funcionalidad. Para esto, se utilizará el método Sort(), el cual recibe a la
expresión lambda(a,b) => a.compareTo.(b), esto hará que la expresión por si misma recorra
todo el objeto y compare uno por uno hasta obtener el orden solicitado.

En el anterior ejemplo se crea una funcionalidad que busca filtrar los nombres que
tiene una longitud menor o igual a 3 caracteres. la cual utiliza la sentencia de LinQ Where
para desarrollar esta labor y utiliza la expresión lambda para extraer los nombres de la lista
y compararlos con la condición <=3. Como resultado se tiene que solamente uno de los
nombres cumple dicha condición.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 40 de 56

11 Uso de LinQ (Language Integrated Query)


LINQ (Language Integrated Query) en .NET C# es una buena práctica de desarrollo de
software debido a su expresividad, legibilidad, productividad, eficiencia, tipado seguro,
detección temprana de errores y su capacidad de interoperabilidad con diversas fuentes de
datos. Utilizar LINQ puede mejorar la calidad del código, acelerar el desarrollo y facilitar el
mantenimiento de aplicaciones que involucran consultas y manipulación de datos.
Al utilizar LINQ, puedes realizar consultas y manipulaciones de datos de manera más
rápida y eficiente en comparación con enfoques tradicionales basados en bucles y
condiciones. Esto se debe a que LINQ proporciona una sintaxis expresiva y declarativa que
permite expresar tus necesidades de manera más clara y concisa.
Por ejemplo: Supongamos que tienes una lista de objetos de tipo "Persona" con las
propiedades "Nombre" y "Edad", y deseas obtener una lista con las personas que tienen
más de 30 años:

En este ejemplo, se utiliza LINQ para aplicar una consulta sobre la lista de personas
mediante el método Where(). Dentro de este método, se especifica una expresión lambda
que define el criterio de filtrado, en este caso, p => p.Edad > 30. Esto significa que se
seleccionarán las personas cuya edad sea mayor a 30.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 41 de 56

El resultado se almacena en la variable personasMayoresDe30, que es una colección


de tipo IEnumerable<Persona>. Luego, se itera sobre esta colección y se imprime el nombre
y la edad de cada persona que cumpla con el criterio establecido.
Otro ejemplo sería: Supongamos que tienes una lista de números y quieres obtener
la suma de los números pares

En este ejemplo, la lista de números está representada por el arreglo números.


Utilizando LINQ, se aplica el método Where() para filtrar los números pares, utilizando la
expresión lambda n => n % 2 == 0. Esto seleccionará solo los números que sean divisibles
por 2, es decir, los números pares.
Luego, se utiliza el método Sum() para calcular la suma de los números resultantes. El
resultado se almacena en la variable sumaPares.
Finalmente, se imprime en la consola el mensaje que muestra la suma de los números
pares.
Estos ejemplos ilustran cómo LINQ simplifica la escritura de consultas y operaciones
en colecciones de datos, permitiendo realizar tareas como filtrado y agregación de manera
más concisa y legible.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 42 de 56

12 Programación orientada a objetos


Es una buena práctica utilizar la programación orientada a objetos por las siguientes
3 razones.

12.1 Mantenibilidad y extensibilidad


La POO permite estructurar el código en clases y objetos, lo que facilita la
comprensión y el mantenimiento a medida que el proyecto crece. Los objetos encapsulan
datos y comportamientos relacionados, lo que hace más sencillo realizar cambios en el
código sin afectar otras partes del sistema. Al agregar nuevas funcionalidades, es posible
extender las clases existentes o crear nuevas clases que hereden de las existentes, lo que
promueve una evolución sostenible del software.

12.2 Reutilización de código


La reutilización de código es un aspecto fundamental de la POO. Mediante la creación
de clases base y la implementación de herencia, es posible compartir y reutilizar código en
diferentes partes de una aplicación. Esto ahorra tiempo y esfuerzo en el desarrollo, ya que
no es necesario volver a escribir o copiar y pegar el mismo código en múltiples lugares.

12.3 Flexibilidad y modularidad


La POO permite desarrollar software de manera modular, dividiendo el sistema en
componentes independientes. Esto facilita la implementación de cambios y actualizaciones
en un componente sin afectar a otros. La modularidad también promueve la colaboración
en equipos de desarrollo, ya que diferentes miembros del equipo pueden trabajar en
módulos específicos sin interferir con el trabajo de otros.
Por ejemplo:
Imaginemos que estás desarrollando un sistema de gestión de empleados, y quieres
representar a los empleados y sus características utilizando la POO. Para esto, puedes crear
una clase llamada Empleado que encapsule los datos y comportamientos relacionados con
un empleado:

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 43 de 56

En este ejemplo, la clase Empleado tiene propiedades como Nombre, Apellido,


FechaNacimiento y Salario para representar los datos de un empleado. Además, tiene
métodos como Trabajar() y CalcularSalario() para modelar las acciones que puede realizar
un empleado. Luego, se deben crear instancias de la clase Empleado para representar
empleados específicos y utilizar sus propiedades y métodos.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 44 de 56

13 Evitar duplicidad de código

La reutilización de código es una técnica en el desarrollo de software que consiste en


utilizar componentes o fragmentos de código existentes en diferentes partes de una
aplicación o en proyectos diferentes. Su objetivo es evitar la duplicación de código y
promover la eficiencia y la consistencia en el desarrollo.
La reutilización de código se puede lograr de diversas formas. Por ejemplo, se pueden
utilizar librerías y frameworks desarrollados por terceros para agregar funcionalidad
específica a una aplicación. Estas librerías ya están implementadas y probadas, lo que
permite aprovechar el código existente en lugar de escribirlo desde cero. Un ejemplo es el
uso del framework ASP.NET en el desarrollo de aplicaciones web en .NET.
Otra forma de reutilización de código es mediante la creación de clases y funciones
de utilidad. Estos componentes pueden realizar tareas comunes o repetitivas y se diseñan
de manera genérica para ser reutilizados en diferentes partes del código. Por ejemplo, se
puede crear una clase de utilidad con métodos para el formateo de fechas o cálculos
matemáticos comunes, y luego utilizarla en diferentes partes de la aplicación.
En la programación orientada a objetos, se puede lograr la reutilización de código a
través de la herencia y el polimorfismo. Una clase puede heredar propiedades y métodos
de otra clase base, lo que permite aprovechar la funcionalidad existente y extenderla según
sea necesario. Por ejemplo, se puede tener una clase base "Animal" con métodos comunes,
y luego crear clases derivadas como "Perro" y "Gato" que hereden de la clase base y
agreguen comportamientos específicos.
Además, es posible desarrollar componentes personalizados que encapsulen
funcionalidades específicas y se puedan utilizar en diferentes proyectos. Estos
componentes se diseñan para ser independientes y reutilizables, lo que ahorra tiempo y
esfuerzo al desarrollar nuevas aplicaciones.
La reutilización de código es una práctica importante en el desarrollo de software, ya
que mejora la productividad, la calidad del software y reduce el riesgo de errores. Al
aprovechar el código existente, se evita tener que desarrollar todo desde cero, lo que
ahorra tiempo y recursos. Además, fomenta la consistencia en el código, ya que se utiliza
una implementación probada y refinada en lugar de reinventar la rueda en cada proyecto.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 45 de 56

Por ejemplo:
Supongamos que necesitas realizar operaciones matemáticas comunes en diferentes
partes de tu aplicación. Puedes crear una clase de utilidad llamada "Calculadora" que
contenga métodos estáticos para realizar estas operaciones. De esta manera, podrás
reutilizar el código de la clase "Calculadora" en diferentes partes de tu código sin tener que
repetir la implementación de las operaciones matemáticas.

En este ejemplo, la clase "Calculadora" contiene dos métodos estáticos: "Sumar" y


"Restar". Estos métodos realizan operaciones matemáticas simples y devuelven el
resultado.
En el método "Main" del programa, se utiliza la clase "Calculadora" para realizar una
suma y una resta. No es necesario crear una instancia de la clase "Calculadora" porque los
métodos son estáticos. Simplemente se invocan los métodos a través del nombre de la clase
seguido del nombre del método, pasando los argumentos necesarios.
La clase "Calculadora" es reutilizable, ya que puedes utilizarla en diferentes partes de
tu aplicación siempre que necesites realizar operaciones de suma y resta. Esto evita la
duplicación de código y promueve la consistencia en el manejo de las operaciones
matemáticas en tu código.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 46 de 56

14 Uso de interfaces
el uso de interfaces en el desarrollo de software en .NET C# tiene múltiples beneficios,
como abstracción, separación de responsabilidades, interoperabilidad, facilidad de testing
y mantenibilidad del código. Estas ventajas contribuyen a un código más modular, flexible
y fácil de comprender, lo que en última instancia mejora la calidad y la eficiencia del
software desarrollado.
Supongamos que estás desarrollando un sistema de gestión de empleados y tienes
una clase Empleado que representa a un empleado en la empresa. Además, tienes
diferentes tipos de empleados, como Desarrollador y Gerente, que tienen funcionalidades
específicas.

En este ejemplo, se define la interfaz IEmpleado que declara el método Trabajar(). La


clase Empleado implementa esta interfaz y proporciona una implementación general del
método Trabajar(). Luego, las clases Desarrollador y Gerente heredan de Empleado y
pueden añadir funcionalidades específicas, como Codificar() para el desarrollador y Dirigir()
para el gerente.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 47 de 56

15 Inyección de dependencias

La inyección de dependencias es un patrón de diseño y una técnica utilizada en el


desarrollo de software para lograr una mejor modularidad y facilitar el mantenimiento de
código. Consiste en suministrar las dependencias de un objeto desde el exterior, en lugar
de que el objeto las cree internamente.
En lugar de que un objeto cree directamente sus dependencias, se definen interfaces
que representan las dependencias y se utilizan mecanismos externos para proporcionar las
implementaciones concretas de esas interfaces. Esto permite que el objeto se desacople de
las implementaciones específicas y dependa solo de las interfaces.
La inyección de dependencias se puede implementar de diferentes formas, siendo los
métodos más comunes la inyección de dependencias por constructor, por propiedades o
por métodos. A través de estas técnicas, las dependencias se pasan al objeto como
argumentos en el momento de su creación o se establecen mediante llamadas a
propiedades o métodos específicos.

Un ejemplo sencillo de inyección de dependencias sería el siguiente:

En este ejemplo, tenemos una interfaz IServicioCorreo que define el contrato para el
envío de correos electrónicos, y una clase ServicioCorreo que implementa esta interfaz.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 48 de 56

La clase Cliente depende del servicio de correo para enviar notificaciones, y recibe
una instancia de IServicioCorreo a través de su constructor. Al utilizar la inyección de
dependencias por constructor, el cliente no necesita crear directamente una instancia del
servicio de correo, sino que se le suministra desde el exterior.

En el método Main(), se crea una instancia concreta de ServicioCorreo y se pasa al


constructor de Cliente. Luego, se utiliza el cliente para enviar una notificación utilizando el
servicio de correo inyectado.
La inyección de dependencias facilita la creación de código más modular, flexible y
testeable. Permite intercambiar fácilmente las implementaciones de las dependencias sin
afectar al objeto que las utiliza. Además, promueve la separación de responsabilidades y
reduce el acoplamiento entre las clases.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 49 de 56

16 Bloque Using
El bloque using en C# se utiliza para garantizar la liberación adecuada de recursos no
administrados, como archivos, conexiones de bases de datos o cualquier objeto que
implemente la interfaz IDisposable. El bloque using asegura que los recursos se liberen
automáticamente al finalizar su uso, incluso si se produce una excepción.
El siguiente es un ejemplo de cómo se utiliza el bloque using para trabajar con un
archivo y garantizar su cierre y liberación de recursos:

En este ejemplo, se crea una clase MiClase que implementa la interfaz IDisposable.
Esta interfaz requiere la implementación del método Dispose(), que se encargará de liberar
los recursos cuando se utilice el bloque using.
Dentro de la clase MiClase, se tiene un método llamado Metodo() que simplemente
muestra un mensaje en la consola.
En el método Main(), se utiliza el bloque using para crear una instancia de MiClase.
Dentro del bloque using, se llama al método Metodo(). Al finalizar el bloque using, se
llamará automáticamente al método Dispose() de MiClase, lo que mostrará el mensaje
"Liberando recursos".

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 50 de 56

Buenas prácticas en servicios Api Rest


Introducción
Las API REST (Representational State Transfer) se han convertido en una forma común
y poderosa de intercambiar datos y funcionalidades entre aplicaciones. Sin embargo, para
asegurar que una API REST sea eficiente, escalable y fácil de usar, es importante seguir
buenas prácticas durante su diseño y desarrollo.
Las buenas prácticas en la creación de una API REST se centran en aspectos clave como
el diseño de recursos, el uso adecuado de métodos HTTP, la estructura de las URL, la gestión
de errores y la seguridad. Estas prácticas ayudan a mantener una API coherente, fácil de
entender y compatible con los estándares de la web.
Al seguir estas buenas prácticas, no solo se mejora la experiencia de los
desarrolladores que utilizan la API, sino que también se promueve la interoperabilidad, lo
que facilita la integración con otras aplicaciones y sistemas.
En esta guía, exploraremos diversas buenas prácticas en API REST, desde el diseño de
recursos y endpoints hasta la autenticación y autorización, pasando por la documentación
y el control de versiones. Al implementar estas prácticas, podrás crear APIs REST robustas,
flexibles y fáciles de mantener, que permitirán a los desarrolladores aprovechar al máximo
tus servicios y datos.

17 Utilizar nombres de recursos significativos

Al igual que en las buenas practicas de desarrollo de software mencionados


anteriormente, en las Apis rest se recomienda utilizar todos los patrones de buena escritura,
entendibles, descriptivos con uso de nomenclaturas tanto CamelCase como PascalCase
dicha escritura debe aplicarse de igual manera para funciones, variables, métodos clases y
verbos utilizados en el desarrollo de software.

18 Metodos Http adecuados

Los métodos HTTP desempeñan un papel fundamental en el diseño y desarrollo de


una API REST. Cada método tiene un propósito específico y debe utilizarse de manera
adecuada para garantizar una comunicación eficiente y coherente entre los clientes y el
servidor. Aquí hay un resumen de los métodos HTTP más comunes en una API REST:
GET: Se utiliza para obtener información o recursos existentes del servidor. Es seguro
e idempotente, lo que significa que no debe causar cambios en los datos.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 51 de 56

Obtener detalles de un usuario: GET /api/users/{id}


Obtener una lista de productos: GET /api/products

POST: Se utiliza para crear nuevos recursos en el servidor. Se envían los datos
necesarios en el cuerpo de la solicitud para que el servidor los procese y cree un nuevo
recurso.
Crear un nuevo usuario: POST /api/users
Agregar un nuevo producto al carrito de compras: POST /api/cart

PUT: Se utiliza para actualizar un recurso completo en el servidor. Se envía un


conjunto completo de datos en el cuerpo de la solicitud para reemplazar los datos
existentes del recurso.
Actualizar los detalles de un usuario: PUT /api/users/{id}
Actualizar los datos de un producto: PUT /api/products/{id}

PATCH: Se utiliza para realizar actualizaciones parciales en un recurso. Se envían solo


los campos que deben actualizarse en el cuerpo de la solicitud, y el servidor aplica los
cambios sin afectar los campos no proporcionados.
Actualizar el estado de un pedido: PATCH /api/orders/{id}
Modificar la descripción de un producto: PATCH /api/products/{id}

DELETE: Se utiliza para eliminar un recurso específico en el servidor. Al enviar una


solicitud DELETE, se elimina permanentemente el recurso correspondiente.
Eliminar un usuario: DELETE /api/users/{id}
Eliminar un producto: DELETE /api/products/{id}

Es importante utilizar los métodos HTTP de acuerdo con su función principal y seguir
las convenciones establecidas en el diseño de API REST. Esto garantiza una comunicación
clara y predecible entre los clientes y el servidor, además de facilitar la interoperabilidad y
el consumo adecuado de la API. Cada método tiene sus características y restricciones, y al
elegir el método correcto para cada operación, se logra una API REST bien estructurada y
fácil de usar.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 52 de 56

19 Códigos de estados
Al momento de crear una API REST, es importante utilizar correctamente los códigos
de estados, ya que estos se convierten en el idioma universal de las API’s. Los códigos de
estado HTTP proporcionan información sobre el resultado de una solicitud realizada a la API
y son una parte esencial de la comunicación entre el servidor y el cliente. Aquí tienes una
descripción de algunos códigos de estado HTTP comúnmente utilizados y su significado:
200 OK: Indica que la solicitud se ha realizado correctamente y que se devuelve una
respuesta exitosa. Este código se utiliza para respuestas exitosas en general.
201 Created: Se utiliza cuando se ha creado un nuevo recurso correctamente. Es
comúnmente devuelto después de una solicitud POST exitosa para indicar que el recurso se
ha creado satisfactoriamente.
204 No Content: Indica que la solicitud se ha completado con éxito, pero no se
devuelve ningún contenido en la respuesta. Este código se utiliza a menudo para respuestas
a solicitudes DELETE o PUT donde no se requiere enviar datos adicionales en la respuesta.
400 Bad Request: Indica que la solicitud del cliente es incorrecta o no se puede
procesar por parte del servidor debido a un formato inválido, datos faltantes o cualquier
otro error en la solicitud del cliente.
401 Unauthorized: Indica que la solicitud requiere autenticación del cliente. Este
código se utiliza cuando el cliente no ha proporcionado las credenciales necesarias o las
credenciales proporcionadas son inválidas.
403 Forbidden: Indica que el cliente no tiene permisos para acceder al recurso
solicitado. A diferencia del código 401, el cliente ya ha sido autenticado, pero no tiene los
permisos necesarios para acceder al recurso.
404 Not Found: Indica que el recurso solicitado no se encuentra en el servidor. Es
comúnmente devuelto cuando se accede a una URL que no existe o cuando se busca un
recurso que no está disponible.
500 Internal Server Error: Indica un error interno en el servidor que impide que se
maneje la solicitud correctamente. Este código se utiliza cuando ocurre un error inesperado
en el servidor.

Es importante utilizar códigos de estado HTTP adecuados para proporcionar una


retroalimentación clara y precisa al cliente sobre el resultado de su solicitud. Los códigos de
estado adecuados ayudan a los desarrolladores a comprender y manejar adecuadamente
las respuestas de la API y facilitan la depuración y resolución de problemas. Al utilizar los
códigos de estado de manera coherente y apropiada, se mejora la experiencia del usuario
y la interoperabilidad de la API REST.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 53 de 56

20 Versionado del api


El versionado de una API se recomienda como buena práctica porque permite
gestionar de manera controlada los cambios y mejoras en la API sin romper la
compatibilidad con los clientes existentes. Al establecer versiones claras y documentar los
cambios, se facilita la comunicación y se brinda a los desarrolladores las herramientas
necesarias para adaptarse y aprovechar las nuevas funcionalidades, garantizando así una
evolución coherente y una experiencia fluida para los usuarios de la API. Esta buena práctica
se recomienda especialmente en el contexto de las API REST, ya que permite gestionar de
manera eficiente la evolución y los cambios en la API sin afectar la compatibilidad con los
clientes existentes.
El objetivo principal del versionado de la API es proporcionar una forma de controlar
y comunicar los cambios en la estructura, la funcionalidad o el comportamiento de la API a
medida que evoluciona con el tiempo. Al implementar versiones en la API, se establece una
separación clara entre las diferentes versiones, lo que permite a los clientes elegir y
mantener la compatibilidad con la versión específica que están utilizando.
Existen diferentes enfoques para el versionado de API, pero dos de los más comunes
son incluir el número de versión en la URL o en el encabezado de la solicitud. La inclusión
de la versión en la URL se puede lograr mediante la adición de un segmento de ruta que
indique la versión, como "v1" o "v2".
Por ejemplo
https://api.example.com/v1/users
https://api.example.com/v2/products.
Alternativamente, se puede incluir la versión en el encabezado de la solicitud,
utilizando un encabezado personalizado, como "X-API-Version: 1".
Mantener versiones anteriores de la API es una práctica importante para garantizar la
compatibilidad con los clientes existentes. Esto implica mantener el código y la lógica de las
versiones anteriores y proporcionar soporte continuo durante un período de tiempo
determinado. Al mantener versiones anteriores, los clientes tienen la opción de migrar a
una nueva versión a su propio ritmo, sin interrupciones en su funcionalidad actual.
Es esencial documentar los cambios realizados en cada versión de la API. Esto ayuda
a los desarrolladores a comprender los cambios y a adaptar sus integraciones de manera
adecuada. La documentación debe incluir detalles sobre las modificaciones realizadas, los
nuevos endpoints o recursos disponibles, los cambios en la estructura de los datos, entre
otros aspectos relevantes.
Además, es recomendable proporcionar un plan de migración claro y guías para
ayudar a los desarrolladores a actualizar sus integraciones. Esto puede incluir
recomendaciones sobre cómo adaptarse a los cambios, resolver posibles problemas de
compatibilidad y aprovechar las nuevas características y mejoras de la nueva versión.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 54 de 56

21 Utilizar autenticación y autorización


Implementar mecanismos de autenticación y autorización en una API es una buena
práctica para protegerla de accesos no autorizados y garantizar la seguridad de los datos y
los recursos que expone. Estos mecanismos permiten verificar la identidad de los usuarios
y controlar los permisos y privilegios que tienen para acceder y manipular los datos.
Existen diferentes métodos y estándares para implementar la autenticación y
autorización en una API. Uno de los enfoques comunes es la autenticación basada en
tokens, donde se emite un token de acceso al cliente después de una autenticación exitosa.
Otro enfoque es la autenticación basada en credenciales, donde el cliente envía las
credenciales (como nombre de usuario y contraseña) en cada solicitud. Además, la
autorización basada en roles y permisos es importante para controlar los permisos de
acceso a recursos específicos.
La elección de los mecanismos de autenticación y autorización depende de los
requisitos de seguridad y las necesidades específicas de la aplicación y los usuarios. También
es fundamental seguir las mejores prácticas de seguridad, como el uso de conexiones
seguras mediante SSL/TLS, almacenamiento seguro de credenciales y la implementación de
políticas de contraseñas fuertes.

21.1 Utilización de token OAuth


OAuth (Open Authorization) es un estándar de autenticación y autorización utilizado
como buena práctica en el desarrollo de aplicaciones web y API. Proporciona un mecanismo
seguro para que los usuarios autoricen a una aplicación a acceder a sus recursos en un
servicio en su nombre, sin compartir directamente sus credenciales.
Un ejemplo sencillo de OAuth es cuando un usuario desea iniciar sesión en una
aplicación utilizando sus credenciales de una cuenta de Google. En lugar de compartir su
nombre de usuario y contraseña con la aplicación, se utiliza el flujo de OAuth.
El proceso comienza cuando el usuario hace clic en el botón "Iniciar sesión con
Google" en la aplicación. Esto redirige al usuario a la página de inicio de sesión de Google,
donde ingresa sus credenciales. Después de la autenticación exitosa, Google le pregunta al
usuario si desea permitir que la aplicación acceda a ciertos recursos, como su nombre y
dirección de correo electrónico. El usuario otorga su consentimiento.
Luego, Google genera un token de acceso y lo envía a la aplicación. Este token se
utiliza para autenticar y autorizar las solicitudes realizadas por la aplicación en nombre del
usuario. Con el token de acceso, la aplicación puede acceder a los recursos solicitados, como
obtener información del perfil del usuario desde Google.
Este ejemplo ilustra cómo OAuth permite a los usuarios autorizar aplicaciones de
terceros a acceder a sus datos sin compartir directamente sus credenciales. En lugar de
almacenar y gestionar las credenciales de inicio de sesión de los usuarios, la aplicación
confía en el proveedor de autenticación (en este caso, Google) para autenticar y autorizar
a los usuarios. Esto mejora la seguridad y la privacidad, ya que las credenciales del usuario
no se comparten ni se almacenan en la aplicación.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 55 de 56

21.2 Utilización de JWT


La autenticación basada en JWT (JSON Web Tokens) se considera una práctica
altamente recomendada en el desarrollo de API REST en .NET debido a sus numerosas
ventajas y beneficios. JWT es un estándar abierto que ofrece un enfoque seguro y confiable
para la autenticación y la transferencia de información entre partes confiables a través de
tokens JSON firmados digitalmente.
Una de las principales ventajas de utilizar la autenticación JWT en una API REST es la
seguridad que proporciona. Los tokens JWT están firmados digitalmente utilizando
algoritmos de cifrado, lo que garantiza que no hayan sido manipulados o alterados durante
la transmisión. Esto asegura que la integridad de los datos se mantenga intacta, lo que es
especialmente importante en entornos donde la seguridad es crucial.
Además, la autenticación JWT ofrece la ventaja de ser un enfoque "sin estado" o
stateless. Esto significa que el servidor no necesita mantener un estado de sesión para cada
usuario, lo que simplifica la implementación y mejora la escalabilidad de la API. Cada token
JWT contiene toda la información necesaria para la autenticación, lo que elimina la
necesidad de realizar consultas constantes a una base de datos o servidor de autenticación
en cada solicitud.
La integración de la autenticación JWT en una API REST desarrollada en .NET es
también altamente eficiente. JWT es ampliamente compatible con múltiples lenguajes de
programación y frameworks, lo que facilita su implementación en entornos .NET y en
diversas plataformas y sistemas.
Otra ventaja significativa es la flexibilidad que ofrece la autenticación JWT. Los tokens
JWT pueden contener información adicional, como roles de usuario, permisos o cualquier
otro dato relevante para la lógica de autorización y control de acceso. Esto permite
personalizar y adaptar la autenticación y la autorización según los requisitos específicos de
la aplicación.

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO
Documento de buenas prácticas .Net Página 56 de 56

22 Referencias
Con el fin de obtener otros puntos de vista se comparten enlaces hacia otros autores
como Microsoft la cual cuenta con una serie de buenas paracticas y estándares para el
proceso de desarrollo de software.

22.1 Convenciones de código de C# comunes

Las convenciones de codificación tienen los objetivos siguientes:


• Crean una apariencia coherente en el código, para que los lectores puedan
centrarse en el contenido, no en el diseño.
• Permiten a los lectores comprender el código más rápidamente al hacer
suposiciones basadas en la experiencia anterior.
• Facilitan la copia, el cambio y el mantenimiento del código.
• Muestran los procedimientos recomendados de C#.
(Microsoft, s.f.) Convenciones de código de C# | Microsoft Learn

22.2 Patrones de Diseño

(Refactoring Guru) Patrones de diseño / Design patterns (refactoring.guru)

Fecha de publicación: 06/03/2024 Las copias impresas no están controladas Uso INTERNO

También podría gustarte