Aikido

Strapi’nin kod tabanından öğrendiklerimiz: Ölçeklenebilir geliştirme için 20 kod inceleme kuralı

Giriş

Strapi, en popüler açık kaynaklı başsız CMS platformlarından biridir; ancak aynı zamanda yüzlerce katkıcıya ve binlerce çekme isteğine sahip devasa bir kod tabanıdır. Böylesine büyük bir projenin kalitesini yüksek tutmak kolay değildir. Her katkının güvenilir, okunabilir ve güvenli olmasını sağlamak için net ve tutarlı kod inceleme kuralları gereklidir.

Bu makalede, Strapi’nin herkese açık deposunu temel alarak bir dizi kod inceleme kuralı derledik. Bu kurallar, kod tabanını istikrarlı tutarken projenin büyümesine katkıda bulunan gerçek sorunlar, tartışmalar ve çekme isteklerinden elde edilmiştir.

Büyük bir açık kaynak projesinde kod kalitesini korumak neden zordur?

Büyük bir açık kaynak projesinde kaliteyi korumak, projenin muazzam boyutu ve katkıların çeşitliliği nedeniyle zorlu bir iştir. Gönüllülerden deneyimli mühendislere kadar yüzlerce, hatta binlerce geliştirici, her biri yeni özellikler, hata düzeltmeleri veya yeniden yapılandırmalar içeren çekme istekleri gönderir. Net kurallar olmadan kod tabanı hızla tutarsız, kırılgan veya gezinmesi zor bir hale gelebilir.

Başlıca zorluklardan bazıları şunlardır:

  • Farklı deneyim düzeylerine sahip çeşitli katılımcılar.
  • Modüller arasında tutarsız kodlama kalıpları.
  • Gizli hatalar ve tekrarlanan mantıklar yavaş yavaş ortaya çıkıyor.
  • Süreçlerin uygulanmaması durumunda ortaya çıkabilecek güvenlik riskleri.
  • Kod tabanının tamamına aşina olmayan gönüllüler için zaman alıcı inceleme süreçleri.

Bu zorlukların üstesinden gelmek için başarılı projeler, ortak standartlar, otomatikleştirilmiş araçlar ve net kılavuzlar gibi yapılandırılmış süreçlere dayanır. Bu uygulamalar, proje büyüdükçe ve daha fazla katılımcıyı kendine çektiğinde bile bakım kolaylığı, okunabilirlik ve güvenliği garanti eder.

Bu kurallara uymak, bakım kolaylığını, güvenliği ve yeni kullanıcıların sisteme alışma sürecini nasıl iyileştirir?

Net bir kod inceleme kuralları dizisine uymak, projenizin sağlığı üzerinde doğrudan bir etkiye sahiptir:

  • Bakım Kolaylığı: Tutarlı klasör yapıları, adlandırma kuralları ve kodlama kalıpları, kod tabanının okunmasını, içinde gezinilmesini ve genişletilmesini kolaylaştırır.
  • Güvenlik: Giriş doğrulama, verilerin temizlenmesi, izin kontrolleri ve kontrollü veritabanı erişimi, güvenlik açıklarını azaltır ve kazara veri sızıntılarını önler.
  • Daha Hızlı Uyum Süreci: Ortak standartlar, belgelenmiş yardımcı araçlar ve net örnekler, yeni katkıcıların projeyi hızlı bir şekilde anlamasına ve kendinden emin bir şekilde katkı sağlamasına yardımcı olur.

Bu kuralları uygulayarak, ekipler katkıda bulunanların sayısı arttıkça bile kod tabanının ölçeklenebilir, güvenilir ve güvenli kalmasını sağlayabilirler.

Bağlam ile kurallar arasında köprü kurmak

Kurallara geçmeden önce, Strapi gibi bir projede kod kalitesini yüksek tutmanın sadece genel en iyi uygulamalara uymaktan ibaret olmadığını anlamak önemlidir. Bu, yüzlerce katkıcıya aynı çizgide kalmalarına yardımcı olacak net kalıplara ve standartlara sahip olmakla ilgilidir. Aşağıdaki 20 kuralın her biri, Strapi’nin kod tabanında ortaya çıkan gerçek zorluklara odaklanmaktadır.

Her kural için verilen örnekler, hem kurallara uymayan hem de uyan yaklaşımları göstererek, bu ilkelerin pratikte nasıl uygulandığını net bir şekilde ortaya koymaktadır.

Şimdi, proje yapısı ve yapılandırma standartlarından başlayarak, Strapi’nin kod tabanını ölçeklenebilir, tutarlı ve yüksek kaliteli kılan kuralları inceleyelim.

Kurallar: Proje yapısı ve tutarlılık

1. Strapi’nin belirlenmiş klasör kurallarına uyun

Dosyaları dağınık hale getirmekten veya yeni yapılar oluşturmaktan kaçının. Gezinmeyi öngörülebilir tutmak için Strapi’nin yerleşik proje düzenine sadık kalın.

Kurallara uymayan örnek

1src/
2├──denetleyiciler/
3│  └── userController.js
4├──hizmetler/
5│  └── userLogic.js
6├──rotalar/
7│  └── userRoutes.js
8└──utils/
9   └── helper.js

✅ Kurallara uygun örnek

1src/
2└──api/
3   └── user/
4       ├── denetleyiciler/
5       │   └── user.js
6       ├── hizmetler/
7       │   └── user.js
8       ├── rotalar/
9       │   └── user.js
10       └── içerik-türleri/
11           └── user/schema.json

2. Yapılandırma dosyalarının tutarlılığını koruyun

Tutarlılığı sağlamak ve hataları önlemek için tüm yapılandırma dosyalarında aynı yapı, adlandırma ve biçimlendirme kurallarını kullanın.

Kurallara uymayan örnek

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});

✅ Kurallara uygun örnek

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. Sıkı tip güvenliği sağlamak

Tüm yeni veya güncellenen kodlar, doğru TypeScript türlerini veya JSDoc tanımlarını içermelidir. Paylaşılan modüllerde tür belirtmemekten, eksik dönüş türlerinden veya örtük tür çıkarımından kaçının.

Kurallara uymayan örnek

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

✅ Kurallara uygun örnek

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. Hizmetler ve denetleyiciler için tutarlı adlandırma

Denetleyici ve hizmet adları, ilgili etki alanlarıyla açıkça eşleşmelidir (örneğin, user.controller.js ile user.service.js).

Kurallara uymayan örnek

1src/
2└── api/
3    └── kullanıcı/
4        ├── denetleyiciler/
5        │   └── anaDenetleyici.js
6        ├── hizmetler/
7        │   └── hesapHizmeti.js
8        ├── yollar/
9        │   └── kullanıcı.js

✅ Kurallara uygun örnek

1src/
2└── api/
3    └── kullanıcı/
4        ├── denetleyiciler/
5        │   └── kullanıcı.js
6        ├── hizmetler/
7        │   └── kullanıcı.js
8        ├── yollar/
9        │   └── kullanıcı.js
10        └── içerik-türler/
11            └── kullanıcı/şema.json

Kurallar: Kod kalitesi ve bakım kolaylığı

5. Erken dönüşlerle kontrol akışını basitleştirin

Derin if/else iç içe geçme yerine, koşullar karşılanmadığında erken dönüş yapın.

Kurallara uymayan örnek

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};

✅ Kurallara uygun örnek

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. Denetleyicilerde aşırı iç içe geçme durumlarından kaçının

Denetleyiciler veya hizmetler içinde iç içe geçmiş büyük mantık bloklarından kaçının. Tekrarlanan veya karmaşık koşulları, uygun şekilde adlandırılmış yardımcı işlevlere veya yardımcı programlara ayırın.

Kurallara uymayan örnek

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};

✅ Kurallara uygun örnek

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. İş mantığını denetleyicilerden uzak tutun

Denetleyiciler yalın kalmalı ve yalnızca istekleri koordine etmelidir. İş mantığını hizmetlere taşıyın.

Kurallara uymayan örnek

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};

✅ Kurallara uygun örnek

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. Tekrarlanan desenler için yardımcı fonksiyonları kullanın

Tekrarlanan kalıplar (örneğin, doğrulama, biçimlendirme) paylaşılan yardımcı programlarda yer almalıdır.

Kurallara uymayan örnek

// 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 } });
  },
};

✅ Kurallara uygun örnek

// src/utils/slugify.js
modül.exports = (text) => 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. Üretim ortamına geçmeden önce hata ayıklama günlüklerini silin

Üretim ortamındaki kodda console.log, console.warn veya console.error kullanmayın. Günlük kayıtlarının ortam ayarlarına uygun olmasını sağlamak ve hassas bilgilerin ifşa edilmesini önlemek için her zaman strapi.log’u veya yapılandırılmış bir günlük kaydediciyi kullanın.

Kurallara uymayan örnek

// 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;
  },
};

✅ Kurallara uygun örnek

// 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);
}

Kurallar: Veritabanı ve sorgu uygulamaları

10. Ham SQL sorgularından kaçının

Denetleyicilerde veya hizmetlerde ham SQL sorguları çalıştırmayın. Bakım kolaylığını sağlamak, kuralları/kancaları uygulamak ve güvenlik risklerini azaltmak için her zaman tutarlı, üst düzey bir sorgu yöntemi (örneğin bir ORM veya sorgu oluşturucu) kullanın.

Kurallara uymayan örnek

// 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;
  },
};

✅ Kurallara uygun örnek

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

11. Strapi’nin sorgu motorunu tutarlı bir şekilde kullanın

Aynı özellik içinde farklı veritabanı erişim yöntemlerini (örneğin, ORM çağrıları ile ham sorgular) birbirine karıştırmayın. Bakım kolaylığı, okunabilirlik ve öngörülebilir davranış sağlamak için tek ve tutarlı bir sorgu yaklaşımı kullanın.

Kurallara uymayan örnek

// 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 };
  },
};

✅ Kurallara uygun örnek

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

12. Veritabanı çağrılarını optimize edin

Performans darboğazlarını önlemek ve gereksiz sıralı çağrıları azaltmak için veritabanı sorgularını gruplandırın veya tek bir işlemde birleştirin.

Kurallara uymayan örnek

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;
}

✅ Kurallara uygun örnek

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

Kurallar: API ve Güvenlik

13. Strapi doğrulayıcılarıyla girdileri doğrulayın

Müşterilerden veya harici kaynaklardan gelen girdilere asla güvenmeyin. Gelen tüm verileri, denetleyicilerde, hizmetlerde veya veritabanı işlemlerinde kullanmadan önce tutarlı bir doğrulama mekanizması kullanarak doğrulayın.

Kurallara uymayan örnek

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);
}

✅ Kurallara uygun örnek

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. Kaydetmeden önce kullanıcı girdisini temizleyin

Verileri veritabanına kaydetmeden veya diğer sistemlere aktarmadan önce tüm giriş verilerini temizleyin.

Kurallara uymayan örnek

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);
}

✅ Kurallara uygun örnek

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. İzin denetimlerini uygulayın

Yalnızca yetkili kullanıcıların erişebilmesini sağlamak için, korunan her rotada izin denetimleri uygulayın.

Kurallara uymayan örnek

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 });
}

✅ Kurallara uygun örnek

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. Boom ile tutarlı hata işleme

Merkezi veya birleştirilmiş bir hata işleme mekanizması kullanarak tüm API rotalarında hataları tutarlı bir şekilde işleyin.

Kurallara uymayan örnek

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
  }
}

✅ Kurallara uygun örnek

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 };

Kurallar: Test ve belgeleme

17. Her özellik için testler ekleyin veya güncelleyin

Testleri olmayan yeni kod birleştirilmeyecektir; testler, “tamamlanma” tanımının bir parçasıdır.

Kurallara uymayan örnek

// 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

✅ Kurallara uygun örnek

// 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. Yeni uç noktaları belgelendirin

Her API eklemesi, birleştirme işleminden önce referans belgelerinde belgelenmelidir.

Kurallara uymayan örnek

// 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

✅ Kurallara uygun örnek

// 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 };
  },
};

Referans Belgeleri Güncelleme Örneği:

### POST /users/deactivate

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

Yanıt:

{
  "success": true
}

Hatalar:

  • 400: userId bilgisi zorunludur
  • 404: Kullanıcı bulunamadı
Bunun neden işe yaradığı:  
- Geliştiriciler ve API kullanıcıları, uç noktaları güvenilir bir şekilde bulabilir ve kullanabilir  
- Uygulama ile belgeler arasında tutarlılık sağlar  
- Bakım ve yeni kullanıcıların sisteme alışmasını kolaylaştırır  

---

**Kural #19 (“Paylaşılan Yardımcı Programlar için JSDoc Kullanın”)** ile aynı formatta devam etmemi ister misiniz?

19. Ortak yardımcı programlar için JSDoc'u kullanın

Ortak işlevler, yeni başlayanların işlere alışmasını ve işbirliğini kolaylaştırmak amacıyla JSDoc ile açıklanmalıdır.

Kurallara uymayan örnek

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

module.exports = slugify;

✅ Kurallara uygun örnek

// 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. Her önemli PR ile değişiklik günlüğünü güncelleyin

Bir PR’yi birleştirmeden önce, projenin değişiklik günlüğünü her önemli özellik, hata düzeltmesi veya API değişikliğiyle güncelleyin.

Kurallara uymayan örnek

# CHANGELOG.md

## [1.0.0] - 2025-09-01
- İlk sürüm

✅ Kurallara uygun örnek

# CHANGELOG.md

## [1.1.0] - 2025-10-06
- Kullanıcı devre dışı bırakma uç noktası eklendi (`POST /users/deactivate`)
- Makale başlıklarının kısaltma oluşturulmasında bulunan hata düzeltildi
- Toplu gönderimi destekleyecek şekilde e-posta bildirim hizmeti güncellendi

Sonuç

Kaliteden ödün vermeden büyük açık kaynaklı projelerin nasıl büyüyebileceğini anlamak için Strapi’nin halka açık kod deposunu inceledik. Bu 20 kural teorik değildir. Bunlar, projenin bakımını kolaylaştıran, güvenliğini artıran ve okunabilirliğini geliştiren, doğrudan Strapi’nin kod tabanından çıkarılan pratik derslerdir.

Projeniz büyüyor ise, bu derslerden yararlanarak kod incelemelerinize uygulayın. Bu sayede, dağınık kodları düzeltmek için daha az zaman harcayıp, gerçekten önemli olan özellikleri geliştirmek için daha fazla zaman ayırabilirsiniz.

Sık Sorulan Sorular

Sorularınız mı var?

Strapi gibi açık kaynaklı projelerde kod inceleme kuralları neden önemlidir?

Yüzlerce geliştiricinin katkıda bulunduğu bir ortamda, tutarlı inceleme kuralları kaosu önler. Bu kurallar, her çekme isteğinin aynı yapıya, adlandırma kurallarına ve güvenlik kalıplarına uymasını sağlayarak projenin zaman içinde istikrarlı ve bakımı kolay kalmasını garanti eder.

Strapi, büyük ölçekte kod kalitesini nasıl koruyor?

Strapi, katı klasör kuralları, TypeScript kullanımı, otomatik testler ve standartlaştırılmış doğrulama süreçlerini uygulamaktadır. Her değişiklik, birleştirilmeden önce anlaşılırlık, performans ve güvenlik açısından incelenir.

Linting kuralları ile kod inceleme kuralları arasındaki fark nedir?

Linting, sözdizimi ve biçimlendirme sorunlarını otomatik olarak tespit eder. Kod inceleme kuralları ise daha derinlemesine inceler; mimari, okunabilirlik, adlandırma netliği, bakım kolaylığı ve güvenlik gibi, araçların insan ya da yapay zeka düzeyinde bir bağlam olmadan tespit edemediği unsurları ele alır.

Ekipler bu kuralları kendi projelerine nasıl uygulayabilir?

- İnceleme standartlarınızı belgelendirin.
- Otomatik kontroller ve PR şablonları ekleyin.
- Tutarlı adlandırma ve klasör yapıları kullanın.
- Her birleştirme işleminde testlerin ve belgelerin güncellenmesini zorunlu kılın.
- Üst düzey tasarım sorunlarını tespit etmek için Aikido Code Quality gibi yapay zeka tabanlı kod inceleme araçlarını kullanın.

Kod inceleme kurallarının otomatik olarak uygulanmasına yardımcı olabilecek araçlar nelerdir?

Aikido Security Code Quality gibi araçlar, kod incelemeleri sırasında mimari, bakım kolaylığı ve güvenlik sorunlarının tespit edilmesine yardımcı olur; bu da geleneksel linting yöntemlerinin çok ötesine geçer.

Strapi’nin kod tabanını sürdürmenin en büyük zorluğu nedir?

Yenilikçilik ile tutarlılık arasında denge kurmak — yeni katılımcılar taze fikirler getirir, ancak net kurallar olmadan proje, tutarsız yapıya sapma ve bakımı zor bir kod haline gelme riskiyle karşı karşıya kalır.

Bu kurallar, yeni katkıcıların sisteme uyum sürecini nasıl iyileştiriyor?

Beklentiler konusunda net bir yol haritası sunarlar. Klasör yapısı, adlandırma kuralları ve belgeleme öngörülebilir olduğunda, yeni geliştiriciler mevcut kalıpları bozmadan nasıl katkı sağlayacaklarını hızla kavrayabilirler.

Şimdi güvenliğinizi sağlayın

Kodunuzu, bulutunuzu ve çalışma zamanınızı tek bir merkezi sistemde güvenceye alın.
Güvenlik açıklarını otomatik olarak hızla bulun ve düzeltin.

Kredi kartı gerekmez | Tarama sonuçları 32 saniyede.