Por qué «usar el espacio de nombres estándar» se considera una mala práctica

La declaración que usa el espacio de nombres std generalmente se considera una mala práctica. La alternativa a esta declaración es especificar el espacio de nombres al que pertenece el identificador usando el operador de alcance (::) cada vez que declaramos un tipo. 
Aunque la instrucción nos evita escribir std:: cada vez que deseamos acceder a una clase o tipo definido en el espacio de nombres estándar, importa la totalidad del espacio de nombres estándar al espacio de nombres actual del programa. Tomemos algunos ejemplos para entender por qué esto podría no ser tan bueno.
Digamos que deseamos usar el cout del espacio de nombres estándar. Entonces escribimos

Ejemplo 1: 

CPP

#include <iostream>
using namespace std;
 
cout << " Something to Display";

Ahora, en una etapa posterior de desarrollo, deseamos usar otra versión de cout que se implemente de forma personalizada en alguna biblioteca llamada «foo» (por ejemplo)
 

CPP

#include <foo.h>
#include <iostream>
using namespace std;
 
cout << " Something to display";

Observe que ahora hay una ambigüedad, ¿a qué biblioteca apunta cout? El compilador puede detectar esto y no compilar el programa. En el peor de los casos, el programa aún puede compilar pero llamar a la función incorrecta, ya que nunca especificamos a qué espacio de nombres pertenecía el identificador.
Los espacios de nombres se introdujeron en C++ para resolver conflictos de nombres de identificadores. Esto aseguró que dos objetos pueden tener el mismo nombre y, sin embargo, ser tratados de manera diferente si pertenecen a diferentes espacios de nombres. Observe cómo ha ocurrido exactamente lo contrario en este ejemplo. En lugar de resolver un conflicto de nombres, en realidad creamos un conflicto de nombres.

Cuando importamos un espacio de nombres, esencialmente estamos extrayendo todas las definiciones de tipo al alcance actual. El espacio de nombres estándar es enorme. Tiene cientos de identificadores predefinidos, por lo que es posible que un desarrollador pase por alto el hecho de que hay otra definición de su objeto deseado en la biblioteca estándar. Sin darse cuenta de esto, pueden proceder a especificar su propia implementación y esperar que se use en partes posteriores del programa. Por lo tanto, existirían dos definiciones para el mismo tipo en el espacio de nombres actual. Esto no está permitido en C++, e incluso si el programa compila, no hay forma de saber qué definición se está usando y dónde.

La solución al problema es especificar explícitamente a qué espacio de nombres pertenece nuestro identificador utilizando el operador de ámbito (::). Por lo tanto, una posible solución al ejemplo anterior puede ser
 

CPP

#include <foo>
#include <iostream>
 
// Use cout of std library
std::cout << "Something to display";
 
// Use cout of foo library
foo::cout < "Something to display";

Pero tener que escribir std:: cada vez que definimos un tipo es tedioso. También hace que nuestro código se vea más peludo con muchas definiciones de tipos y dificulta la lectura del código. Considere, por ejemplo, el código para obtener la hora actual en el programa
Ejemplo 2:
 

CPP

#include <chrono>
#include <iostream>
 
auto start = std::chrono::high_performance_clock::now()
 
// Do Something
 
auto stop
    = std::chrono::high_peformance_clock::now();
auto duration
    = std::duration_cast<std::chrono::milliseconds>(stop - start);

El código fuente que está plagado de definiciones de tipo complicadas y largas no es muy fácil de leer. Esto es algo que los desarrolladores buscan evitar, ya que la mantenibilidad del código es muy importante para ellos.
Hay algunas formas de resolver este dilema, es decir, especificar el espacio de nombres exacto sin ensuciar el código con palabras clave estándar.

Considere usar typedefs 
typedefs nos evita escribir definiciones de tipo largas. En nuestro ejemplo 1, podríamos resolver el problema usando dos typedefs uno para la biblioteca estándar y otro para foo

CPP

#include <foo>
#include <iostream>
 
typedef std::cout cout_std;
typedef foo::cout cout_foo;
 
cout_std << "Something to write";
cout_foo << "Something to write";

En lugar de importar espacios de nombres completos, importe un espacio de nombres truncado 
. En el ejemplo 2, podríamos haber importado solo el espacio de nombres crono en std. 

CPP

#include <chrono>
#include <iostream>
 
// Import only the chrono namespace under std
using std::chrono;
 
auto start = high_performance_clock::now();
 
// Do Something
auto stop = high_performance_clock::now();
auto duration duration_cast<milliseconds>(stop - start);

También podemos usar la declaración para importar un único identificador. Para importar solo std::cout podríamos usar 

using std::cout;

Si aún importa espacios de nombres completos, intente hacerlo dentro de funciones o de alcance limitado y no en el alcance global.
Use la instrucción «using namespace std» dentro de las definiciones de funciones o clases, definiciones de estructuras. Al hacerlo, las definiciones del espacio de nombres se importan a un ámbito local y, al menos, sabemos dónde se pueden originar los posibles errores si surgen.

CPP

#include <iostream>
 
// Avoid this
using namespace std;
 
void foo()
{
    // Inside function
    // Use the import statement inside limited scope
    using namespace std;
 
    // Proceed with function
}

Conclusión. 
Hemos discutido métodos alternativos para acceder a un identificador desde un espacio de nombres. En todos los casos, evite importar espacios de nombres completos en el código fuente.
Si bien las buenas prácticas de codificación pueden tardar algún tiempo en aprenderse y desarrollarse, por lo general dan sus frutos a largo plazo. Escribir código limpio, inequívoco y robusto sin errores debe ser la intención de cualquier desarrollador de programación.
 

Publicación traducida automáticamente

Artículo escrito por Sayan Mahapatra y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *