Home | Cronograma | Sprints | Requisitos | Gerência de Projeto | Horários Disponiveis |
---|---|---|---|---|---|
Mockups | Banco de Dados | Material de estudo | Arquitetura | Git Workflow | Configuração |
Padronização do Código | Testes |
Página do Banco de Dados
A aplicação utiliza o Firebase Realtime Database para a persistência de dados. O Realtime Database é um banco de dados de documentos NoSQL, sendo possível armazenar documentos JSON em qualquer estrutura, sem restrições de integridade (schema-less).
Modelo conceitual do banco de dados.
Dados armazenados
Fichas de anamnese
Considerando que todas as informações de identificação de um usuário estão relacionadas a uma anamnese, atributos como nome, email e data de nascimento, por exemplo, estão ligados à entidade Anamnese, e não a Usuário.
O atributo modificações contém o nome dos atributos que foram modificados entre uma ficha de anamnese e a ficha imediatamente anterior. Essa informação é armazenada no Firebase para melhorar o desempenho da aplicação e reduzir a quantidade de requisições ao serviço de banco de dados. Desse modo, a diferença entre duas fichas é calculada apenas uma vez (na sua criação), e não toda vez que a mesma é exibida (o que necessitaria de uma requisição extra pela ficha anterior, além da execução de um algoritmo de diffing).
Os sub-atributos frequência, dos atributos medicamentos e hábitos, possuem uma restrição de integridade de domínio: pode ser apenas um valor de um conjunto de códigos de frequência suportados pela aplicação. Os valores predefinidos, e o significado dos mesmos, podem ser vistos na tabela abaixo.
Domínio dos valores dos sub-atributos frequência dos atributos medicamentos e sintomas.
Valor do campo | Descrição |
---|---|
6-6h |
a cada 6h |
8-8h |
a cada 8h |
12-12h |
a cada 12h |
24-24h |
a cada 24h |
1xw |
uma vez por semana |
1-3xw |
de uma a três vezes por semana |
3xw |
três vezes por semana |
+3xw |
mais de três vezes por semana |
sm:-1d |
menos de um maço por dia |
sm:1d |
um maço por dia |
sm:+2d |
mais de dois maços por dia |
daily |
diariamente |
occasionaly |
ocasionalmente |
rarely |
raramente |
never |
nunca |
Esquema físico1
O objeto AnamnesisRecord
armazena as informações de uma ficha de anamnese, conforme definido abaixo:
class AnamnesisRecord {
name: string // nome
email: string // email
birthDate: string // data de nascimento: formato ISO 8601 (YYYY-MM-DD)
weight: number // peso: decimal, quilogramas
height: number // altura: inteiro, centímetros
symptoms: string[] // sintomas
pathologies: string[] // patologias
familyPathologies: string[] // histórico familiar
lifeRhythm: string // ritmo de vida
eatingStyle: string // alimentação
medicines: { // medicamentos
name: string // nome
frequency: string // frequência (restrição de domínio)
}[]
habits: { // hábitos
name: string // nome
frequency: string // frequência (restrição de domínio)
}[]
changes: string[] // modificações
}
Acompanhamento diário
O usuário deve conseguir usar a aplicação para um acompanhamento diário do seu humor, medicamentos, sintomas, nível de estresse e pressão arterial.
O acompanhamento do humor deve ser feito através do uso de emojis, para que o usuário possa facilmente indicar como se sente no momento que responde ao questionário de acompanhamento. Como emojis são caracteres Unicode, é possível armazená-los como dado textual no Firebase. Por conta disso, não foi preciso definir uma enumeração para mapear uma imagem para texto, nem persistir imagens dos emojis no Firebase. Isso permitiu a simplificação do modelo e da implementação da aplicação.
Esquema físico1
O objeto JournalEntry
armazena as informações de uma entrada no acompanhamento diário, conforme definido abaixo:
class JournalEntry {
humor: {
emotion: string // emoji
text: string // descrição do humor (raiva, feliz, ...)
}
bloodPressure: string // pressão arterial: XX/YY, XX e YY são números (ex. 12/8, 9/5, ...)
stressLevel: string // nível de estresse
symptoms: string[] // sintomas
medicines: string[] // medicamentos
}
Exames
O app oferece a funcionalidade de persistir imagens de exames realizados pelo usuário: a pessoa pode selecionar várias imagens da galeria do dispositivo (ou tirar fotos com a câmera dentro do app), e atribuir um nome e uma descrição ao conjunto de imagens. A aplicação persiste essas informações no Firebase, para que o usuário possa ter acesso rápido aos seus exames de qualquer lugar.
Um desafio para a implementação dessa funcionalidade se dá pela persistência das imagens: como isso pode ser feito com o React Native e coordenado com o Firebase.
O Firebase permite armazenar arquivos de qualquer tipo usado o Storage. As imagens são armazenadas da forma que a pessoa desenvolvedora desejar, sendo necessário apenas atribuir um caminho para a mesma.
As imagens foram organizadas no Storage de acordo com o usuário e o exame aos quais estão relacionadas: o caminho para uma imagem é dado pelo ID do usuário e pela data de criação do exame, conforme exemplo abaixo:
/<user-id>/exams/<timestamp>/<image-name>
/user-id-x/exams/1573478824428/img-ajfhskd.jpg
Esquema físico1
O objeto Exam
armazena as informações de um exame, conforme definido abaixo:
class Exam {
name: string // nome
description: string // descrição
images: string[] // nomes das imagens no Storage
}
Esquema físico do banco de dados1
Definiu-se que os dados serão armazenados no Firebase de acordo com a identificação do usuário. A partir do objeto raiz, cada usuário possui um objeto onde seu id é a chave, e suas anamneses, entradas no diário e exames são seu valor, conforme exemplo abaixo:
{ // raiz do Realtime Database
[userId: string]: {
anamneses: {
[creationDate: number /* timestamp */]: AnamnesisRecord
}
journalEntries: {
[date: number /* YYYYMMDD */]: {
[time: number /* HHmmss */]: JournalEntry
}
}
exams: {
[creationDate: number /* timestamp */]: Exam
}
}
}
Esquema físico do Storage1
Seguindo o que foi feito no Realtime Database, os arquivos armazenados no Storage são organizados de acordo com a identificação do usuário. A partir do objeto raiz, cada usuário possui uma "pasta" onde seu id é a chave.
Para permitir extensões futuras, como uma nova funcionalidade que requer a persistência de arquivos, as subpastas diretas são de acordo com a feature. As imagens de exames ficam na pasta exams
, e uma possível futura feature que necessite usar o Storage pode usar uma outra pasta no mesmo nível.
A partir do objeto raiz, a organização do Storage segue o exemplo abaixo:
{ // raiz do Storage
[userId: string]: {
exams: {
[creationDate: number /* timestamp */]: File[] // imagens do exame
}
}
}
1: a definição dos esquemas físicos está usando uma sintaxe parecida com a do TypeScript, por ser bastante parecida com a sintaxe de JSON (com a adição de tipos).