# Documentación Interna Del Equipo De Desarrollo
El presente documento tiene como objetivo guiar al equipo de desarrolladores DALE, centralizando los diferentes acuerdo establecidos para la construcción de soluciones tecnológicas.
## Un poco de humor

> Hacer re-trabajo es la pasión de **DALE** — Anómico
## Entorno de Desarrollo Integrado (IDE)
Cada desarrollador puede utilizar el **IDE** que le sea más cómodo, pero como equipo sugerimos el uso de [Visual Studio Code](https://code.visualstudio.com/) por los siguientes motivos:
- Por su alta variedad de extensiones útiles para la construcción de soluciones tecnológica.
- Su excelente integración con nuestros stack tecnológico.
## Buenas practicas
Esa son una serie de buenas practicas que consideramos relevantes para la construcción de aplicativos.
### Utilización de un arquetipo base
Esto no es nada más que construir un base de un aplicativo, el cual se ocupara para generar nuevos proyectos y lo puedes encontrar en nuestro [repositorio](https://bitbucket.org/coopeuch/msarchetynode/src/master/).
### Acuerdos de definición de estructura de carpeta y archivos
Se sugiere que el código fuente del proyecto este dentro de la carpeta `scr`. Ademas que nombre de los archivos deben estar `camelCase`.
Existen varias definiciones de tipos de notación, aca te mostraremos algunos en base a este texto de prueba "Hola COMO estas".
- **camelCase:** `holaComoEstas`
- **constantCase (upperCase + snakeCase):** `HOLA_COMO_ESTAS`
- **dotCase:** `hola.como.estas`
- **kebab o paramCase:** `hola-como-estas`
- **lowerCase:** `hola como estas`
- **pascalCase:** `HolaComoEstas`
- **pathCase:** `hola/como/estas`
- **snakeCase:** `hola_como_estas`
- **titleCase:** `Hola Como Estas`
- **upperCase:** `HOLA COMO ESTAS`
> **NOTA:**
>
> Al final de documento puede encontrar una extension para VScode que te puede ayudar a cambiar texto a los diferentes tipos de notación.
#### Base de datos
- Las **tablas** se definen en `snakeCase` y en singular. Ejemplo: `estado_usuario`.
- Los **atributos** se definen `snakeCase`. Ejemplo: `primer_nombre`.
- Los **id** deber ser de tipo **uuid**, específicamente `UUIDV4`. Ejemplo: `41559151-e4b7-4c1d-929a-012a4af797c5`.
- Las **fechas** deber ser de tipo **timestamptz**.
- Las **cadenas de texto** deber ser de tipo **varchar**.
- Las **números** deber ser de tipo **int4**.
- Las **estados** deber ser de tipo **bool**.
- Tanto las **tablas** como los **atributos** se definen en español.
#### Codificación
- Las **clases** se definen en `pascalCase`. Ejemplo: `ServicioUsuario`.
- Los **métodos** se definen en `camelCase`. Ejemplo: `obtenerPrimerNombre`.
- Las **variables** se definen en `camelCase`. Ejemplo: `primerNombre`.
- Las **constantes** se definen en `upperCase` + `snakeCase`. Ejemplo: `NOMBRES_EN_ESPANOL`.
- Tanto las **clases**, **métodos** y **variables** y **constantes** se definen en español.
#### Endpoint
Los endpoint se deben construir de forma semántica o amigable.
- Si se esta trabajando en un modulo de alguna entidad, la URL debe contener una sub-carpeta que represente este modulo. Ejemplo: `/usuarios`.
- Si se esta trabajando en un recurso de la alguna entidad, la URL debe contener un verbo que represente la acción, Ejemplo: `/obtener`.
- Si es necesario enviar parámetros para algún método definido como `GET`, este debe ser cambiado a `POST` y enviar los parámetros y/o un contrato de comunicación (`JSON`) por medio del `BODY` del request. Ya que de momento no utilizamos **query params**.
- Los métodos utilizados son `OPTIONS`, `GET`, `POST`, `PUT`, y `DELETE`.
- Tanto las **sub-carpetas** como los **recursos** de las URL se definen en `kebab` y en español. Ejemplo: `/usuarios/obtener`.
> **NOTA:**
>
> La anatomía de una URL, por ejemplo: "https://blog.example.com/subtopic/blog-post?order=asc" consta de las siguientes partes:
>
> - **"https"**: Protocolo.
> - **"blog"**: Subdominio.
> - **"example"**: Dominio.
> - **"com"**: Dominio de Nivel Superior (TLD).
> - **"subtopic"**: Sub-carpeta.
> - **"blog-post"**: Recurso o slug.
> - **"?order=asc"**: Parámetros de consulta o query params.
> - **"subtopic/blog-post"**: Ruta o path.
### Código formateado
A la hora de codificar y respaldar tu código con alguna herramienta de control de versiones, mantener un estándar de formato en el código es primordial. Por lo que sugerimos utilizar la herramienta `Prettier`.
Con esto se obtiene un beneficios indirecto al momento de realizar `PULL REQUEST`, ya nos aseguramos ha mantener un estándar el formato del código fuente. Ejemplo: eliminar las linear innecesarias en un archivo.
Por lo que es importante verificar la correcta configuración de prettier en los proyectos.
#### Configuración del archivo `.prettierrc`
```json
{
"arrowParens": "always",
"printWidth": 80,
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false
}
```
> **NOTA:**
>
> [Aquí](https://prettier.io/docs/en/ignore.html) pueden encontrar información sobre uso del `prettier-ignore` en el código fuente.
#### Configuración del archivo `.prettierignore`
```txt
dist
node_modules
```
### DRY: Don't repeat yourself
No repitas código, modulariza tus desarrollos. Repetir partes de código a lo largo de un desarrollo solo sirve para dificultar el mantenimiento y aumentar la probabilidad de cometer errores.
Agrupa en funciones las operaciones que se repitan, y aíslalas del resto del código, el esfuerzo necesario para el mantenimiento del código fuente disminuirá.
Si estos trozos de código son requeridos por otros ficheros, no solo eliminados del flujo natural, si no que colócalo en un fichero aparte y accesible por todos los elementos del código.
### Comenta tu código
Para facilitar el entendimiento de las ideas que se codifican, te sugerimos por favor **comentar tu código**.
> **NOTA:**
>
> Al final de documento puede encontrar una extension para VScode que te puede ayudar a generar comentarios en clases y métodos.
### Divide y vencerás
Divide los desarrollos complejos en varios más sencillos. Enrocarse en buscar una solución que abarque todas las posibilidades o funcionalidades te va a hacer perder mucho el tiempo.
Divide el desarrollo en funcionalidades y programarlas atendiendo a su función principal y a la integración con el resto.
### Optimización
No todas las instrucciones y módulos necesitan la misma capacidad de procesamiento intenta utilizar siempre las más sencillas.
### Alternativa para no ocupar `SWITCH`
```typescript
// en vez de hacer esto
switch (valor) {
case "CASO1":
console.log();
break;
case "CASO2":
console.log();
break;
case "CASO3":
console.log();
break;
default:
console.log();
break;
}
// puedes tomar esta alternativa
const logicas = {
CASE1: async () => {
console.log();
},
CASE2: async () => {
console.log();
},
CASE3: async () => {
console.log();
},
default: async () => {
console.log();
},
};
await(logicas[valor] || logicas.default)();
```
### Utilizar literales de plantilla
```typescript
// en vez de hacer esto
const nombre = "Peter";
const mensaje = "Hola" + name + ",";
// mejor hacer algo asi
const nombre = "Peter";
const mensaje = `Hola ${name},`;
```
### Utilizar operaciones abreviadas
```typescript
// en vez poner todas estas validaciones
if (x !== "" && x !== null && x !== undefined) {
console.log();
}
// mejor realizar algo como esto
if (!!x) {
console.log();
}
```
### Evitar los callbacks
```typescript
// En vez de utilizar callbacks
obtenerUsuario((error, data) => {
console.log();
obtenerPerfil(usuario, (error, data) => {
console.log();
obtenerCuenta(perfil, (error, data) => {
console.log();
cargarCuenta(cuenta, (error, data) => {
console.log();
});
});
});
});
// Mejor implementa promesas
obtenerUsuario()
.then(obtenerPerfil)
.then(obtenerCuenta)
.then(cargarCuenta)
.catch((error) => {
console.error(error);
});
// O, mejor implementa Async/Await
const main = async () => {
try {
const usuario = await obtenerUsuario();
const perfil = await obtenerPerfil(usuario);
const cuenta = await obtenerCuenta(perfil);
return cargarCuenta(cuenta);
} catch (error) {
console.error(error);
}
};
```
### Codificación semántica
Aca no tenemos un cobro adicional por caracteres utilizados en nuestros proyecto, por lo que no es necesario definir variables y/o métodos con pocos caracteres, como por ejemplo:
```typescript
// asi no, por favor...
const a = new Array();
// mejor asi...
const listaDeUsuarios = new Array();
```
### Uso correcto de migraciones
Todo proyecto esta en constante cambio, y muchas veces estos cambios pueden no ser de código fuente sino de modelo de base de datos. Para este tipo de cambios, la mayoría del los frameworks provee de una administración de migraciones.
## Nuestro Stack tecnológico
### Infraestructura
Las base de datos son construidos en [PostgreSQL](https://www.postgresql.org/).
### Backend
Nuestros aplicativos **backend** son construidos con la ayudar del framework [NestJS](https://nestjs.com/). Para la abstracción de la base de datos se ocupa [TypeORM](https://typeorm.io/).
#### Comando para crear migraciones
Este comando debe ejecutado en la raíz del proyecto, donde `NAME` debe ser sustituido con algún nombre que represente la migración a crear.
```bash
# Ejemplo para crear migración NAME
npx typeorm migration:create ./src/_common/migrations/NAME.migration
```
> **IMPORTANTE**:
>
> - El nombre debe esta escribo en **kebab**. Ejemplo: `agregar-tabla-nueva`.
> - Posterior al nombre del archivo debe llevar la cadena de texto `.migration`.
#### Comando para crear módulo
```bash
# Ejemplo para crear el modulo admin
npx nest g module admin
```
#### Comando para crear controlador
```bash
# Ejemplo para crear controlador admin
npx nest g controller admin
```
#### Comando para crear servicio
```bash
# Ejemplo para crear servicio admin
npx nest g service admin
```
### Frontend-App
Nuestros aplicativos **frontend-app** son construidos con la ayudar del framework [ReactNative](https://reactnative.dev/).
### Frontend-Web
Nuestros aplicativos **frontend-web** son construidos con la ayudar la librería [React](https://reactjs.org/) y [Redux](https://redux.js.org/).
## Extensiones Visual Studio Code útiles
- [change-case](https://marketplace.visualstudio.com/items?itemName=wmaurer.change-case): cambia una cadena de texto en diferentes formatos.
- [code-spell-checker-spanish](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker-spanish): verificador de ortografía en español.
- [code-spell-checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker): verificador base de ortografía. Esto siempre es util para mitigar esos detalles de tipeo.
- [doxdocgen](https://marketplace.visualstudio.com/items?itemName=cschlosser.doxdocgen): Generador es estructura de documentación de código.
- [git-graph](https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph): Interfaz gráfica o GUI para visualizar los commit y sus ramas. (algo parecido a Sourcetree).
- [gitlens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens): Agente Git que proporciona una serie de características a nuestro IDE, como por ejemplo ver quien modifico una linea especifica en un archivo.
- [prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode): Agente de Prettier utilizado para formatear e indexar archivos.
- [tabnine-vscode](https://marketplace.visualstudio.com/items?itemName=TabNine.tabnine-vscode): IA Code, es netamente un copiloto al momento de construir.
- [todo-tree](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree): Modulo para visualizar rápidamente todos los `TODO:` y `FIXME:` en nuestro proyectos.
- [vscode-import-cost](https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost): Verificar del costo al importar una librería.
- [vscode-todo-highlight](https://marketplace.visualstudio.com/items?itemName=wayou.vscode-todo-highlight): Destaca con colores las cadena de texto `TODO:` y `FIXME:`.
## Extra
### Definir métodos y atributos privados en una clase
```typescript
class Usuario {
#nombre = "";
constructor(nombre: string = "") {
this.#nombre = nombre;
}
#formatearNombre(nombreSinFormato: string) {
return nombreSinFormato.toUpperCase();
}
registrarNombre(value: string) {
this.#nombre = this.#formatearNombre(value);
}
obtenerNombre() {
return this.#nombre;
}
}
let usuario = new Usuario();
console.log(usuario);
// Usuario {
// __proto__: {
// constructor: ƒ Usuario(),
// registrarNombre: ƒ registrarNombre(),
// obtenerNombre: ƒ obtenerNombre()
// }
// }
usuario.#formatearNombre("Thomas A. Anderson"); // Error: No se puede acceder a la propiedad "#formatearNombre" fuera de la clase "Usuario" porque tiene un identificador privado.
usuario.#nombre = "Thomas A. Anderson"; // Error: No se puede acceder a la propiedad "#nombre" fuera de la clase "Usuario" porque tiene un identificador privado.
```