Menu fechado

Desenvolva APIs de Produção com Qualidade e Escalabilidade

APIs de Produção

Arquitetura da API de Produção 🏗️

Para garantir a manutenção do sistema, implementei um padrão de Model-View-Controller (MVC) rigoroso.

Modelos

Os modelos foram definidos com Mongoose para lidar com esquemas complexos, incluindo uma referência de autor que liga Blogs a Usuários.


const mongoose = require('mongoose');

const blogSchema = new mongoose.Schema({
  title: String,
  body: String,
  author: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }
});

Controladores

Os controladores são a “mente” da engrenagem, gerenciando o fluxo de dados e lidando com interações assíncronas com o MongoDB.


const express = require('express');
const router = express.Router();
const Blog = require('./models/Blog');

router.get('/blogs', async (req, res) => {
  const blogs = await Blog.find().exec();
  res.json(blogs);
});

Lógica de Estado

Os artigos passam por estados diferentes, incluindo rascunho e publicado. Implementei guardas de segurança para garantir que rascunhos permaneçam privados enquanto conteúdo publicado é exibido na feed pública.


const mongoose = require('mongoose');

const blogSchema = new mongoose.Schema({
  title: String,
  body: String,
  state: {
    type: String,
    enum: ['draft', 'published']
  }
});

blogSchema.pre('save', async function(next) {
  if (this.state === 'draft') {
    this.private = true;
  } else {
    this.private = false;
  }
  next();
});

A arquitetura MVC contribui para a manutenção do sistema ao separar responsabilidades e permitir a fácil modificação ou substituição de qualquer componente sem afetar o resto do sistema.

Implementação de Recursos Avançados 🤖

Automatização do Algoritmo de Tempo de Leitura

Para automatizar o cálculo do tempo de leitura, utilizei Mongoose hooks para analisar o conteúdo do texto antes da salvação do documento. O código abaixo demonstra como isso foi feito:


// Define o esquema do blog
const blogSchema = new mongoose.Schema({
  // ...
  body: String,
  reading_time: Number
});

// Utilize o hook 'pre-save' para calcular o tempo de leitura
blogSchema.pre('save', async function() {
  if (this.body) {
    const wordsPerMinute = 200;
    const words = this.body.split(/\s+/).length;
    this.reading_time = Math.ceil(words / wordsPerMinute);
  }
});

Segurança com JWT

Para implementar a segurança com JWT, utilizei o middleware para verificar a validade do token em cada rota protegida. O código abaixo demonstra como isso foi feito:


// Defina o middleware para verificar o token JWT
const jwtMiddleware = async (req, res, next) => {
  const token = req.header('Authorization');
  if (!token) return res.status(401).send({ error: 'Token não fornecido' });
  
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    res.status(400).send({ error: 'Token inválido' });
  }
};

// Utilize o middleware em cada rota protegida
router.get('/protected', jwtMiddleware, async (req, res) => {
  // ...
});

Esses recursos melhoram a funcionalidade e a segurança da API, permitindo que os usuários acessem conteúdo protegido e que o tempo de leitura seja calculado automaticamente.

Depuração e Solução de Problemas

O Conflito de Porta AirPlay (Port 5000)

Encontrei um problema persistente de 404 onde meu servidor parecia estar rodando, mas o Postman não conseguia encontrar minhas rotas.


// macOS Monterey usa a porta 5000 para o AirPlay Receiver
// Migrar o ambiente local para a porta 3000 resolveu o conflito instantaneamente

Erros de Chave Duplicada (E11000)

Enquanto escrevia testes automatizados com Jest, eu atingi erros E11000 de chaves duplicadas.


// Implementar "Ativos de Dados Únicos" para o conjunto de testes, usando timestamps (Date.now()) para e-mails de usuário para garantir que cada execução de teste tenha um banco de dados isolado

Importância da Depuração e Testes

A depuração e testes são fundamentais para garantir a robustez e a escalabilidade de uma API. É crucial identificar e resolver problemas como o conflito de porta e erros de chave duplicada para garantir que a API seja estável e confiável.

Garantia de Qualidade e Testes

Abordagem de Garantia de Qualidade

Para garantir a robustez e a confiabilidade da API, foi implementada uma abordagem de garantia de qualidade que inclui a criação de uma suíte de testes abrangente com Jest e Supertest.

Suíte de Testes com Jest e Supertest

A suíte de testes foi criada utilizando Jest e Supertest, que permitem testar a API de forma eficaz e eficiente. A suíte de testes inclui 22 testes que cobrem diferentes cenários, incluindo:




* Autenticação (Signup, Login, Logout)
* Busca e precisão de regex
* Controle de autorização (garantindo que o usuário B não possa deletar o trabalho do usuário A)
* Incremento de leitura de métricas

Código de Exemplo


import request from 'supertest';
import app from '../app';

describe('Autenticação', () => {
  it('Deve realizar o login com sucesso', async () => {
    const response = await request(app).post('/login').send({ email: 'user@example.com', password: 'password' });
    expect(response.status).toBe(200);
  });

  it('Deve realizar o logout com sucesso', async () => {
    const response = await request(app).post('/logout');
    expect(response.status).toBe(200);
  });
});

Garantia de Qualidade

A abordagem de garantia de qualidade implementada garante que a API seja robusta e confiável, pois:

* A suíte de testes abrangente cobre diferentes cenários e garantindo que a API funcione corretamente
* A utilização de Jest e Supertest permite testar a API de forma eficaz e eficiente
* A criação de uma suíte de testes permite identificar e corrigir problemas de forma rápida e eficaz

Conclusão

A abordagem de garantia de qualidade implementada garante que a API seja robusta e confiável, permitindo que os usuários tenham uma experiência de utilização satisfatória. A suíte de testes abrangente e a utilização de Jest e Supertest permitem identificar e corrigir problemas de forma rápida e eficaz, garantindo a qualidade da API.

Implantação e Conclusão 🚀

A API Yarncom foi implantada em um ambiente de produção utilizando o Render e MongoDB Atlas. O processo de implantação envolveu a configuração de variáveis de ambiente, a configuração do banco de dados e a deploy da aplicação.

Deploy no Render

O deploy da API no Render foi feito utilizando o comando `render deploy`. Isso criou um ambiente de produção com o nome `yarncom-api` e configurou o servidor para ouvir em `http://yarncom-api.onrender.com`.


render deploy

Configuração do Banco de Dados

A configuração do banco de dados foi feita utilizando o MongoDB Atlas. Foi criado um cluster e configurado o usuário e senha para acesso ao banco de dados.


// Configuração do banco de dados
const mongoose = require('mongoose');

mongoose.connect('mongodb+srv://usuário:senha@cluster.mongodb.net/yarncom', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

Lições Aprendidas

Essa experiência me ensinou a importância da persistência e testes rigorosos no desenvolvimento de APIs de produção. Além disso, aprendi a importância de configurar o ambiente de produção corretamente e de testar a aplicação antes de implantá-la.

A API Yarncom foi um projeto desafiador, mas também muito gratificante. Aprendi muito sobre sistemas de gerenciamento de conteúdo e segurança de dados, e estou ansioso para aplicar essas habilidades em projetos futuros.

Se você está interessado em ver a API Yarncom em ação, pode acessá-la em https://yarncom-api.onrender.com/blogs.


Fonte de Referência: dev.to.
Curadoria e Adaptação: Redação Yassutaro Developers.



Redação YTI&W-News

Redação Developers | Yassutaro TI & Web

Notícias do universo do Desenvolvimento Web, dicas e tutoriais para Webmasters.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Publicado em:Desenvolvimento Web
Fale Conosco
×

Inscreva-se em nossa Newsletter!


Receba nossos lançamentos e artigos em primera mão!