Entornos de desarrollo

1º DAM/DAW - Curso 2026-2027

User Tools

Site Tools


apuntes:configuracion

This is an old revision of the document!


Configuración de un proyecto

Figure 1: Buenas prácticas en la configuración de proyectos

Convenciones de código / Guias de estilo

No existe ninguna guia de estilo oficial para desarrollar con lenguaje Javascript. Diferentes organizaciones o compañias elaboran las suyas propias para uso interno o bien para extender un buen estilo entre desarrolladores.

Os dejo aqui un par de guias de estilo a modo de ejemplo:

Contenido generado

Son todos aquellos ficheros o carpetas que generan las herramientas que empleamos para desarrollar

  • Por parte del Sistema Operativo:
    • Sistemas MacOs: .DS_Store
  • Por parte del IDE:
    • IDEs de Jetbrains: .idea
    • Visual Studio Code: .vscode
  • Por parte del framework:
    • Node.js/npm: node_modules y package-lock.json
  • Sistemas de Control de Versiones:
    • Git: .git contiene toda la información necesaria del repositorio en el equipo local

Representan todo lo que tendremos que añadir a nuestro fichero .gitignore para que no sea incluido en el repositorio del proyecto

Mantener estilos y convenciones entre diferentes IDEs: EditorConfig

https://editorconfig.org/

.editorconfig
[*.js]
indent_style = space
indent_size = 4

Reinicio automático (hot reload)

nodemon es una herramienta que permite que nuestra aplicación nodejs se reinicie automáticamente cada vez que detecta un cambio en el código. De esa manera podemos evitar tener que estar continuamente parando y arrancándola.

Primero tendremos que instalar nodemon de forma global (de forma que podamos ejecutarlo como un nuevo comando de nuestro equipo):

santi@localhost:$ npm install -g nodemon

A partir de entonces, si tenemos bien configurado el script start de nuestro proyecto en el fichero package.json, podremos lanzar el proyecto simplemente ejecutando nodemon y éste monitorizará nuestro código en busca de cambios para reiniciarlo automáticamente. Asi podemos centrarnos simplemente en escribir código y comprobar si éste funciona correctamente:

santi@localhost:$ nodemon
[nodemon] 3.1.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node src/app.js`
Iniciando el backend en el puerto 8080

Cómo gestionar el ciclo de vida de mi proyecto

Qué version del framework elegir

A la hora de definir la configuración del proyecto, podemos también indicar para qué versiones del framework, node en este caso, está preparado para funcionar:

. . .
  "name": "my-project",
    "version": "1.0.0",
  "engines": {
    "node": "20.x"
. . . 

El calendario de releases de cualquier framework puede consultarse en su página web. En el caso de Nodejs, está disponible en https://nodejs.org/en/about/previous-releases

Figure 2: Node Release Schedule (Fuente: https://nodejs.org/en/about/previous-releases)

Para saber qué cambios ha habido en una release/version concreta, tendremos que consultar lo que se conoce como Changelog. Por ejemplo, en https://nodejs.org/en/download/archive/v24.21.0 se pueden consultar el de Node v24 junto con otros detalles sobre esa release.

Uso de linters

eslint es una herramienta que funciona como linter. Un linter en una herramienta que realiza un análisis estático de código. Esto es, revisa el código en busca de errores de sintaxis o de estilo, potenciales errores por referencias a variables que no existen o variables que no se utilizan, . . .

Para utilizar eslint, tendremos que incluirlo como dependencia de desarrollo, devDependencies, en nuestro package.json, junto con una serie de plugins:

package.json
{
  "name": "cities-backend",
  "version": "0.1",
  "description": "A sample project to learn Node.js",
  "type": "module",
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "start": "node src/app.js"
  },
  "author": "Santiago Faci",
  "license": "GPL-2.0-only",
  "dependencies": {
    "express": "^4.21.1"
  },
  "devDependencies": {
    "eslint": "6.4.0",
    "eslint-config-standard": "14.1.1",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-node": "11.1.0",
    "eslint-plugin-promise": "4.3.1",
    "eslint-plugin-standard": "4.1.0"
  }
}

El siguiente paso será preparar un fichero de configuración para eslint. En él definiremos las reglas que queremos que nuestro código siga, cuando queremos un error o un warning y cualquier otro parámetro. El siguiente es un ejemplo sencillo de un fichero de configuración que revisará aspectos como habituales como:

- Que el indentado de código sea de 4 espacios - Que se emplee el punto y coma (semicolon) al final de cada sentencia - Que no haya puntos y coma adicionales - Nos avisará de las variables definidas que realmente no se usen - Nos permitirá usa sentencias como console.log para mostrar mensajes por pantalla (su uso no siempre está recomendado)

.eslintrc.js
module.exports = {
    "env": {
        "node": "true"
    },
    "extends": [
        "eslint:recommended"
    ],
    "parserOptions": {
        "ecmaVersion": 2020,
        "sourceType": "module"
    },
    "rules": {
        "indent": ["error", 4],
        "semi": ["error", "always"],
        "no-extra-semi": "error",
        "no-unused-vars": "warn",
        "no-console": "off"
    }
}

npm runt lint ejecutará eslint para llevar a cabo el análisis estático de nuestro código, mostrándonos todos los errores encontrados:

santi@zenbook:$ npm run lint
 
> cities-backend@0.1 lint
> eslint .
 
 
/home/santi/Projects/cities-backend-module-linter/src/app.js
  22:21  error  Missing semicolon                             semi
  26:1   error  Expected indentation of 4 spaces but found 0  indent
 
✖ 2 problems (2 errors, 0 warnings)
  2 errors and 0 warnings potentially fixable with the `--fix` option.

Si queremos que eslint corrija todos los errores que pueda, podemos ejecutar npm run lint:fix que, en nuestro package.json, lanza eslint con el flag –fix que arreglará todo los fallos posibles (en ocasiones hay problemas que tendremos que arreglar a mano)

santi@zenbook:$ npm run lint:fix
 
> cities-backend@0.1 lint
> eslint .

Es probable que no todo lo que forma parte del proyecto en un momento determinado deba ser analizado por eslint. Hay mucho contenido generado que querremos ignorar. Para eso podemos indicarlo en el fichero .eslintignore y la herramienta ignorará esos ficheros o carpetas:

.eslintignore
coverage/
public/
submodules/
toolforge/

Reutilización de código: exportar/importar funciones

Documentación

Siempre que trabajemos en el desarrollo de un proyecto de software tendremos que desarrollar algún tipo de documentación. Esta documentación dependerá del tipo de usuario al que vaya destinado dicho proyecto:

  • Manual de usuario: Tendrás que hacer un manual de usuario cuando tu proyecto esté destinado para ser utilizado por usuarios humanos
  • Documentación técnica: En ocasiones estarás desarrollando librerías que otros desarrolladores necesitarán usar
  • Especificación API: Si desarrollas un backend con el objetivo de desarrollar una API REST, existe una especificación concreta que deberás de seguir, Open API Specification, también conocida como OAS

Como los proyectos que estamos desarrollando son APIs, nos centraremos en la generación de documentación siguiendo la especificación Open API, concretamente para proyectos desarrollados con el framework Node.js

Enfoque API First

Enfoque Code First

Es la metodología tradicional. En este caso, primero se implementa la API en base a los requisitos funcionales y la documentación se generará más adelante (probablemente con alguna librería que permitirá que se integre de cierta manera con el código).

En este enfoque se prioriza la velocidad de implementación. Cabe destacar que, en los últimos años, ha ido ganando protagonismo el otro enfoque, API First, por todas las ventajas que presenta.

Organización de un proyecto

En nuestro caso nos enfocaremos en la organización de un proyecto para el desarrollo de una API REST utilizando el framework de desarrollo de Node.js

Figure 3: Arquitectura API Node.js (Fuente: https://www.coreycleary.me/project-structure-for-an-express-rest-api-when-there-is-no-standard-way)

En nuestro caso trabajaremos con las siguientes capas:

  • route: Se definen las rutas o endpoints disponibles para cada uno de los elementos del modelo de datos
  • controller: Se definen las funciones que reciben las peticiones de las rutas definidas en la capa route
  • service: Funciones que definen la lógica de aplicación

A continuación desarrollaremos una API completa (CRUD) utilizando una base de datos y con el código organizado correctamente siguiendo el modelo de capas que se ha planteado anteriormente.

Ficheros de configuración

config.local.yaml
db:
  host: localhost
  port: 3306
  user: user
  password: password
  database: cities

service:
  port: 8080
config/configuration.js
const yaml = require('js-yaml');
const fs = require('fs');
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
 
// Lee el fichero de configuración
let configFile = 'config.prod.yaml';
const argv = yargs(hideBin(process.argv)).argv;
if (argv.config != undefined) {
    configFile = argv.config;
}
const config = yaml.load(fs.readFileSync(configFile, 'utf-8'));
 
module.exports = {
    config
};

Dockerizar un entorno de pruebas

https://www.docker.com/

https://www.docker.com/products/docker-desktop/

db/init.sql
CREATE DATABASE cities;
 
GRANT ALL PRIVILEGES ON cities.* TO USER;
 
USE cities;
 
CREATE TABLE cities (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    population INT,
    altitude FLOAT,
    foundation_date DATE,
    age INT,
    area INT,
    density FLOAT,
    id_country INT
);
 
INSERT INTO cities (name, population, altitude, foundation_date, age, area, density) VALUES
    ('Zaragoza', 700000, 200, '1000-01-01', 1000, 734734, 2373),
    ('Madrid', 5000000, 500, '1200-01-01', 800, 344734, 23473);
docker-compose.dev.yaml
name: cities
services:
  db:
    image: mariadb:11.3.2
    container_name: cities-dev-db
    environment:
      MARIADB_USER: user
      MARIADB_PASSWORD: password
      MARIADB_DATABASE: cities
      MARIADB_PORT: 3306
      MARIADB_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - ./db:/docker-entrypoint-initdb.d

Automatización con Makefile

https://dev.to/debajit13/make-makefiles-a-modern-developers-guide-to-classic-automation-14hl

Makefile
start-dev-env:
	docker compose -f docker-compose.dev.yaml up -d
 
stop-dev-env:
	docker compose -f docker-compose.dev.yaml down
 
all-test: stop-dev-env start-dev-env
	sleep 4
	npm test
 
.PHONY: all-test start-dev-env stop-dev-env
santi@zenbook:$ make start-dev-env

Licencia del proyecto

Mock API

db.json
{
  "$schema": "./node_modules/json-server/schema.json",
  "movies": [
    { "id": "1", "title": "Spiderman", "views": 100 },
    { "id": "2", "title": "Superman", "views": 200 },
    { "id": "3", "title": "X-Men", "views": 550 },
    { "id": "4", "title": "Batman", "views": 230 }
  ],
  "comments": [
    { "id": "1", "text": "Que pelicula más buena", "movieId": "1" },
    { "id": "2", "text": "Que pelicula más mala", "movieId": "2" },
    { "id": "3", "text": "Que pelicula más normal", "movieId": "2" },
    { "id": "4", "text": "Que pelicula más alucinante", "movieId": "3" }
  ]
}
santi@zenbook:$ npm install json-server@0.17.4
santi@zenbook:$ npx json-server db.json

© 2024-2026 Santiago Faci

apuntes/configuracion.1790674352.txt.gz · Last modified: by Santiago Faci