O projeto good notes é uma aplicação web de notas simples e funcional.
O link para acessá-lo é: good notes
Inicialmente foi em aprender Javascript
e como funciona o fluxo de uma "aplicação real", porém eu aprendi mais do que eu esperava. Por esses motivos, eu gostaria de compartilhar sobre o processo de estudo e desenvolvimento do projeto.
Por motivos educacionais e por ser a minha primeira aplicação "grande", eu não usei nenhuma biblioteca que me fornecesse coisas prontas.
- Explicação curta
-
Com o good notes você pode criar uma conta e armazenar suas notas organizando-as em categorias.
- Explicação técnica
-
Neste projeto nós temos três entidades, usuário, categoria e nota. Para cada um, nós temos um
CRUD
(Create, Read, Update, Delete), essas entidades estão relacionadas, é por isso que nós usamos oSQL
(Structured Query Language; Usado para relacionar tabelas).Para manter tudo organizado, eu usei o
MVC
(Model View Controller) no backend, padrões deFactory
eObserver
no frontend (Mais detalhes sobre arquitetura de software serão citados abaixo).
Os links para acessar os repositórios são:
No frontend, HTML
, CSS
e JS
são usados para contruir todas as interfaces. A biblioteca Serve
é usada para criar um servidor estático no Heroku
(heroku só permite fazer deploy de um repositório se ele é um servidor).
No backend, eu estou usando Python
como linguagem principal (mas hoje eu usaria o Node.js
). Flask
é um framework usado para criar APIs (Application Programming Interface, são usados para criar pontos de comunicação entre o frontend e o backend em uma aplicação).
Heroku
é um serviço de hospedagem usado para "subir" uma aplicação (cria um dominio, ex: https://github.com), assim todos podem acessá-lo. Cloudinary
é um serviço simples usado para armazenar imagens. PostgreSQL
é um banco de dados relacional usado para armazenar informações do usuário e do sistema.
Para o servidor indentificar cada usuário, entre vários tipos de autenticação eu escolhi a autenticação via JWT
(Json Web Token). O access token permite as ações principais, refresh token pode criar um novo access token e emailConfirmation token permite e autoriza todas as ações de email.
Um projeto organizado e arquitetado deixa seu código mais legível, escalável e manutenível. Eu "sofri" muito até entender que eu precisava de uma arquitetura. Por esses motivos eu usei os padrões de MVC (Model View Controller), factory e observer.
M
O model é um representação de entidade, responsável por armazenar as regras de negócio e as consultas no banco de dados.
V
A view é a interface do cliente, responsável por fazer a comunicação entre o usuário e o model.
C
O controller é um intermediário entre a view e o model, responsável por autorizar a view à acessar a ação do model.
Com a factory, nós podemos criar uma camada (representa um componente da interface) e com o observer você consegue separar essas camadas.
function createCounter() {
const state = {
currentValue: 0 // Quando a função de incremento é chamada, esse valor é alterado
}
const increment = () => state.currentValue++;
return { increment } // Aqui ficam os métodos públicos (Os métodos que todas as camadas podem acessar)
}
const counter = createCounter(); // { increment }
counter.increment();
O state armazena os valores globais da camada. Criando camadas como esta, nós podemos organizar os valores e funções privadas e públicas.
function createDisplay() {
const state = {
display: document.querySelector('.display')
}
const setValue = value => {
state.display.innerText = value;
}
return { setValue }
}
function createCounter() {
const state = {
observers: [], // Lista de observadores para esta camada
currentValue: 0
}
const subscribe = observerFunction => {
state.observers.push(observerFunction); // Registra um observador
}
const notifyAll = counterValue => {
for (const observerFunction of state.observers) {
observerFunction(counterValue);
}
}
const increment = () => {
state.currentValue++;
notifyAll(state.currentValue); // Notifica todos os observadores
}
return { subscribe, increment }
}
const counter = createCounter(); // { subscribe, increment }
const display = createDisplay(); // { setValue }
display.setValue(0);
counter.subscribe(display.setValue);
Toda vez que o state do contador atualizar, todos os observadores do contador são notificados. Assim nós podemos desacoplar/separar as camadas, melhorando o controle e a manutenção do código.
Importante: Não é sempre que é bom usar o observer pattern, porque este padrão adiciona um complexidade (as vezes desnecessária) que é considerada "over engineering". Por esses motivos, eu não uso em toda camada.
Todas as chaves sensíveis estão escondidas no arquivo .env
e todos os tratamento de erros como a conexão com o banco de dados e ações de usuários estão implementadas. Outras implementações básicas de segurança tal como criptografia de senha no banco de dados também foram introduzidas.
Em tudo que nós fazemos, sempre há uma maneira de melhorar e este projeto não é diferente, aqui estão algumas melhorias que eu faria caso eu fosse refaze-lo.
-
Rich Text
O rich text é uma funcionalidade do good notes usado para editar notas mas essa funcionalidade é limitada, porque ela foi criada com
Javascript
puro e o única maneira de fazer um rich text é usando o método execCommand do document (este método está obsoleto). Para resolver este problema eu adicionaria uma biblioteca de rich text, assim o rich text teria mais funcionalidades e também melhoraria a experiência do usuário. -
Migrar para React.js
Eu adicionaria o
React.js
para melhorar o desenvolvimento, escalabilidade e produtividade. -
Filtros e Customizações de Categorias
Talvez seria interessante adicionar filros de categorias e mais curstomizações, também melhorando a experiência do usuário.
-
Paginação de Categorias e Notas
Para melhorar o carregamento das categorias e notas, eu adicionaria uma paginação de até 15 itens, reduzindo a quantidade de tráfico no primeiro carregamento.