Aikido

Lo que aprendimos del código base de Strapi: 20 reglas de revisión del código para un desarrollo escalable

Introducción

Strapi es una de las plataformas CMS headless de código abierto más populares, pero también es una enorme base de código con cientos de colaboradores y miles de pull requests. Mantener la calidad de un proyecto tan grande no es fácil. Se necesitan reglas de revisión del código claras y coherentes para garantizar que todas las contribuciones sean fiables, legibles y seguras.

En este artículo, hemos reunido un conjunto de reglas de revisión de código basadas en el repositorio público de Strapi. Estas reglas provienen de trabajo real: problemas reales, discusiones y pull requests que ayudaron al proyecto a crecer mientras se mantenía la estabilidad del código base.

Por qué es difícil mantener la calidad del código en un gran proyecto de código abierto

Mantener la calidad en un gran proyecto de código abierto es un reto debido a la magnitud y diversidad de las contribuciones. Cientos o incluso miles de desarrolladores, desde voluntarios a ingenieros experimentados, envían pull requests, cada uno introduciendo nuevas características, correcciones de errores o refactorizaciones. Sin reglas claras, el código base puede volverse incoherente, frágil o difícil de navegar.

Algunos de los principales retos son:

  • Colaboradores diversos con distintos niveles de experiencia.
  • Patrones de codificación incoherentes entre módulos.
  • Bugs ocultos y lógica duplicada arrastrándose.
  • Riesgos de seguridad si no se aplican los procesos.
  • Revisiones que requieren mucho tiempo para los voluntarios que no están familiarizados con todo el código base.

Para afrontar estos retos, los proyectos de éxito se basan en procesos estructurados: normas compartidas, herramientas automatizadas y directrices claras. Estas prácticas garantizan el mantenimiento, la legibilidad y la seguridad incluso cuando el proyecto crece y atrae a más colaboradores.

Cómo el cumplimiento de estas normas mejora la capacidad de mantenimiento, la seguridad y la integración.

La adhesión a un conjunto claro de normas de revisión del código repercute directamente en la salud del proyecto:

  • Facilidad de mantenimiento: Las estructuras de carpetas, las convenciones de nomenclatura y los patrones de codificación coherentes facilitan la lectura, la navegación y la ampliación del código base.
  • Seguridad: La validación de entradas, el saneamiento, las comprobaciones de permisos y el acceso controlado a las bases de datos reducen las vulnerabilidades y evitan las fugas accidentales de datos.
  • Incorporación más rápida: Las normas compartidas, las utilidades documentadas y los ejemplos claros ayudan a los nuevos colaboradores a entender el proyecto rápidamente y a contribuir con confianza.

Aplicando estas reglas, los equipos pueden garantizar que la base de código siga siendo escalable, fiable y segura, incluso aunque aumente el número de colaboradores.

Entre el contexto y las normas

Antes de ver las reglas, es importante entender que mantener la calidad del código alta en un proyecto como Strapi no se trata sólo de seguir las mejores prácticas generales. Se trata de tener patrones y estándares claros que ayuden a cientos de colaboradores a estar en la misma página. Cada una de las 20 reglas siguientes se centra en retos reales que aparecen en el código base de Strapi.

Los ejemplos que se ofrecen para cada norma ilustran tanto los planteamientos no conformes como los conformes, lo que da una idea clara de cómo se aplican estos principios en la práctica.

Ahora, exploremos las reglas que hacen que el código base de Strapi sea escalable, consistente y de alta calidad, empezando por la estructura del proyecto y los estándares de configuración.

Normas: Estructura y coherencia del proyecto

1. Siga las convenciones de carpetas establecidas por Strapi

Evite dispersar archivos o inventar nuevas estructuras. Cíñete al diseño de proyecto establecido por Strapi para que la navegación sea predecible.

Ejemplo de no conformidad

1src/
2├──controllers/
3│└── userController.js
4├──servicios/
5│└── userLogic.js
6├──rutas/
7│└── userRoutes.js
8└──utils/
9 └── helper.js

Ejemplo de conformidad

1src/
2└──api/
3 └── usuario/
4 ├── controladores/
5 │ └── user.js
6 ├── servicios/
7 │ └── user.js
8 ├── rutas/
9 │ └── user.js
10 └── content-types/
11 └── user/schema.json

2. Mantener la coherencia de los archivos de configuración

Utilice la misma estructura, nomenclatura y convenciones de formato en todos los archivos de configuración para garantizar la coherencia y evitar errores.

Ejemplo de no conformidad

1// config/server.js
2module.exports = {
3    PORT: 1337,
4    host: '0.0.0.0',
5    APP_NAME: 'my-app'
6}
7
8// config/database.js
9export default {
10  connection: {
11    client: 'sqlite',
12    connection: { filename: '.tmp/data.db' }
13  }
14}
15
16// config/plugins.js
17module.exports = ({ env }) => ({
18   upload: { provider: "local" },
19   email: { provider: 'sendgrid' }
20});

Ejemplo de conformidad

1// config/server.js
2module.exports = ({ env }) => ({
3  host: env('HOST', '0.0.0.0'),
4  port: env.int('PORT', 1337),
5  app: { keys: env.array('APP_KEYS') },
6});
7
8// config/database.js
9module.exports = ({ env }) => ({
10  connection: {
11    client: 'sqlite',
12    connection: { filename: env('DATABASE_FILENAME', '.tmp/data.db') },
13    useNullAsDefault: true,
14  },
15});
16
17// config/plugins.js
18module.exports = ({ env }) => ({
19  upload: { provider: 'local' },
20  email: { provider: 'sendgrid' },
21});

3. Mantener una estricta seguridad de tipo

Todo el código nuevo o actualizado debe incluir tipos TypeScript precisos o definiciones JSDoc. Evite el uso de cualquier tipo de retorno o la inferencia implícita de tipos en módulos compartidos.

Ejemplo de no conformidad

1// src/api/user/services/user.ts
2export const createUser = (data) => {
3  return strapi.db.query('api::user.user').create({ data });
4};

Ejemplo de conformidad

1// src/api/user/services/user.ts
2import { User } from './types';
3
4export const createUser = async (data: User): Promise<User> => {
5  return await strapi.db.query('api::user.user').create({ data });
6};

4. Nombres coherentes para servicios y controladores

Los nombres de controladores y servicios deben coincidir claramente con su dominio (por ejemplo, usuario.controlador.js con usuario.servicio.js).

Ejemplo de no conformidad

1src/
2└── api/
3    └── usuario/
4        ├── controladores/
5        │ └── mainController.js
6        ├── servicios/
7        │ └── accountService.js
8        ├── rutas/
9        │ └── usuario.js

Ejemplo de conformidad

1src/
2└── api/
3    └── usuario/
4        ├── controladores/
5        │ └── usuario.js
6        ├── servicios/
7        │ └── usuario.js
8        ├── rutas/
9        │ └── usuario.js
10        └── contenido-tipos/
11            └── usuario/esquema.json

Normas: Calidad y mantenimiento del código

5. Simplificar el flujo de control con devoluciones anticipadas

En lugar de un profundo anidamiento if/else, devuelva pronto cuando las condiciones fallen.

Ejemplo de no conformidad

1// src/api/article/controllers/article.js
2module.exports = {
3  async create(ctx) {
4    const { title, content, author } = ctx.request.body;
5
6    if (title) {
7      if (content) {
8        if (author) {
9          const article = await strapi.db.query('api::article.article').create({
10            data: { title, content, author },
11          });
12          ctx.body = article;
13        } else {
14          ctx.throw(400, 'Missing author');
15        }
16      } else {
17        ctx.throw(400, 'Missing content');
18      }
19    } else {
20      ctx.throw(400, 'Missing title');
21    }
22  },
23};

Ejemplo de conformidad

1// src/api/article/controllers/article.js
2module.exports = {
3  async create(ctx) {
4    const { title, content, author } = ctx.request.body;
5
6    if (!title) ctx.throw(400, 'Missing title');
7    if (!content) ctx.throw(400, 'Missing content');
8    if (!author) ctx.throw(400, 'Missing author');
9
10    const article = await strapi.db.query('api::article.article').create({
11      data: { title, content, author },
12    });
13
14    ctx.body = article;
15  },
16};

6. Evitar el anidamiento excesivo en los controladores

Evite grandes bloques de lógica anidada dentro de controladores o servicios. Extraiga las condiciones repetidas o complejas en funciones de ayuda o utilidades bien denominadas.

Ejemplo de no conformidad

1// src/api/order/controllers/order.js
2module.exports = {
3  async create(ctx) {
4    const { items, user } = ctx.request.body;
5
6    if (user && user.role === 'customer') {
7      if (items && items.length > 0) {
8        const stock = await strapi.service('api::inventory.inventory').checkStock(items);
9        if (stock.every((i) => i.available)) {
10          const order = await strapi.db.query('api::order.order').create({ data: { items, user } });
11          ctx.body = order;
12        } else {
13          ctx.throw(400, 'Some items are out of stock');
14        }
15      } else {
16        ctx.throw(400, 'No items in order');
17      }
18    } else {
19      ctx.throw(403, 'Unauthorized user');
20    }
21  },
22};

Ejemplo de conformidad

1// src/api/order/utils/validation.js
2const isCustomer = (user) => user?.role === 'customer';
3const hasItems = (items) => Array.isArray(items) && items.length > 0;
4
5// src/api/order/controllers/order.js
6module.exports = {
7  async create(ctx) {
8    const { items, user } = ctx.request.body;
9
10    if (!isCustomer(user)) ctx.throw(403, 'Unauthorized user');
11    if (!hasItems(items)) ctx.throw(400, 'No items in order');
12
13    const stock = await strapi.service('api::inventory.inventory').checkStock(items);
14    const allAvailable = stock.every((i) => i.available);
15    if (!allAvailable) ctx.throw(400, 'Some items are out of stock');
16
17    const order = await strapi.db.query('api::order.order').create({ data: { items, user } });
18    ctx.body = order;
19  },
20};

7. Mantener la lógica de negocio fuera de los controladores

Los controladores deben permanecer delgados y sólo orquestar las solicitudes. Traslade la lógica empresarial a los servicios.

Ejemplo de no conformidad

1// src/api/article/controllers/article.js
2module.exports = {
3  async create(ctx) {
4    const { title, content, authorId } = ctx.request.body;
5
6    const author = await strapi.db.query('api::author.author').findOne({ where: { id: authorId } });
7    if (!author) ctx.throw(400, 'Author not found');
8
9    const timestamp = new Date().toISOString();
10    const slug = title.toLowerCase().replace(/\s+/g, '-');
11
12    const article = await strapi.db.query('api::article.article').create({
13      data: { title, content, slug, publishedAt: timestamp, author },
14    });
15
16    await strapi.plugins['email'].services.email.send({
17      to: author.email,
18      subject: `New article: ${title}`,
19      html: `<p>${content}</p>`,
20    });
21
22    ctx.body = article;
23  },
24};

Ejemplo de conformidad

1// src/api/article/controllers/article.js
2module.exports = {
3  async create(ctx) {
4    const article = await strapi.service('api::article.article').createArticle(ctx.request.body);
5    ctx.body = article;
6  },
7};
// src/api/article/services/article.js
module.exports = ({ strapi }) => ({
  async createArticle(data) {
    const { title, content, authorId } = data;

    const author = await strapi.db.query('api::author.author').findOne({ where: { id: authorId } });
    if (!author) throw new Error('Author not found');

    const slug = title.toLowerCase().replace(/\s+/g, '-');
    const article = await strapi.db.query('api::article.article').create({
      data: { title, content, slug, author },
    });

    await strapi.plugins['email'].services.email.send({
      to: author.email,
      subject: `New article: ${title}`,
      html: `<p>${content}</p>`,
    });

    return article;
  },
});

8. Utilizar funciones de utilidad para patrones repetidos

Los patrones duplicados (por ejemplo, validación, formato) deben vivir en utilidades compartidas.

Ejemplo de no conformidad

// src/api/article/controllers/article.js
module.exports = {
  async create(ctx) {
    const { title } = ctx.request.body;
    const slug = title.toLowerCase().replace(/\s+/g, '-');
    ctx.body = await strapi.db.query('api::article.article').create({ data: { ...ctx.request.body, slug } });
  },
};

// src/api/event/controllers/event.js
module.exports = {
  async create(ctx) {
    const { name } = ctx.request.body;
    const slug = name.toLowerCase().replace(/\s+/g, '-');
    ctx.body = await strapi.db.query('api::event.event').create({ data: { ...ctx.request.body, slug } });
  },
};

Ejemplo de conformidad

// src/utils/slugify.js
módulo.exports = (texto) => text.toLowerCase().trim().replace(/\s+/g, '-');
// src/api/article/controllers/article.js
const slugify = require('../../../utils/slugify');

module.exports = {
  async create(ctx) {
    const { title } = ctx.request.body;
    const slug = slugify(title);
    ctx.body = await strapi.db.query('api::article.article').create({ data: { ...ctx.request.body, slug } });
  },
};

9. Eliminar los registros de depuración antes de la producción

No utilices console.log, console.warn, o console.error en código de producción.Utiliza siempre strapi.log o un logger configurado para asegurar que los logs respetan la configuración del entorno y evitan exponer información sensible.

Ejemplo de no conformidad

// src/api/user/controllers/user.js
module.exports = {
  async find(ctx) {
    console.log('Request received:', ctx.request.body); // Unsafe in production
    const users = await strapi.db.query('api::user.user').findMany();
    console.log('Users fetched:', users.length);
    ctx.body = users;
  },
};

Ejemplo de conformidad

// src/api/user/controllers/user.js
module.exports = {
  async find(ctx) {
    strapi.log.info(`Fetching users for request from ${ctx.state.user?.email || 'anonymous'}`);
    const users = await strapi.db.query('api::user.user').findMany();
    strapi.log.debug(`Number of users fetched: ${users.length}`);
    ctx.body = users;
  },
};
if (process.env.NODE_ENV === 'development') {
  strapi.log.debug('Request body:', ctx.request.body);
}

Normas: Base de datos y prácticas de consulta

10. Evite las consultas SQL sin procesar

No ejecute consultas SQL sin procesar en controladores o servicios. Utilice siempre un método de consulta coherente y de alto nivel (como un ORM o un generador de consultas) para garantizar la capacidad de mantenimiento, aplicar reglas/ganchos y reducir los riesgos de seguridad.

Ejemplo de no conformidad

// src/api/user/services/user.js
module.exports = {
  async findActiveUsers() {
    const knex = strapi.db.connection; 
    const result = await knex.raw('SELECT * FROM users WHERE active = true'); // Raw SQL
    return result.rows;
  },
};

Ejemplo de conformidad

// src/api/user/services/user.js
module.exports = {
  async findActiveUsers() {
    return await strapi.db.query('api::user.user').findMany({
      where: { active: true },
    });
  },
};

11. Utilizar el motor de consulta de Strapi de forma coherente

No mezcle diferentes métodos de acceso a la base de datos (por ejemplo, llamadas ORM frente a consultas sin procesar) dentro de la misma función.Utilice un enfoque de consulta único y coherente para garantizar la mantenibilidad, la legibilidad y el comportamiento predecible.

Ejemplo de no conformidad

// src/api/order/services/order.js
module.exports = {
  async getPendingOrders() {
    // Using entityService
    const orders = await strapi.entityService.findMany('api::order.order', {
      filters: { status: 'pending' },
    });

    // Mixing with raw db query
    const rawOrders = await strapi.db.connection.raw('SELECT * FROM orders WHERE status = "pending"');

    return { orders, rawOrders };
  },
};

Ejemplo de conformidad

// src/api/order/services/order.js
module.exports = {
  async getPendingOrders() {
    return await strapi.db.query('api::order.order').findMany({
      where: { status: 'pending' },
    });
  },
};

12. Optimizar las llamadas a la base de datos

Realice consultas a bases de datos relacionadas por lotes o combínelas en una sola operación para evitar cuellos de botella en el rendimiento y reducir las llamadas secuenciales innecesarias.

Ejemplo de no conformidad

async function getArticlesWithAuthors() {
  const articles = await db.query('articles').findMany();

  // Fetch author for each article sequentially
  for (const article of articles) {
    article.author = await db.query('authors').findOne({ id: article.authorId });
  }

  return articles;
}

Ejemplo de conformidad

async function getArticlesWithAuthors() {
  return await db.query('articles').findMany({ populate: ['author'] });
}

Normas: API y seguridad

13. Validar la entrada con validadores Strapi

No confíe nunca en la información procedente de clientes o fuentes externas. Valide todos los datos entrantes mediante un mecanismo de validación coherente antes de utilizarlos en controladores, servicios u operaciones de bases de datos.

Ejemplo de no conformidad

async function createUser(req, res) {
  const { username, email } = req.body;

  // Directly inserting into database without validation
  const user = await db.query('users').create({ username, email });
  res.send(user);
}

Ejemplo de conformidad

const Joi = require('joi');

async function createUser(req, res) {
  const schema = Joi.object({
    username: Joi.string().min(3).required(),
    email: Joi.string().email().required(),
  });

  const { error, value } = schema.validate(req.body);
  if (error) return res.status(400).send(error.details);

  const user = await db.query('users').create(value);
  res.send(user);
}

14. Sanear la entrada del usuario antes de guardar

Desinfecte todas las entradas antes de guardarlas en la base de datos o pasarlas a otros sistemas.

Ejemplo de no conformidad

async function createComment(req, res) {
  const { text, postId } = req.body;

  // Directly saving data
  const comment = await db.query('comments').create({ text, postId });
  res.send(comment);
}

Ejemplo de conformidad

const sanitizeHtml = require('sanitize-html');

async function createComment(req, res) {
  const { text, postId } = req.body;

  const sanitizedText = sanitizeHtml(text, { allowedTags: [], allowedAttributes: {} });

  const comment = await db.query('comments').create({ text: sanitizedText, postId });
  res.send(comment);
}

15. Aplicar controles de permisos

Aplique comprobaciones de permisos en cada ruta protegida para asegurarse de que sólo los usuarios autorizados pueden acceder a ella.

Ejemplo de no conformidad

async function deleteUser(req, res) {
  const { userId } = req.params;

  // No check for admin or owner
  await db.query('users').delete({ id: userId });
  res.send({ success: true });
}

Ejemplo de conformidad

async function deleteUser(req, res) {
  const { userId } = req.params;
  const requestingUser = req.user;

  // Allow only admins or the owner
  if (!requestingUser.isAdmin && requestingUser.id !== userId) {
    return res.status(403).send({ error: 'Forbidden' });
  }

  await db.query('users').delete({ id: userId });
  res.send({ success: true });
}

16. Tratamiento coherente de errores con Boom

Gestione los errores de forma coherente en todas las rutas API mediante un mecanismo de gestión de errores centralizado o unificado.

Ejemplo de no conformidad

async function getUser(req, res) {
  const { id } = req.params;

  try {
    const user = await db.query('users').findOne({ id });
    if (!user) res.status(404).send('User not found'); // raw string error
    else res.send(user);
  } catch (err) {
    res.status(500).send(err.message); // different error format
  }
}

Ejemplo de conformidad

const { createError } = require('../utils/errors');

async function getUser(req, res, next) {
  try {
    const { id } = req.params;
    const user = await db.query('users').findOne({ id });

    if (!user) throw createError(404, 'User not found');

    res.send(user);
  } catch (err) {
    next(err); // passes error to centralized error handler
  }
}
// src/utils/errors.js
function createError(status, message) {
  return { status, message };
}

function errorHandler(err, req, res, next) {
  res.status(err.status || 500).json({ error: err.message });
}

module.exports = { createError, errorHandler };

Normas: Pruebas y documentación

17. Añadir o actualizar pruebas para cada característica

El código nuevo sin pruebas no se fusionará, las pruebas forman parte de la definición de hecho.

Ejemplo de no conformidad

// src/api/user/services/user.js
module.exports = {
  async createUser(data) {
    const user = await db.query('users').create(data);
    return user;
  },
};

// No test file exists for this service

Ejemplo de conformidad

// tests/user.service.test.js
const { createUser } = require('../../src/api/user/services/user');

describe('User Service', () => {
  it('should create a new user', async () => {
    const mockData = { username: 'testuser', email: 'test@example.com' };
    const result = await createUser(mockData);

    expect(result).toHaveProperty('id');
    expect(result.username).toBe('testuser');
    expect(result.email).toBe('test@example.com');
  });
});

18. Documentar nuevos puntos finales

Cada adición a la API debe documentarse en los documentos de referencia antes de la fusión.

Ejemplo de no conformidad

// src/api/user/controllers/user.js
module.exports = {
  async deactivate(ctx) {
    const { userId } = ctx.request.body;
    await db.query('users').update({ id: userId, active: false });
    ctx.body = { success: true };
  },
};

// No update in API reference or docs

Ejemplo de conformidad

// src/api/user/controllers/user.js
module.exports = {
  /**
   * Deactivate a user account.
   * POST /users/deactivate
   * Body: { userId: string }
   * Response: { success: boolean }
   * Errors: 400 if userId missing, 404 if user not found
   */
  async deactivate(ctx) {
    const { userId } = ctx.request.body;
    if (!userId) ctx.throw(400, 'userId is required');

    const user = await db.query('users').findOne({ id: userId });
    if (!user) ctx.throw(404, 'User not found');

    await db.query('users').update({ id: userId, active: false });
    ctx.body = { success: true };
  },
};

Ejemplo de actualización de documentos de referencia:

### POST /users/deactivate

**Request Body:**
```json
{
  "userId": "string"
}

Respuesta:

{
  "success": true
}

Errores:

  • 400: userId es obligatorio
  • 404: Usuario no encontrado
Por qué funciona:  
- Los desarrolladores y usuarios de API pueden descubrir y utilizar los puntos finales de forma fiable.  
- Garantiza la coherencia entre la implementación y la documentación  
- Facilita el mantenimiento y la incorporación  

---

¿Quieres que continúe con la **Regla#19 ("Usar JSDoc para Utilidades Compartidas")** en el mismo formato?

19. Utilizar JSDoc para utilidades compartidas

Las funciones compartidas deben explicarse con JSDoc para facilitar la incorporación y la colaboración.

Ejemplo de no conformidad

// src/utils/slugify.js
function slugify(text) {
  return text.toLowerCase().trim().replace(/\s+/g, '-');
}

module.exports = slugify;

Ejemplo de conformidad

// src/utils/slugify.js

/**
 * Converts a string into a URL-friendly slug.
 *
 * @param {string} text - The input string to convert.
 * @returns {string} A lowercased, trimmed, dash-separated slug.
 */
function slugify(text) {
  return text.toLowerCase().trim().replace(/\s+/g, '-');
}

module.exports = slugify;

20. Actualizar el registro de cambios con cada PR significativo

Actualice el registro de cambios del proyecto con cada característica significativa, corrección de errores o cambio de API antes de fusionar un PR.

Ejemplo de no conformidad

# CHANGELOG.md

## [1.0.0] -  2025-09-01
- Versión inicial

Ejemplo de conformidad

# CHANGELOG.md

## [1.1.0] -  2025-10-06
- Añadido punto final de desactivación de usuarios (`POST /users/deactivate`)
- Corregido error en la generación de slug para títulos de artículos
- Actualizado el servicio de notificación por correo electrónico para gestionar el envío por lotes

Conclusión

Estudiamos el repositorio público de Strapi para entender cómo unos patrones de código coherentes ayudan a los grandes proyectos de código abierto a crecer sin perder calidad. Estas 20 reglas no son teoría. Son lecciones prácticas tomadas directamente del código base de Strapi que hacen que el proyecto sea más fácil de mantener, más seguro y más fácil de leer.

Si tu proyecto está creciendo, aprovecha estas lecciones y aplícalas a tus revisiones de código. Te ayudarán a pasar menos tiempo limpiando código desordenado y a dedicar más tiempo a crear funciones que realmente importan.

Preguntas frecuentes

¿Tiene alguna pregunta?

¿Por qué son importantes las normas de revisión del código en proyectos de código abierto como Strapi?

Dado que cientos de desarrolladores contribuyen, unas normas de revisión coherentes evitan el caos. Garantizan que cada pull request siga la misma estructura, nomenclatura y patrones de seguridad, manteniendo el proyecto estable y mantenible a lo largo del tiempo.

¿Cómo mantiene Strapi la calidad del código a gran escala?

Strapi utiliza estrictas convenciones de carpetas, adopción de TypeScript, pruebas automatizadas y validación estandarizada. Cada cambio se revisa en cuanto a claridad, rendimiento y seguridad antes de fusionarlo.

¿Qué diferencia hay entre las reglas de linting y las de revisión de código?

Linting detecta automáticamente problemas de sintaxis y formato. Las reglas de revisión del código van más allá: abordan la arquitectura, la legibilidad, la claridad de los nombres, la mantenibilidad y la seguridad que las herramientas no pueden detectar sin un contexto humano o de inteligencia artificial.

¿Cómo pueden los equipos aplicar estas reglas a sus propios proyectos?

- Documente sus normas de revisión.
- Añada comprobaciones automatizadas y plantillas de relaciones públicas.
- Utilice estructuras de nombres y carpetas coherentes.
- Imponga pruebas y actualizaciones de documentación en cada fusión.
- Ejecute herramientas de revisión de código basadas en IA, como Aikido Code Quality, para detectar problemas de diseño de alto nivel.

¿Qué herramientas pueden ayudar a aplicar automáticamente las normas de revisión del código?

Herramientas como Aikido Security Code Quality ayudan a detectar problemas arquitectónicos, de mantenimiento y de seguridad durante las revisiones del código, yendo mucho más allá del linting tradicional.

¿Cuál es el mayor reto a la hora de mantener el código base de Strapi?

Equilibrar la innovación con la coherencia: los nuevos colaboradores aportan ideas nuevas, pero sin reglas claras, el proyecto corre el riesgo de desviarse hacia patrones incoherentes y código difícil de mantener.

¿Cómo mejoran estas normas la incorporación de nuevos contribuyentes?

Proporcionan una hoja de ruta clara de las expectativas. Cuando la estructura de carpetas, la nomenclatura y la documentación son predecibles, los nuevos desarrolladores pueden entender rápidamente cómo contribuir sin romper los patrones existentes.

Asegúrese gratis

Proteja el código, la nube y el tiempo de ejecución en un sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No requiere tarjeta de crédito | Escanea resultados en 32segs.