Pular para o conteúdo

Como construir sistemas escaláveis com Django

woman working app development django

Na Cheesecake Labs, trabalhamos com projetos muito diferentes entre si, cada um com demandas e complexidades próprias. Depois de 10 anos construindo produtos digitais escaláveis com clientes para resolver problemas reais, percebemos alguns padrões que se repetem no nosso trabalho.

  • Trabalho duplicado: mesmo com cada projeto sendo único, parte do que construímos é sempre boilerplate, e repetimos tarefas parecidas de um projeto para o outro. Com setups padronizados, dá para acelerar as primeiras entregas e encurtar o cronograma.
  • Variação de arquitetura: cada projeto tinha uma arquitetura e um estilo de desenvolvimento diferentes. Uma arquitetura base e um styleguide deixariam a transição entre projetos mais simples para os desenvolvedores.

Com esses desafios em mente, decidimos montar starter kits na nossa stack principal, para usar de um projeto para o outro. 

Vamos ver em detalhe o nosso Starter Kit de Django.

Neste post: 

O que é o Django Starter Kit?

O Django Starter Kit é um projeto em revisão constante. Ele reúne o código reaproveitável da maior parte dos nossos projetos em uma arquitetura robusta e escalável, para que cada projeto novo comece com uma base sólida e adaptável.

O starter é mais do que boilerplate. É um projeto dockerizado e pronto para produção, que contém:

  • Módulos: a lógica que todo projeto precisa, incluindo autenticação, gestão de usuários e termos de uso. Cada módulo foi pensado para ser fácil de extrair ou estender.
  • Pacotes pré-configurados: os melhores ajustes para Django e Django REST Framework, com monitoramento de erros, documentação interativa de API e outros componentes úteis.
  • Styleguide: documentação completa, com detalhes de arquitetura, boas práticas e convenções. Desenvolvemos o nosso a partir de um styleguide já existente.

A arquitetura

A nossa arquitetura é composta por dois tipos de módulo: o core app e os demais apps. O objetivo principal é garantir que todos os apps, com exceção do core, permaneçam independentes e desacoplados.

O core app

O core app é a espinha dorsal do projeto e concentra os componentes essenciais, exigidos pela aplicação inteira. É ali que ficam settings, código comum, abstrações e utilitários que os outros apps do projeto podem compartilhar e usar.

Os demais apps

Todos os outros apps são módulos que podem interagir com o core app. Eles seguem uma estrutura parecida com esta:

.
├── models
│ └── ...
├── services
│ └── ...
├── utils
│ └── ...
├── v1
│ ├── user
│ │ ├── get
│ │ │ ├── views.py
│ │ │ ├── docs.py
│ │ │ ├── serializers.py
│ │ │ ├── tests_get_user.py
│ │ │ ├── use_case.py
│ │ │ └── ...
│ │ ├── ...
│ ├── urls.py
│ └── ...
├── urls.py
├── conftest.py
└── ...Code language: Django (django)

Alguns arquivos, como __init__.py e migrations, foram omitidos para deixar à vista só o que importa na estrutura.

Na nossa arquitetura, cada endpoint tem uma pasta com o seguinte:

  • View: cada API deve ter uma view. A view recebe as requisições e devolve as respostas adequadas.
  • Use cases: cada API deve ter um use case, chamado pela view. O use case concentra a regra de negócio da API.
  • Docs: cada API deve ter a especificação da documentação. O arquivo de documentação traz a definição da API e é usado para gerar a página OpenAPI.
  • Tests: cada API precisa de suítes de teste completas, que cubram cenários variados, incluindo edge cases e condições de erro.
  • Serializers de request e de response: cada API deve ter serializers de request e de response. Eles cuidam da validação e da transformação dos dados.

Quando vários use cases compartilham a mesma regra de negócio, essa lógica é extraída e consolidada nas pastas services ou utils, o que mantém o código coeso e organizado. A nossa filosofia de arquitetura é clara: regra de negócio mora em lugares definidos, use cases, models e services/utils. 

Independência entre apps e reúso de código

Manter o código legível e sustentável é um desafio grande. É por isso que manter os apps desacoplados importa tanto. 

É assim que tratamos a independência entre apps no starter kit:

  • Para favorecer o reúso, movemos para o core app os trechos de código comuns a vários apps. Alguma redundância, claro, é aceitável.
  • Quando precisamos estender uma propriedade muito específica do model do core, usamos o Proxy Model do Django. Assim dá para ampliar a funcionalidade do model do core sem alterar o comportamento original. Veja um exemplo:
from core.models import User as CoreUser

class User(CoreUser):
    def my_app_specific_property(self):
        ...

    class Meta:
        proxy = TrueCode language: Django (django)
  • Ao criar um relacionamento com um model que não pertence nem ao próprio app nem ao core, optamos por unmanaged models. Assim conseguimos usar o model sem importar o original, o que evita dependencies desnecessárias.
class ModelName(BaseModel):
    essential_field = models.TextField()

    class Meta:
        managed = False
        db_table = 'original_app_model_name'

class ModelWhichNeedsRelationship(BaseModel):
    relation = models.ForeignKey(ModelName, ...)
    ...Code language: Django (django)

Próximas melhorias

O Django starter kit tem sido essencial para manter a qualidade e a consistência do código nos nossos projetos. 

Mas a jornada não termina aqui. Na Cheesecake Labs, sabemos que desenvolvimento web e desenvolvimento mobile exigem adaptação e inovação contínuas.

A nossa abordagem atual é uma base robusta, mas não existe bala de prata. Seguimos refinando a arquitetura para atender as demandas específicas de cada projeto que chega.

Algumas das novidades que já estão no nosso radar:

  • Mais módulos: mapeamos módulos de uso frequente que ainda precisam entrar no starter para encurtar o nosso tempo de entrega. Um exemplo é um módulo de push notification.
  • Alternativas de framework: estamos avaliando se o Django Ninja é uma opção melhor que o Django REST Framework para o starter kit. A troca reduziria bastante o boilerplate, já que typehints simples substituiriam os serializers e as especificações de API.

Seguimos buscando novas formas de simplificar o desenvolvimento e entregar produtos melhores para os nossos clientes. 

Saiba mais sobre como trabalhamos 

Para conhecer melhor como trabalhamos na Cheesecake Labs, veja o resto do nosso blog, onde falamos de tudo que envolve desenvolvimento de software e design e detalhamos os nossos processos e a nossa abordagem.

E se você quer ajuda especializada para construir produtos digitais de qualidade, vamos conversar! Vai ser um prazer ouvir você.

construa aplicações escaláveis

Veja mais conteúdo sobre Django no nosso blog: