1. Introducción
El Ingeniero de Software utiliza diferentes herramientas tecnológicas para transformar requisitos y diseños en sistemas funcionales, confiables y mantenibles. Estas herramientas permiten construir aplicaciones, almacenar y procesar información y controlar la calidad del código producido.
En esta lección estudiaremos tres grupos fundamentales:
- Lenguajes de programación
- Bases de datos
- Linters y herramientas de análisis estático
El dominio de estas herramientas no consiste únicamente en conocer su sintaxis o configuración. Un Ingeniero de Software debe ser capaz de seleccionar la tecnología adecuada según las características y restricciones de cada proyecto.
2. Lenguajes de programación
Un lenguaje de programación es un lenguaje formal que permite expresar instrucciones que posteriormente pueden ser ejecutadas por una computadora.
Mediante los lenguajes de programación es posible implementar algoritmos, reglas de negocio, interfaces de usuario, servicios web, procesamiento de datos y prácticamente cualquier comportamiento requerido por un sistema de software.
Por ejemplo:
Requisito:
"El sistema debe calcular el total de una venta."
↓
Algoritmo:
total = precio × cantidad
↓
Implementación:
Código escrito en un lenguaje de programación
Por lo tanto, el lenguaje de programación constituye una de las principales herramientas utilizadas para transformar el diseño de una solución en software ejecutable.
2.1 Lenguajes compilados e interpretados
Una clasificación tradicional distingue entre lenguajes compilados e interpretados.
Lenguajes compilados
El código fuente pasa por un proceso de compilación antes de su ejecución.
Ejemplos:
- C
- C++
- Rust
- Go
De manera simplificada:
Código fuente
↓
Compilador
↓
Código ejecutable
↓
Ejecución
La compilación permite detectar determinados errores antes de ejecutar el programa y puede producir aplicaciones con un alto nivel de rendimiento.
Lenguajes interpretados
En estos lenguajes existe un intérprete o entorno de ejecución encargado de procesar las instrucciones.
Ejemplos comunes incluyen:
- Python
- JavaScript
- PHP
El modelo puede representarse como:
Código fuente
↓
Intérprete / Runtime
↓
Ejecución
Sin embargo, la distinción moderna entre compilado e interpretado no siempre es absoluta. Muchos lenguajes utilizan modelos híbridos.
Java, por ejemplo, normalmente compila el código a bytecode, que posteriormente es ejecutado por la Java Virtual Machine (JVM).
Java
↓
Compilador
↓
Bytecode
↓
JVM
↓
Ejecución
C# utiliza un principio similar mediante la plataforma .NET.
2.2 Lenguajes de tipado estático y dinámico
Otra característica importante es la forma en que los lenguajes manejan los tipos de datos.
Tipado estático
Los tipos son conocidos y comprobados principalmente antes de la ejecución.
Ejemplo en Java:
int edad = 25;
String nombre = "Ana";
Otros ejemplos son:
- C#
- C++
- Java
- Go
- Rust
- TypeScript
Una ventaja importante es que determinados errores pueden detectarse durante el desarrollo o compilación.
Tipado dinámico
Los tipos están asociados a los valores y se determinan durante la ejecución.
Ejemplo en Python:
edad = 25
nombre = "Ana"
Ejemplos:
- Python
- JavaScript
- PHP
Esto puede proporcionar mayor flexibilidad, aunque también requiere controles adecuados para evitar errores que solamente aparecen durante la ejecución.
2.3 Lenguajes utilizados actualmente
No existe un lenguaje universalmente superior. Cada lenguaje posee características que lo hacen apropiado para determinados contextos.
| Lenguaje | Usos frecuentes |
|---|---|
| JavaScript | Aplicaciones web, frontend y backend |
| TypeScript | Aplicaciones web de mediana y gran escala |
| Java | Sistemas empresariales, backend y aplicaciones distribuidas |
| C# | Sistemas empresariales, servicios web y ecosistema .NET |
| Python | Backend, automatización, análisis de datos e inteligencia artificial |
| C/C++ | Sistemas operativos, software de alto rendimiento y sistemas embebidos |
| Go | Backend, servicios distribuidos y herramientas de infraestructura |
| Rust | Sistemas de alto rendimiento y software donde la seguridad de memoria es importante |
La selección debe considerar factores como:
- requisitos del sistema;
- rendimiento;
- mantenibilidad;
- ecosistema disponible;
- experiencia del equipo;
- compatibilidad con sistemas existentes;
- disponibilidad de bibliotecas;
- seguridad;
- costos de desarrollo y mantenimiento.
Un Ingeniero de Software no debería seleccionar una tecnología simplemente porque es popular o porque personalmente la domina.
3. Bases de datos
La mayoría de los sistemas necesitan almacenar información de manera permanente. Para ello se utilizan bases de datos y Sistemas Gestores de Bases de Datos (SGBD).
Una base de datos permite almacenar información estructurada para posteriormente:
- consultar;
- insertar;
- modificar;
- eliminar;
- relacionar;
- proteger;
- procesar.
Por ejemplo, un sistema comercial podría almacenar:
Clientes
Productos
Ventas
Facturas
Pagos
Usuarios
La aplicación interactúa con esta información mediante un gestor de base de datos.
Aplicación
↓
Gestor de Base de Datos
↓
Datos persistentes
Dos grandes categorías utilizadas en Ingeniería de Software son las bases de datos relacionales y NoSQL.
4. Bases de datos relacionales
Las bases de datos relacionales organizan principalmente la información mediante tablas relacionadas entre sí.
Ejemplo:
CLIENTE
-------------------
IdCliente
Nombre
Documento
│
│
▼
VENTA
-------------------
IdVenta
IdCliente
Fecha
Total
Las relaciones permiten representar las dependencias existentes entre las entidades del negocio.
Una de sus principales herramientas es SQL (Structured Query Language).
Por ejemplo:
SELECT Nombre, Documento
FROM Cliente
WHERE IdCliente = 10;
Entre los gestores relacionales más conocidos encontramos:
- Microsoft SQL Server
- PostgreSQL
- MySQL
- Oracle Database
- MariaDB
- SQLite
4.1 Características
Las bases de datos relacionales destacan por características como:
Integridad: permiten establecer restricciones para mantener datos válidos.
Relaciones: permiten establecer asociaciones entre diferentes entidades.
Transacciones: permiten ejecutar múltiples operaciones como una unidad lógica.
Consultas: SQL proporciona una forma declarativa de consultar y transformar información.
Consistencia: proporcionan mecanismos para mantener el estado válido de la información.
5. Bases de datos NoSQL
Las bases de datos NoSQL utilizan modelos diferentes al modelo relacional tradicional.
NoSQL no representa una única tecnología. Dentro de esta categoría existen diferentes modelos.
Entre ellos:
- documentos;
- clave-valor;
- columnas;
- grafos.
Una base orientada a documentos, por ejemplo, podría almacenar información similar a:
{
"cliente": "Carlos Pérez",
"documento": "123456",
"telefonos": [
"70000000",
"71111111"
]
}
Entre las tecnologías NoSQL conocidas encontramos:
- MongoDB
- Redis
- Cassandra
- Neo4j
- Amazon DynamoDB
Las bases NoSQL pueden resultar apropiadas cuando existen necesidades específicas relacionadas con escalabilidad, distribución, estructuras de datos flexibles o determinados patrones de acceso.
Esto no significa que NoSQL sea una evolución o reemplazo de SQL.
La decisión correcta depende del problema.
Necesidades del sistema
↓
Características de los datos
↓
Patrones de consulta
↓
Requisitos de consistencia
↓
Escalabilidad
↓
Selección de tecnología
6. SQL vs. NoSQL
Una simplificación frecuente consiste en pensar que SQL es apropiado para sistemas antiguos y NoSQL para sistemas modernos. Esta afirmación es incorrecta.
Ambos enfoques continúan siendo ampliamente utilizados.
| Característica | Relacional | NoSQL |
| Organización tradicional | Tablas | Depende del modelo |
| Relaciones | Muy importantes | Depende de la tecnología |
| Esquema | Generalmente definido | Puede ser flexible |
| Consultas | Principalmente SQL | Dependen del gestor |
| Transacciones | Tradicionalmente muy fuertes | Dependen del producto |
| Ejemplos | SQL Server, PostgreSQL | MongoDB, Redis |
Incluso una misma arquitectura puede utilizar múltiples tecnologías.
Por ejemplo:
SISTEMA
│
┌─────────┼─────────┐
↓ ↓ ↓
PostgreSQL MongoDB Redis
│ │ │
Negocio Documentos Caché
El Ingeniero de Software debe comprender las ventajas y limitaciones de cada alternativa antes de seleccionar una base de datos.
7. Linters
Durante el desarrollo de software, escribir código que funcione no es suficiente. También debe procurarse que el código sea:
- legible;
- consistente;
- mantenible;
- comprensible;
- menos propenso a errores.
Una herramienta importante para este propósito es el linter.
Un linter es una herramienta que analiza el código fuente para detectar posibles errores, inconsistencias, patrones problemáticos y violaciones de reglas previamente establecidas.
El proceso puede representarse como:
Código fuente
↓
Linter
↓
┌────┴───────────┐
↓ ↓
Errores Advertencias
potenciales de calidad
8. ¿Qué puede detectar un linter?
Dependiendo del lenguaje y de la configuración, un linter puede detectar problemas como:
Variables declaradas y no utilizadas
const nombre = "Carlos";
const edad = 25;
console.log(nombre);
El linter podría advertir que edad fue declarada pero nunca utilizada.
Código inalcanzable
function calcular() {
return 10;
console.log("Resultado");
}
La segunda instrucción nunca será ejecutada.
Comparaciones potencialmente problemáticas
if (edad == "18") {
// ...
}
Una configuración de ESLint podría exigir:
if (edad === "18") {
// ...
}
Reglas de estilo
Los linters también pueden controlar aspectos como:
- nombres de variables;
- longitud máxima de líneas;
- uso de determinadas construcciones;
- importaciones innecesarias;
- funciones demasiado complejas;
- convenciones definidas por el equipo.
9. Linters según el lenguaje
Existen diferentes herramientas dependiendo del ecosistema utilizado.
| Tecnología | Herramientas |
| JavaScript / TypeScript | ESLint |
| Python | Pylint, Ruff, Flake8 |
| C# | Roslyn Analyzers, StyleCop |
| Java | Checkstyle, PMD, SpotBugs |
| C/C++ | Clang-Tidy, Cppcheck |
| Go | golangci-lint |
| Rust | Clippy |
Estas herramientas pueden ejecutarse directamente desde el entorno de desarrollo o integrarse en procesos automatizados.
10. El linter como herramienta de calidad
Un linter no reemplaza las pruebas de software.
Por ejemplo, considere:
function sumar(a, b) {
return a - b;
}
El código puede estar perfectamente escrito desde el punto de vista sintáctico y cumplir todas las reglas del linter.
Sin embargo, existe un error lógico: una función denominada sumar está realizando una resta.
Por lo tanto:
Linter
↓
Calidad estática del código
Pruebas
↓
Comportamiento del software
Ambos mecanismos son complementarios.
El linter busca determinados problemas sin necesidad de ejecutar el programa, razón por la cual forma parte de las técnicas de análisis estático de código.
11. Integración del linter en el desarrollo
En proyectos profesionales, el análisis no debería depender únicamente de que cada programador recuerde ejecutar el linter.
Puede incorporarse dentro del flujo de desarrollo:
Desarrollador
↓
Escribe código
↓
Ejecuta Linter
↓
Corrige problemas
↓
Repositorio
↓
Análisis automático
De esta manera, las mismas reglas pueden aplicarse a todo el equipo.
Esto permite establecer un estándar mínimo de calidad y evitar que código que incumpla determinadas reglas llegue a etapas posteriores del desarrollo.
12. Relación entre las tres herramientas
Los lenguajes de programación, las bases de datos y los linters cumplen funciones diferentes pero complementarias.
Supongamos que se desarrolla un sistema de ventas:
SISTEMA DE VENTAS
│
┌────────────┼────────────┐
↓ ↓ ↓
Lenguaje Base de Linter
Java / C# / Datos
JavaScript │
│ │ │
↓ ↓ ↓
Lógica del Persistencia Calidad
sistema de datos del código
El lenguaje de programación permite implementar el comportamiento del sistema.
La base de datos permite almacenar y consultar la información utilizada por la aplicación.
El linter analiza el código para detectar posibles problemas y mantener estándares de calidad.
13. Criterio del Ingeniero de Software
El verdadero valor profesional no consiste en memorizar una gran cantidad de herramientas.
Un Ingeniero de Software debe desarrollar la capacidad de preguntarse:
¿Qué problema necesito resolver?
A partir de esa pregunta puede evaluar qué tecnología resulta más apropiada.
Por ejemplo:
PROBLEMA
↓
REQUISITOS
↓
RESTRICCIONES
↓
EVALUACIÓN DE ALTERNATIVAS
↓
SELECCIÓN DE HERRAMIENTAS
Esto significa que conocer Java, Python, SQL Server, MongoDB o ESLint es importante, pero también lo es comprender cuándo utilizarlos, cuándo no utilizarlos y qué consecuencias técnicas produce cada decisión.
Conclusión
Los lenguajes de programación, las bases de datos y los linters constituyen tres grupos importantes de herramientas dentro de la Ingeniería de Software.
Los lenguajes permiten construir el comportamiento del sistema; las bases de datos permiten administrar la información persistente; y los linters contribuyen a mantener la calidad y consistencia del código fuente.

¿Qué criterios se priorizan al decidir entre una base de datos relacional y una NoSQL cuando el proyecto prevé un crecimiento rápido pero con estructuras de datos que aún están evolucionando?
¿Qué es un Árbol de Sintaxis Abstracta (AST) y cómo lo usa un linter para analizar tu código?
¿Es necesario que un ingeniero de software conozca muchas herramientas o que sepa elegir la herramienta adecuada según las necesidades del proyecto?
Además de conocer la sintaxis o configuración, ¿qué capacidad debe tener un Ingeniero de Software respecto a estas herramientas?