Construindo uma aplicação web completa - Parte 1

Construindo uma aplicação web completa - Parte 1

Uma das coisas mais legais de saber programar é  quando você nota uma dor/necessidade na vida real e pensa como esse problema poderia ser lidado com tecnologia, com programação. Nem sempre quando uma novo trend/mania começa a acontecer, ela ocorre da melhor forma. Muitas vezes, na verdade, o uso dessa nova trend é bem primitivo.

O poder do desenvolvimento

Com essa introdução, me refiro a nova forma de acessar os cardápios em estabelecimentos de alimentação atualmente: os cardápios online, geralmente disponibilizados por qr code nas mesas. Visitei um restaurante recentemente e logo que entrei o garçom perguntou: “O senhor quer o cardápio físico?” e, dessa vez, infelizmente respondi que preferia testar o de QR code mesmo, o modelo digital.

De forma não surpreendente, o link abriu um PDF compartilhado dentro do Google Drive. Acho que com essas informações você já consegue ter uma ideia a respeito da experiência, certo? Necessidade de dar zoom nas informações, dados desatualizados e uma experiência visual no mínimo muito ruim. Isso sem contar que outros colegas que estavam comigo na mesa tinham experiências totalmente distintas: alguns nem conseguiam abrir por não ter um leitor de pdf em seu aparelho por exemplo. E essa experiência não ocorreu apenas nesse restaurante, mas também em vários outros que visitei o mesmo problema se apresenta.

A solução em alto nível

Aqui apresento a vocês a ideia de um app que usaremos como caso de uso para construir uma aplicação com backend, frontend, banco de dados e infraestrutura.

Uma aplicação que gera um cardápio que pode ser acessado por um link gerado àquele restaurante. O problema a ser resolvido é prover uma forma fácil de criar um cardápio que ficará facilmente acessível via link/QR code. A usabilidade e responsividade do conteúdo dentro do cardápio também é uma das principais features, dentre elas:

  • Gerenciamento de categorias de produtos.
  • CRUD da entidade categorias, isto é: a possibilidade de criação (create), leitura (read), atualização (update) e deleção (delete) da entidade.
  • Gerenciamento de produtos.
  • CRUD da entidade produtos.
  • Gerenciamento da empresa (entidade).
  • Cadastro da empresa no sistema e possibilidade de alterar suas propriedades.
  • Gerar cardápio para link próprio com QR code.
  • Página responsiva para uso em todos os dispositivos móveis.

A aplicação terá dois usuários principais: a empresa (restaurante) e o cliente/consumidor. A única ação que o consumidor irá realizar é a de visualizar o cardápio, enquanto a empresa irá poder fazer todo o gerenciamento do seu catálogo de produtos.

O resultado final que queremos atingir é de uma aplicação web com sua infraestrutura provisionada na nuvem e com uma painel administrativo para a empresa que atualizará o cardápio disponível para o cliente.

Frontend x Backend

Esses dois componentes trabalham em conjunto para atingir um único objetivo: fazer com que o usuário consiga utilizar a aplicação. De forma simplificada, uma requisição “viaja” do frontend ao backend da seguinte forma:

  1. Usuário digita um domínio em seu navegador e clica em Enter.
  2. O navegador faz as requisições para o servidor (backend).
  3. O navegador recebe as respostas do servidor (backend).
  4. A página é construída (frontend) para que o usuário possa interagir com ela. Essas interações fazem com que esse processo se repita novamente.

As definições são:

  • Backend: parte da aplicação que não é visível para o usuário. É ele que irá receber as requisições e processar os dados para serem transmitidos de volta ao cliente (que pode ser um navegador).
  • Frontend: parte da aplicação que são visíveis para o usuário. Geralmente é executado pelo navegador e contém código HTML, CSS e JS.

Como conectar as pontas?

Falamos um pouco a respeito de alguns componentes que farão nossa aplicação funcionar: backend, frontend, banco de dados, infraestrutura em cloud. Gostaria de explicar um pouco como eos três primeiros componentes se comunicam.

Os requests HTTP, presentes na camada de aplicação do modelo OSI, são enviados pelo cliente ao servidor contendo HTTP headers e caso aplicável um corpo também. Essas requisições são construídas do lado do cliente antes de serem enviadas e cada requisição provavelmente terá uma resposta trazendo de volta os dados processados naquele processo.

Você pode se perguntar que tipos de dados são trafegados nesse processo. Em relação às respostas do backend variam entre:

  • Respostas HTML.
  • Arquivos estáticos: CSS, JS, imagens.
  • Resposta em JSON.
  • Sem corpo, apenas header e status code.

E o frontend:

  • HTTP requests sem corpo.
  • Form data.
  • Requisição JSON.

Fluxo ao usar um framework

Vamos supor que para essa aplicação faremos uso de Django com Django templates. Django é um framework web escrito em Python que tem foco na rapidez do desenvolvimento. Neste caso, para o navegador que fará a requisição do conteúdo é como se ele solicitasse conteúdo estático. A requisição chegará no servidor (físico/cloud) e é passada ao web server (como nginx por exemplo). Desta camada ele é enviado ao framework (Django neste caso).

É aqui que a mágica acontece para gerar conteúdo dinâmico: é o Django que é responsável por executar as lógicas necessárias para devolver a “página estática” ao navegador. Ele pode acessar o banco de dados ou até outros serviços para atingir essa objetivo, em detalhes: a URL requisitada é lida no arquivo urls.py e este arquivo é o que faz a ligação da URL com a view (controller) distinta para este processo. A view pode acessar o banco de dados através de model ou até uma outra API. No fim, um template será gerado com dados de contexto sendo passados a ele. O HTML final é enviado como resposta ao navegador e é renderizado.

Pensando um pouco na experiência do usuário

Por mais que não somos designers, algo que sempre temos que fazer ao idealizar uma aplicação é pensar um pouco na jornada do usuário e nas telas que vamos criar. Toquei um pouco neste assunto quando falei da solução em alto nível e vou ser um pouco mais específico ao falar das telas/funcionalidades que estarão presentes. Telas a serem construídas:

  • Cadastro de empresa.
  • Login de empresa.
  • Página inicial da empresa.
  • Gerenciamento de categorias: CRUD.
  • Gerenciamento de produtos: CRUD.
  • Gerenciamento de empresa: alteração.
  • Página do menu.

A escolha da stack frontend

Na seção “Fluxo ao usar um framework” falei um pouco sobre como os componentes internos de uma biblioteca conversam com um client (navegador). Para o exemplo, usei o Django e é ele mesmo que iremos usar para desenvolvimento de nossa solução. Aqui vão alguns motivos por trás da escolha deste Python framework:

  • Desenvolvimento rápido.
  • Modelo de usuário built-in.
  • Autenticação built- in.
  • Sistema de templates.
  • Comunidade ativa.
  • Otima documentação.
  • Open-source.
  • Escalável.
  • Seguro.

Essas são várias das características que fazem do Django um excelente framework para desenvolvimento web, mas podemos destacar o desenvolvimento rápido como uma das principais vantagens que me fez escolher para este app. Pode-se dizer que o Django segue a filosofia de batteries included, isto é, tudo que você pode precisar está disponível para uso, sem precisar de uma outra biblioteca ou construção própria ou desenvolvimento.

A outra principal característica que posso destacar é meu nível de conforto/proficiência com a ferramenta. Como eu tenho trabalhado nos últimos dois anos na Cornershop by Uber e a empresa usa Django para seus sistemas, acabo desenvolvendo apps com o framework mais rapidamente. Esse fator é muito influente para decidir qual stack uma empresa usará para seu produto, ou seja, o que seu time atual já dominar será levado em conta para escolher qual stack/linguagem escolher para seguir em frente.

Mãos à massa! Começando a construir o frontend

Vamos começar o desenvolvimento do código da solução proposta. Você precisará de alguns pré-requisitos instalados em sua máquina:

Após ter essas aplicações instaladas fazer a criação do nosso django app, execute em seu terminal:

django-admin startproject menugenerator

Teremos a seguinte file tree em seguida:


Logo após, podemos dentro da pasta raiz criaremos o nosso primeiro app: store. Esse será o app responsável pelo restaurante/estabelecimento cadastrado em nosso sistema. Execute:

django-admin startapp store

Teremos a seguinte file tree:

Agora faremos algumas alterações em nossa estrutura atual aplicando boas práticas de projetos em Django. A todos que gostariam de saber um pouco mais sobre este assunto eu recomendo fortemente o livro Two Scoops of Django dos Greenfelds.

Usaremos uma two tier app onde o primeiro nível será o do repository root (a primeira pasta a esquerda da imagem acima menugenerator). E o segundo nível será formado pelas pastas de apps (store por exemplo) em adição a pasta de configuração principal. A alteração de diretórios deixará da seguinte forma:


Desta forma, quando um desenvolvedor abrir o projeto ele terá uma visão de alto nível de todo o projeto. Lembre-se de alterar os imports em config/settings.py para de menugenerator para config. O arquivo final ficará assim:

Django settings for menugenerator project.

Generated by 'django-admin startproject' using Django 4.1.1.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'hidden'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
]

MIDDLEWARE = [
  'django.middleware.security.SecurityMiddleware',
  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.common.CommonMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'config.urls'

TEMPLATES = [
  {
      'BACKEND': 'django.template.backends.django.DjangoTemplates',
      'DIRS': [],
      'APP_DIRS': True,
      'OPTIONS': {
          'context_processors': [
              'django.template.context_processors.debug',
              'django.template.context_processors.request',
              'django.contrib.auth.context_processors.auth',
              'django.contrib.messages.context_processors.messages',
          ],
      },
  },
]

WSGI_APPLICATION = 'config.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
  'default': {
      'ENGINE': 'django.db.backends.sqlite3',
      'NAME': BASE_DIR / 'db.sqlite3',
  }
}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
  {
      'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
  },
  {
      'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
  },
  {
      'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
  },
  {
      'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
  },
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'


Agora podemos executar um comando que iniciará o server:

python manage.py runserver


O console mostrará:

Ao acessar o navegador na url http://127.0.0.1:8000/ você verá:

Ótimo! Agora já temos nossa aplicação funcionando na web e com um app criado.

O que veremos a seguir?

Neste artigo, fiz uma explicação sobre a solução e como os componentes web se conectam com o framework, além de ter explicado como o frontend e o backend se comunicam. A respeito do desenvolvimento fizemos apenas que nossa aplicação servisse um template estático HTML, mas ainda precisamos desenvolver todas as telas previamente apresentadas e dar a devida dinamicidade a elas. Faremos isso em muito mais passo a passo nos próximos artigos , você pode esperar ver:

  • Criação dos modelos
  • Overview do ORM do Django
  • Criação dos templates
  • Overview do sistema de templates do Django
  • Ações do usuário: cadastro autenticação
  • Criação das telas mencionadas em pensando um pouco na experiência do usuário usando os template
  • Provisionamento da aplicação na infra

E muito mais! Vejo você nos próximos posts :)

⚠️
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.