miércoles, 2 de octubre de 2013

Namespaces en C# - Parte 1

Tabla de Contenido

0. Introducción
1. Namespaces
2. La Directiva using
3. Reglas Dentro de un Namespace

3.1 Alcance de Nombres de Tipo
3.2 Ocultamiento de Nombres de Tipo
3.3 Namespaces Repetidos
3.4 Directiva using Anidada
4. Conclusiones
5. Glosario
6. Referencias

0. Introducción

Cuando se trata de jerarquizar el código de un proyecto de software, los espacios de nombre (namespaces, preferiblemente) se pueden analogar con un dominio. En esta entrada les hablaré con más detalle acerca de este concepto, el uso (animadamiento, alcance (scope), etc.) de esta construcción para estructurar los artefactos integrales de la solución software.

1. Namespaces

El sentido de existencia de los namespaces es el de permitir organizar el código de un proyecto software de tal manera que los artefactos integrales puedan ser referenciados, encontrados, estructurados de forma intuitiva. Esto es análogo a la organización de los contenidos de un sitio bajo un dominio:
  • midominio.com
    • midominio.com/productos
      • midominio.com/productos/listado.html
    • midominio.com/servicios
    • midominio.com/contacto/
      • midominio.com/contacto/mapa.html
      • midominio.com/contacto/dirección.html
Entonces cabe decir que un namespace es simplemente el uso sintáctico que ha dado .NET Framework a esta técnica o medio de estructuración del código de un proyecto.

Por otro lado, los namespaces evitan los coflictos entre librerías ya existentes, pues uno podría hacer parte del nombre del namespace el nombre del dominio (al ser únicos no se genera conflicto entre los tipos referenciados en un proyecto, sin embargo, más adelante veremos cómo atacar el conflicto de nombre de namespaces).

Por ejemplo, .NET contiene el namespace System.Security.Cryptography [4] que es un conjunto de servicios de criptografía [2] para la codificación y decodificación de datos, entre otras operaciones como: hashing [3], generación de números aleatorios, etc. Entonces, para referirnos a uno de los artefactos integrales de este namespace utilizamos su nombre completamente calificado [5] (o q-name); así:

System.Security.Cryptography.RSA rsa = System.Security.Cryptography.RSA.Create();

[NotaSystem.Security.Cryptography.RSA [6] es la clase base de la implementación del algoritmo RSA.]

En [1] apuntan que:
Namespaces are independent of assemblies, which are units of deployment such as an .exe or .dll.
Ídem:
Namespaces also have no impact on member visibility -public, internal, private, and so on.
Adicionalmente, dentro del cuerpo de declaración de un namespace, el programador puede declarar uno o más de los siguientes tipos de artefactos:
  • Un namespace anidado
  • Una clase
  • Una interfaz
  • Una estructura (struct)
  • Una enumeración (enum)
  • Un delegado (delegate)

Palabra clave namespace

La palabra clave namespace permite al programador definir un namespace (evidentemente) para los tipos artibitrarios que requieran declararse en el cuerpo de artefactos. Así:

Archivo C# UsoNamespace.cs [enlace alternativo]:

En la línea 1 se define el namespace en donde van a residir las clases ahí declaradas Clase1Clase2Exterior.Intermedio.Interior. Obsérvese que los puntos en el namespace indican la jerarquía de los espacios de nombre, también se podría ver así:
  • Exterior
    • Intermedio
      • Interior
        • Clase1
        • Clase2
El anterior es un esquema mental de jeraraquía. Mientras en código C# tendríamos algo como:

Archivo C# UsoNamespace.cs [enlace alternativo]:
Ahora, para referirnos a uno de los artefactos, es decir las clases Clase1Clase2, lo hacemos especificando los nombres de namespace empezando por el más exterior y el más interior:

Exterior.Intermedio.Interior.Clase1

En [1] nos aclaran que:
Types not defined in any namespace are said to reside in the global namespace. The global namespace also includes top-level namespaces...
De acuerdo con [9]:
  • Los namespaces sirven para organizar grandes proyectos.
  • Los namespaces se delimitan por medio de la unidad sintáctica . (punto).
  • La directiva using obvia el uso del nombre completamente calificado de las clases declaradas en el namespaces.
  • El namespace global es el namespace de la jerarquía superior: global::System (éste siempre se refiere al namespace System .NET Framework).

2. La Directiva using

La directiva using [9] permite crear un atajo o acceso rápido a los tipos declarados en un namespace. Esto se logra referenciando el espacio de nombre a través de using. El beneficio radica en la omisión del uso del nombre completamente calificado del tipo. 

Veamos el siguiente ejemplo:

Archivo C# PruebaDirectivaUsing.cs [enlace alternativo]:
En la línea 1 la sentencia using Exterior.Intermedio.Interior; incluye todos los tipos declarados en el nombre de espacio Exterior.Intermedio.Interior. En consecuencia, esto es lo que nos permite declarar un objeto de la clase Clase1 en la línea 7: Clase1 objClase1;.

3. Reglas Dentro de un Namespace

3.1 Alcance de nombres de tipo

Los namespace tienen un alcance según el nivel de la jerarquía donde hayan sido declarados. Por un lado, los tipos declarados en un namespace de grado superior son importados de manera implícita en namespaces de grado inferior (al grado también nos podemos referir como el subnivel que ocupa en la jerarquía un tipo dado).

Dediquemos tiempo a detallar el siguiente ejemplo:

Archivo C# AlcanceTiposNamespace.cs [enlace alternativo]: 

Véase cómo en la línea 12 se hace uso (por medio de la herencia) la clase Clase1 declarada en el namespace inmediatamente del grado superior (Intermedio). Aquí queda demostrado que los tipos son importados implícitamente en un namespace del subnivel inmediato (en particular, Interior).

Otro caso que se puede dar con la referenciación a namespaces, es el que consiste en especifcar el nombre completamente calificado de un tipo de un namespace del mismo grado de la jerarquía. Este ejemplo muestra cómo se puede lograr:

Archivo C# ReferenciaTipoNamespace.cs [enlace alternativo]:

3.2 Ocultamiento de nombres de tipo

Aquí ocurre un efecto similar al que sucede con las variables de instancia y las de ámbito local a un método: si en el método hay una variable con el mismo nombre de identificador de una variable de instancia (campo), la primera gana debido a su "poder local". En el caso de los namespaces se ve así:

Archivo C# OcultamientoNombres.cs [enlace alternativo]:
Una nota importante en [1]:
All type names are converted to fully qualified names at compile time. Intermediate Language (IL) code contains no unqualified or partially qualified names.
En resumen, podemos decir que la complejidad del código IL está dada por la robustez y o el grado de elaboración complejo que requiere la escritura de código intermedio.

3.3 Namespaces repetidos

Los espacios de nombre (vuelvo con que preferiblemente se les llame namespaces) pueden repetirse en múltiples declaracion. Esto está permitido siempre y cuando los nombres de los tipos (clases, enumeraciones, delegados, estructuras, namespaces anidados, e interfaces) no entren en conflicto por el nombre del identificador.

En el presente ejemplo las dos declaraciones de los namespaces ocurre en el mismo archivo de código fuente C#:

Sin embargo, C# nos permite poner las declaraciones repetidas del namespace -Exterior.Intermedio.Interior- completo en dos archivo diferentes. Así:

Archivo C# NamespaceRepetido2.cs [enlace alternativo]:

Archivo C# NamespaceRepetido3.cs [enlace alternativo]:

3.4 Directiva using Anidada

La directiva using puede ser usada para importar los nombres de tipos de un namespace dentro de otro namespace. Pasemos al siguiente ejemplo:

4. Conclusiones

Hasta el momento hemos visto el uso de los namespaces para la organización. Éstas construcciones del lenguaje C# permiten hacer más legible el código y poder crear software más robusto y fácil de mantener gracias a la jerarquización de nombres de tipos que se crea con su aplicación.

5. Glosario

  • Criptografía
  • Dominio
  • Espacio de nombre
  • Namespace
  • q-name

6. Referencias

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: Cryptography - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/Cryptography
[3]: What is hashing? - A Word Definition From the Webopedia Computer Dictionary - http://www.webopedia.com/TERM/H/hashing.html
[4]: System.Security.Cryptography Namespace () - http://msdn.microsoft.com/en-us/library/system.security.cryptography.aspx
[5]: Fully qualified name - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/Fully_qualified_name
[6]: RSA Class (System.Security.Cryptography) - http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsa.aspx
[7]: RSA (algorithm) - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/RSA_(algorithm)
[8]: Namespaces (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/0d941h9d.aspx
[9]: using Directive (C# Reference) - http://msdn.microsoft.com/en-us/library/sf0df423.aspx


O

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.