0% acharam este documento útil (0 voto)
22 visualizações16 páginas

JavaScript - Aplicação em Camadas

Enviado por

valentimmorais81
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
22 visualizações16 páginas

JavaScript - Aplicação em Camadas

Enviado por

valentimmorais81
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 16

JavaScript: Aplicação em camadas

Introdução
Aplicação em camadas – Uma aplicação em camadas é aquela em que o código da
aplicação é dividido em arquivos diferentes. Esses arquivos são chamados de camadas e
o tipo de camada é determinado com base no seu contexto. Para entender isso mais
facilmente vamos utilizar um exemplo mostrando a diferença entre uma aplicação
tradicional e uma aplicação em camadas. Nossa aplicação de exemplo é um conversor de
temperatura de Fahrenheit para Celsius.

Aplicação sem camadas


Esse é o código:
function converteParaCelsius(fahrenheit)
{
let celsius = (fahrenheit – 32) / 1.8;
return celsius;
}

let fahrenheit = 77;

console.log(converteParaCelsius(fahrenheit));
Veja que nessa versão temos apenas um arquivo e todo código da nossa aplicação está
nele. Como vimos, a aplicação em camadas tem seu código dividido em múltiplos
arquivos. Veja os exemplos abaixo:
Camada de conversão de temperatura
Arquivo conversor.js
function converteParaCelsius(fahrenheit)
{
let celsius = (fahrenheit – 32) / 1.8;
return celsius;
}

export default converteParaCelsius;


Camada de exibição
Arquivo index.js
Import converteParaCelsius from ‘./conversor.js’;

let fahrenheit = 77;

console.log(converteParaCelsius(fahrenheit));
Veja que o código ainda é o mesmo, porém, agora ele está dividido em dois arquivos
diferentes. Essa divisão resultou em duas camadas para a nossa aplicação.

O arquivo conversor.js é a camada de conversão de temperatura. Essa camada


armazena toda a lógica de conversão de temperatura da aplicação. No nosso exemplo ela
armazena a lógica de conversão de temperatura, contida na função
converteParaCelsius.
Já o arquivo index.js será nossa camada de exibição, pois é ela quem exibe os dados
para o usuário na tela. No caso do nosso exemplo, é a camada de exibição (index.js) que
vai imprimir a temperatura convertida para celsius no console.

Veja que a camada de conversão de temperatura é acessada pela camada de


exibição através do import. E a partir dessa inclusão a função converteParaCelsius é
chamada. A gente viu isso anteriormente, onde através do export e do import podemos
acessar o conteúdo de outros módulos.
Camada de exibição e camada de conversão de temperatura.
Camada de exibição -> index.js
Camada de conversão de temperatura -> conversor.js
A camada de exibição consome a camada de conversão de temperatura.

Agora que vimos o que é uma aplicação em camadas, vamos entender por que é útil.
A principal utilidade de uma aplicação em camadas é facilitar a manutenção do código. As
aplicações estão sempre recebendo atualizações e novidades, e com isso, o código
aumenta constantemente. Quanto maior o código mais complexo é a sua manutenção e
sem a divisão de camadas, todos os contextos da aplicação ficam em um só lugar. Por
exemplo: se o desenvolvedor precisasse alterar o conteúdo dos dados armazenados, ele
teria que percorrer todo o código para encontrar essa informação. A divisão em camadas
facilita esse processo, pois o desenvolvedor pode ir direto ao ponto em que precisa fazer a
alteração. Além de facilitar a manutenção, a separação em camadas também deixa o
código mais organizado e fácil de entender. Vamos a um exemplo:
function efetuaCalculoArea(raio)
{
const valorPi = 3.14;
let retornaArea = valorPi * (raio * raio);
return retornaArea;
}

let raio = 10;


let retornoArea;

retornoArea = efetuaCalculoArea(raio);

console.log(“Area: “ + retornoArea);

Repare que o nosso código possui duas variáveis com nomes bem semelhantes. Uma
situação como essa pode facilmente confundir o desenvolvedor e a alteração da variável
incorreta pode causar um erro na aplicação. Por exemplo, se no momento da
implementação tivéssemos utilizado a variável retornaArea no lugar de retornoArea, a
aplicação retornaria um erro. Por isso, dividir a aplicação em camadas nos ajuda a resolver
esse problema.
index.js
import efetuaCalculoArea from ‘./calculo.js’;

let raio = 10;


let retornoArea;

retornoArea = efetuaCalculoArea(raio);

console.log(“Area: “ + retornoArea);

calculo.js
function efetuaCalculoArea(raio)
{
const valorPi = 3.14;
let retornaArea = valorPi * (raio * raio);
return retornaArea;
}

export default efetuaCalculoArea;

Veja que as variáveis foram separadas em arquivos diferentes, resolvendo o problema dos
nomes semelhantes no mesmo arquivo.

Refatoração
Agora que você já sabe o que são e para que servem as aplicações em camadas, vamos
conhecer um conceito muito importante no processo de divisão de camadas: a refatoração.
Conceito: Na programação, refatorar significa melhorar, reorganizar um código sem alterar
seu objetivo. Para entender melhor, vamos a um exemplo:
Essa é uma aplicação que converte Celsius para Fahrenheit
let celsius = 25;
let fahrenheit;

fahrenheit = (celsius * 1.8) + 32;

console.log(fahrenheit + ‘ºF’);

if(fahrenheit >= 99)


{
console.log(‘Temperatura alta’);
} else {
console.log(‘Temperatura normal’);
}
Veja que apesar de pequeno o código não é tão simples de entender. A solução ara
casos como esse é reorganizar o código para facilitar o entendimento. Agora vamos ao
código refatorado:

function converteCelsiusParaFahrenheit(celsius)
{
let fahrenheit;
fahrenheit = (celsius * 1.8) + 32;
return fahrenheit;

function retornaStatusTemperaturaFahrenheit(celsius)
{
let status;

if(fahrenheit >= 99)


{
status = 'Temperatura alta';
}
else
{
status = 'Temperatura normal';
}

return status;
}
let celsius = 25;

let resultado = converteCelsiusParaFahrenheit(celsius);


let statusResultado = retornaStatusTemperaturaFahrenheit(resultado);

console.log(resultado + ‘ºF’);
console.log(statusResultado);

Ciclo de refatoração
Um código pode ser refatorado várias vezes, de acordo com a necessidade do
programador.

Refatoração na divisão de camadas


O processo de divisão em camadas é feito através da técnica de refatoração. Vamos
reorganizando nosso código em arquivos diferentes, a cada ciclo de refatoração.
index.js
import {converteCelsiusParaFahrenheit, retornaStatusTemperaturaFahrenheit} from
‘./retornaDadosTemperatura.js’;

let celsius = 25;

let resultado = converteCelsiusParaFahrenheit(celsius);


let statusResultado = retornaStatusTemperaturaFahrenheit(resultado);

console.log(resultado + ‘ºF’);
console.log(statusResultado);

retornaDadosTemperatura.js
function converteCelsiusParaFahrenheit(celsius)
{
let fahrenheit;
fahrenheit = (celsius * 1.8) + 32;
return fahrenheit;

function retornaStatusTemperaturaFahrenheit(celsius)
{
let status;

if(fahrenheit >= 99)


{
status = 'Temperatura alta';
}
else
{
status = 'Temperatura normal';
}
}
export { converteCelsiusParaFahrenheit, retornaStatusTemperaturaFahrenheit}
Note que assim como não existe uma única forma certa de refatorar, também não existe
uma única forma certa de se dividir uma aplicação em camadas. Nós dividimos o nosso
código em 2 arquivos, mas ele também poderia ter sido dividido em 3 arquivos.

index.js
import {converteCelsiusParaFahrenheit, retornaStatusTemperaturaFahrenheit} from
‘./retornaDadosTemperatura.js’;

let celsius = 25;

let resultado = converteCelsiusParaFahrenheit(celsius);


let statusResultado = retornaStatusTemperaturaFahrenheit(resultado);

console.log(resultado + ‘ºF’);
console.log(statusResultado);

converteTemperatura.js
function converteCelsiusParaFahrenheit(celsius)
{
let fahrenheit;
fahrenheit = (celsius * 1.8) + 32;
return fahrenheit;
}

export default converteCelsiusParaFahrenheit;

statusTemperatura.js
function retornaStatusTemperaturaFahrenheit(celsius)
{
let status;

if(fahrenheit >= 99)


{
status = 'Temperatura alta';
}
else
{
status = 'Temperatura normal';
}
}
export default retornaStatusTemperaturaFahrenheit;
As duas formas estão corretas: a diferença entre elas está no contexto.

Na versão com 2 arquivos as funções são tratadas como um único contexto: O contexto
de temperatura.

Já na versão com 3 arquivos, conversão de temperatura e status da temperatura são


tratados como contextos diferentes.

A técnica de refatoração será essencial não apenas na divisão de camadas, mas também
durante toda sua carreira como programador. Um código organizado demonstra
profissionalismo e é através da refatoração que a organização do código é alcançada. E
lembre-se: a refatoração é um ciclo e você deve sempre buscar melhorar o código da sua
aplicação.

Contextos da aplicação
O contexto de uma aplicação é a separação do seu conteúdo em grupos menores com
base em suas semelhanças. Veja um exemplo:
Contexto do cálculo da área
let base = 16;
let altura = 8;

let área = (base * altura) / 2;

contexto de exibição
console.log(“A área do triângulo é “ + area);

Para continuar nosso processo de aprendizado, vamos fazer a separação em contexto de


um código um pouco mais complexo. Veja o exemplo:

function calculaIMC(peso, altura)


{
let imc = peso / (altura * altura);
return imc;
}

let peso = 78;


let altura = 1.72;

let resultado = calculaIMC(peso, altura);

console.log(“IMC: “ + resultado);
Agora é só analisar o código e identificar seus contextos. Observando o código podemos
ver dois contextos: Contexto do cálculo de IMC e o contexto de exibição. O contexto do
cálculo de IMC é representado pela função calculaIMC, pois o único objetivo dela é esse.
Já o restante do código assume o contexto de exibição, pois seu objetivo em conjunto é
retornar resultado do cálculo de IMC para o usuário.

Modificando a calculadora IMC


Legal, a calculadora de IMC que vimos anteriormente foi separada em grupos de
contexto. Agora, faremos uma modificação no seu código para adicionar um novo recurso
nele. Vamos fazer uma modificação no código da nossa calculadora IMC, o objetivo é que
além de calcular o IMC ela também retorne um status. Para isso, adicionamos a função
retornaStatusIMC ao nosso código.

function calculaIMC(peso, altura)


{
let imc = peso / (altura * altura);
return imc;
}
function retornaStatusIMC(imc)
{
let status;
if(imc < 18.5)
{
status = “abaixo do peso”;
}
else if(imc > 18.5 && imc < 24.9)
{
status = “peso normal”;
}
else if(imc > 24.9 && imc < 30)
{
status = “acima do peso”;
}
else
{
status = “obeso”;
}
return status;
}

let peso = 78;


let altura = 1.72;

let resultado = calculaIMC(peso, altura);


let statusIMC = retornaStatusIMC(resultado);

console.log(“Seu IMC é: “ + resultado + “ e você está “ + statusIMC);


Também criamos uma variável statusIMC que armazena o valor retornado pela função.

Como fizemos alterações no nosso código, será necessário observá-lo novamente para
identificar os contextos. A função retornaStatusIMC é utilizada para retornar o status do
usuário com base no cálculo do IMC e por esse motivo ela está no contexto do cálculo
IMC.

Modificando a calculadora IMC - Tratamento de erros


Com o objetivo de deixar nosso código mais seguro contra erros, vamos fazer mais uma
mudança na nossa calculadora de IMC. Agora vamos alterar um pouco o nosso código
para que ele seja capaz de validar os valores de peso e altura. Para isso, adicionamos
duas funções no começo do código: validaPeso e validaPeso.
Contexto de validação
validaPeso
function validaPeso(peso)
{
let pesoValido = falso;

if(peso > 0)
{
pesoValido = true;
}
return pesoValido;
}

validaAltura
function validaAltura(altura)
{
let alturaValida = false;

if(altura > 0)
{
alturaValida = true;
}
return alturaValida;
}

Nesta parte do código as duas funções são utilizadas para checar os valores de peso e
altura e determinar o que dever ser feito.
let verificaPesoAltura = validaPeso(peso);
let verificaAlturaValida = validaAltura(altura);

if(verificaPesoAltura && verificaAlturaValida)


{
let resultado = calculaIMC(peso, altura);
let statusIMC = retornaStatusIMC(resultado);

console.log(“Seu IMC é “ + resultado + “ e você está “ + statusIMC);


}
Else
{
console.log(“Peso e altura devem ser maiores que zero”);
}

Se observarmos novamente nosso código vamos perceber que as funções que


adicionamos (validaPeso e validaAltura) não se encaixam em nenhum dos contextos
anteriores. Isso ocorre, pois, essas funções não tem como objetivo principal participar do
cálculo ou exibir dados, mas validar informações. Por esse motivo, validaPeso e
validaAltura terão seu próprio contexto: contexto de validação de peso e altura.

Hierarquia de camadas
Vamos usar o exemplo da calculadora de IMC, onde vimos a camada exibição consumir
funções da camada de serviço IMC. Agora nós conheceremos as subcamadas, que são
camadas menores que auxiliam direta ou indiretamente uma camada de hierarquia maior.
Uma camada pode ter infinitos níveis de subcamadas, o limite é a necessidade da
aplicação. Para entender melhor essa ideia, considere o seguinte exemplo:

Uma empresa quer fazer uma reforma no escritório e para isso ela contrata um arquiteto. A
relação entre a camada empresa e a camada arquiteto se dá em uma hierarquia de grau 1,
pois os dois são de hierarquias maiores e estão no mesmo nível. O arquiteto será
responsável pela obra, mas não é ele quem vai fazer a obra. O arquiteto não vai pintar as
paredes ou colocar os pisos. Para isso, o arquiteto contrata um mestre de obras. Observe
que o mestre de obras está em uma hierarquia de grau 2, pois está 1 grau abaixo do
arquiteto. O mestre de obras por sua vez, contrata uma equipe de operários, que
executam as tarefas e se reportam a ele. Os operários estão em uma hierarquia de grau 3,
pois estão separados do arquiteto por duas hierarquias.
Agora que entendemos a hierarquia, vamos ver o que cada parte desse exemplo
representa. O arquiteto é como a camada de serviço. É uma camada de hierarquia maior
que para cumprir a sua missão consome camadas de hierarquia menor. O mestre de
obras e os operários são as subcamadas que fornecem dados para o arquiteto direta e
indiretamente. O arquiteto se informa do estado da obra com o mestre de obras, que por
sua vez, busca informações com os operários para levar ao arquiteto. No nosso exemplo
a empresa se comunica com o arquiteto e ele fala com o mestre de obras. A empresa
nunca fala diretamente com o mestre de obras. Isso acontece, pois, empresa e arquiteto
estão no mesmo grau de hierarquia. A hierarquia deve ser respeitada na comunicação
entre as camadas.

Hierarquia de camadas no JavaScript


Agora que entendemos o conceito das hierarquias de camadas, veremos como aplicamos
isso em um código JavaScript.
Esse é o nosso código inicial. Ele possui duas camadas.
index.js
import calculaIMC frim ‘./calculadoraIMC.js’;

let peso = 78;


let altura = 1.72;

let imc = calculaIMC(peso, altura);

let mensagem = “Seu IMC é: “ + imc;

console.log(mensagem);

calculadoraIMC.js(camada de serviço IMC)


function calculadoraIMC(peso, altura)
{
let imc = peso / (altura * altura);

return imc;
}

export default calculadoraIMC;


A camada de serviço IMC é responsável por receber o peso e a altura e retornar o IMC
calculado. No final do código do arquivo calculadoraIMC.js exportamos a função
calculaIMC, para ela ser consumida por outra camada. Já na nossa camada de exibição,
logo no início importamos a camada de serviço IMC para consumirmos suas funções. Em
seguida, passamos o peso e a altura para a função calculaIMC e salvamos o retorno na
variável imc. Agora vem a variável mensagem que contém o texto que deve ser exibido
junto do resultado do imc. E por fim, utilizamos o console.log para imprimir a mensagem
no console. A camada de exibição não se preocupa com como o resultado será obtido,
ela apenas cuida de exibir os dados e a camada de serviço IMC fornece esses dados.

Subcamada de serviço
Vamos ver como a aplicação muda quando adicionamos uma nova camada a ela.
O que queremos fazer aqui é adicionar o seguinte código à nossa aplicação.
function formataIMC(imc)
{
return imc.toFixed(2);
}
Esse código tem como objetivo formatar o valor do IMC em duas casas decimais. Perceba
que a função formataIMC não se encaixa em nenhum contexto existente da nossa
calculadora de IMC. A função formataIMC não está diretamente relacionada ao cálculo do
IMC e também não é associada diretamente a exibição dos dados. Ela é uma função de
apoio para a camada de serviço IMC. Por esse motivo foi necessário criar uma nova
camada. Uma nova camada é criada quando existe um novo contexto. Agora qie
entendemos porque precisamos de uma nova camada, vamos adicioná=la à nossa
calculadora. Para isso, criaremos um novo arquivo chamado formatacaoDados.js, que será
responsável por formatar o resultado do IMC.
function formataIMC(imc)
{
return imc.toFixed(2);
}

export default formataIMC;


Isso vai fazer com que o resultado do IMC tenha no máximo duas casas decimais. Essa
camada de formatação do IMC será consumida pela camada de serviço IMC, que agora
importa o arquivo formatacaoDados.js.
import formataIMC from "../formatacao/formatacaoDados.js";

function calculaIMC(peso, altura)


{
let imc = peso / (altura * altura);
let imcFormatado = formataIMC(imc);
return imcFormatado;
}
Veja que o código da camada de serviço IMC foi alterado para incluir a função formataIMC
da camada de formatação IMC. O único objetivo da camada de formatação de IMC é
retornar para a camada de serviço o valor de IMC formatado. Desse modo, podemos dizer
que a camada de formatação de IMC é uma subcamada da camada de serviço IMC.

Subcamada de exibição
Perfeito, vimos a nossa primeira subcamada, e agora vamos ver como diferentes camadas
podem ter subcamadas.
As subcamadas não são adicionadas apenas à camada de serviço, qualquer camada pode
ter uma subcamada. Para demonstrar isso, vamos adicionar uma subcamada à nossa
camada de exibição. Para isso, criamos um novo arquivo: pesoAlturaValidacao.js
function validaPeso(peso)...
}

function validaAltura(altura)...
}

export { validaPeso, validaAltura};


Seu objetivo é verificar se os valores de peso e altura são maiores que zero e retornar a
resposta com um valor booleano. Essa verificação evita problemas de divisão por zero. Ao
executar a aplicação e tentar dividir algum valor por zero temos o problema abaixo:
PS C:\calculadoraIMC> node index.js
Infinity
A camada de validação de peso e altura foi criada para checar os dados e impedir que esse
tipo de erro ocorra. Veja que a camada de exibição cresceu. Agora ela consome também a
camada de validação de peso e altura. Agora o cálculo só será feito se o peso e altura
tiverem valor maior que zero, caso contrário outra mensagem será exibida. O único objetivo
da camada de validação de peso e altura é fornecer dados de validação do peso e da altura
para a camada de exibição. Por isso podemos dizer que a camada de validação de peso e
altura é uma subcamada da camada de exibição.
A utilização correta de camadas e subcamadas torna o código da aplicação mais
organizado, e por consequência, mais fácil de dar manutenção. Saber analisar um código
e dividi-lo em camadas é parte importante do desenvolvimento de uma aplicação.

Contextos
import {converteParaReal, converteParaEuro} from './converteMoedas.js';
import {formataReal, formataEuro, formataDolar} from './formataMoedasConvertidas.js';

let conversor = 'real';

let dolar = '5.00';


let valor_convertido;

if(conversor == 'real')
{
valor_convertido = converteParaReal(dolar);
valor_convertido = formataReal(valor_convertido);
}
else if(conversor == 'euro')
{
valor_convertido = converteParaEuro(dolar);
valor_convertido = formataEuro(valor_convertido);
}

console.log("Valor em Dólar: "+formataDolar(dolar));


console.log("Valor convertido: "+valor_convertido);

function converteParaReal(dolar)
{
let taxa_conversao = 5.07;
let real = dolar * taxa_conversao;

return real;
}

function converteParaEuro(dolar)
{
let taxa_conversao = 0.83;
let euro = dolar * taxa_conversao;

return euro;
}

export {converteParaReal, converteParaEuro};

function formataDolar(dolar)
{
let valor_formatado = '$ '+dolar;
return valor_formatado;
}

function formataReal(real)
{
let valor_formatado = 'R$ '+real;

return valor_formatado;
}

function formataEuro(euro)
{
let valor_formatado = ' € '+euro;

return valor_formatado;
}

export {formataDolar, formataReal, formataEuro};


É necessário ter um projeto node configurado com suporte a módulos para executar esse
exemplo. Isso é feito através do arquivo package.json salvo na pasta principal do projeto,
ou seja, junto do arquivo index.js.

O código do arquivo package.json pode ser visto no Código abaixo.


{
"type": "module"
}
Nem todo recurso novo precisa de uma nova camada. Recursos com contextos já
existentes devem ser colocados em camadas existentes. Já quando existe um novo
contexto, uma nova camada deve ser criada.

Projeto: Calendário de feriados


Vamos utilizar um calendário de feriados como nosso novo exemplo e veremos como uma
aplicação complexa é dividida em camadas.
O objetivo da nossa aplicação é exibir quais são os 3 próximos feriados com base nos
dados de um array de feriados.
const feriadosNacionais = [
{ nome: 'Confraternização universal', data: '01/01'},
{ nome: 'Tiradentes', data: '04/21'},
{ nome: 'Dia do trabalho', data: '05/01'},
{ nome: 'Independência do Brasil', data: '09/07'},
{ nome: 'Nossa senhora aparecida', data: '10/12'},
{ nome: 'Finados', data: '11/02'},
{ nome: 'Proclamação da república', data: '11/15'},
{ nome: 'Natal', data: '12/25'},
];

export default feriadosNacionais;

A aplicação pega a data atual, consulta os dados do array e informa os 3 próximos


feriados. O resultado ao executar a aplicação é parecido com esse exemplo abaixo:
Os próximos feriados serão:
Independência do Brasil cairá em: Terça-feira, 7/9/2021
Nossa senhora aparecida cairá em: Terça-feira, 12/10/2021
Finados cairá em: Terça-feira, 2/11/2021

O objetivo principal da aplicação é mostrar em que dia da semana vai cair cada feriado
retornado.

Calendário de feriados - camada de exibição


Já sabemos o que a nossa aplicação faz, agora conheceremos uma parte do seu código.
Esse é o index.js, nossa camada de exibição. Ela é responsável por mostrar no console
os próximos feriados.

import retornaProximosFeriados from ‘./retornaFeriados.js’;


import imprimeFeriados from ‘./imprimeFeriados.js’;

console.log("\nOs próximos feriados serão:\n");

let numeroFeriados = 3;

let proximosFeriados = retornaProximosFeriados(numeroFeriados);


imprimeFeriados(proximosFeriados);

A camada de exibição utiliza as funções retornaProximosFeriados e imprimeFeriados


para retornar e imprimir os próximos feriados.

Completando a camada de exibição temos o imprimeFeriados.js, nossa camada de


impressão dos feriados.
function imprimeFeriados(feriadosFiltro)
{
feriadosFiltro.forEach(feriado => {
const nome = feriado.nome;
const diaSemana = feriado.diaSemana;
const dataFeriado = feriado.data;

console.log(`${nome} cairá em: ${diaSemana}, ${dataFeriado}`);


});
}

export default imprimeFeriados;


Seu objetivo é imprimir no console a lista com os próximos feriados retornados pelo array.
E como vimos, a camada de exibição consome a camada de serviço feriados e a de
impressão dos feriados para alcançar seu objetivo.

Calendário de feriados - camada de serviço feriados


Agora vamos conhecer em mais detalhes a camada de serviço feriados e as suas camadas
auxiliares.
Agora que já conhecemos a estrutura da camada de exibição vamos conhecer a da camada
de serviço. O arquivo retornaFeriados.js é a nossa camada de serviço feriados. O seu papel
é fornecer dados para a camada de exibição.
A função retornaProximosFeriados faz parte da camada de serviço feriados e é responsável
por retornar um array formatado com os próximos feriados.
retornaFeriados.js
import feriadosNacionais from ‘../camada-de-dados/dataFeriados.js’;
import filtraFeriados from ‘../camada-de-apoio-servico/filtros.js’;
import {formataDiaSemana, formataDataFeriado} from ‘../camada-de-apoio-
servico/formataDataFeriado.js’;

function retornaProximosFeriados(numeroFeriados)
{
// Para conseguir filtrar os dados a função filtraFeriados precisa do array dos feriados e
do número de feriados a ser retornado.
let feriadosFiltro = filtraFeriados (feriadosNacionais, numeroFeriados);

let feriadosFiltroFormatados = [];

feriadosFiltro.forEach(feriado => {
const dataFeriado = feriado.data;
let diaSemana = formataDiaSemana(dataFeriado);
const dataFeriadoFormatada = formataDataFeriado(diaFeriado);

feriadosFiltroFormatados.push({
nome: feriado.nome,
diaSemana: diaSemana,
data: dataFeriadoFormatada
});
});

return feriadosFiltroFormatados;
}
A camada de serviço feriados não sabe como a filtragem ocorre ou como a formatação é
feita. Ela apenas se preocupa em retornar os próximos feriados. A função
retornaProximosFeriados recebe como parâmetro o número de feriados que queremos
retornar. Em seguida, esse valor é passado para a função filtraFeriados que recebe também
um array contendo todos os feriados da camada de dados. O retorno do filtro é então
‘varrido’ e retornamos o dia da semana em que o feriado vai cair e a data do feriado formata
no padrão dia/mês/ano. Resultado é adicionado ao array feriadosFiltroFormatadoss que
passa a ter o nome, o dia da semana e a data formatada do feriado. Por fim, a função
retorna o array com os dados formatados para que ele possa ser consumido pela camada
de exibição. Veja que a camada de serviço feriados possui chamadas para outras funções
que o auxiliam. Essas funções fazem parte das camadas de apoio de serviço.

Calendário de feriados - camadas de apoio de serviço feriados


Legal, conhecemos nossa camada de serviço feriados, agora vamos conhecer suas
camadas de apoio.
A primeira camada de apoio é a camada de dados. Seu objetivo é armazenar os dados de
todos os feriados cadastrados. Ele é a nossa camada de dados e o primeiro arquivo
consumido pela camada de serviço feriados. A camada de dados armazena todos os
feriados e suas datas correspondentes. As datas são armazenadas no formato americano
(mês/dia). O motivo para isso é que o Javascript por padrão utiliza o formato americano
quando precisamos fazer cálculos e comparações envolvendo datas. Perceba que as datas
também não possuem ano. Isso é feito para que nossa aplicação funcione sempre, não
importa o ano.
dataFeriados.js
const feriadosNacionais = [
{nome: 'Confraternização universal', data: '01/01'},
{nome: 'Tiradentes', data: '04/21'},
{nome: 'Dia do Trabalho', data: '05/01'},
{nome: 'Independência do Brasil', data: '09/07'},
{nome: 'Nossa senhora aparecida', data: '10/12'},
{nome: 'Finados', data: '11/02'},
{nome: 'Proclamação da República', data: '11/15'},
{nome: 'Natal', data: '12/25'}
];

export default feriadosNacionais;

Outra camada de apoio é a camada de filtragem dos feriados. Seu objetivo é filtrar os
próximos feriados e retornar para a camada de serviço feriados. O processo de filtragem
dos feriados começa ‘varrendo’ o array de feriados e adicionando o ano as datas
correspondentes. Fazemos isso adicionando o ano atual em todas as datas de feriados e
comparando-as com a data atual. Se a data do feriado já tiver passado colocamos ela para
o próximo ano. Exemplo:
Hoje = 24/12/2023
Natal = 25/12/2023
Ano novo = 01/01/2023 => 01/01/2024
Veja que como 01/01/2023 já passou, seu ano foi alterado para 2024
Com as datas definidas criamos um novo array com o mesmo conteúdo, mas dessa vez
com a data completa e no formato Date do JS. Por fim usamos a função nativa sort para
ordenar nosso array por data e depois retornamos dele apenas o número de feriados que
queremos com o slice. No código do nosso exemplo retornaremos apenas os 3 próximos
feriados. Com os dados filtrados, precisamos formata-los e é exatamente o que veremos
como fazer.
filtros.js
// Define a função filtraFeriados que recebe dois parâmetros: feriados e numeroFeriados
function filtraFeriados(feriados, numeroFeriados)
{
// Obtém a data atual
const dataAtual = new Date();
// Obtém o ano atual da data atual
const anoAtual = dataAtual.getFullYear();

// Inicializa um array vazio para armazenar os próximos feriados


let proximosFeriados = [ ];
// Declara uma variável para armazenar a nova data do feriado
let novaDataFeriado;

// Itera sobre cada feriado na lista de feriados


feriados.forEach(feriado => {
// Converte a data do feriado para o formato de data do JavaScript, adicionando o ano
atual
novaDataFeriado = Date(feriado.data + '/' + anoAtual)
// Verifica se a data do feriado já passou em relação à data atual
if(dataAtual > novaDataFeriado)
{
// Se sim, ajusta o ano para o próximo ano
novaDataFeriado.setFullYear(anoAtual + 1);
}
// Adiciona um objeto contendo o nome e a nova data do feriado ao array
proximosFeriados
proximosFeriados.push({
nome: feriado.nome,
data: novaDataFeriado
});
})
// Ordena o array de feriados com base na data
proximosFeriados = proximosFeriados.sort((a, b) => a.data - b.data);
// Limita o array aos primeiros 'numeroFeriados' elementos
proximosFeriados = proximosFeriados.slice(0, numeroFeriados);
// Retorna a lista dos próximos feriados
return proximosFeriados;
}
A função faz uso de alguns conceitos fundamentais do JavaScript, como a criação de
objetos com propriedades ({ nome: feriado.nome, data: novaDataFeriado }), o uso do
método forEach para iterar sobre arrays, o uso de objetos Date para manipulação de datas,
e o método sort para ordenar arrays. Além disso, a função utiliza a função slice para limitar
o número de elementos no array resultante.

A última camada de apoio é a camada de formatação dos feriados. Seu objetivo é retornar
a data e o dia da semana formatados corretamente.
formataDataFeriado.js
function formataDiaSemana(dataFeriado) {
let diasDaSemana = [
"Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira",
"Sábado"
];
return diasDaSemana[dataFeriado.getDay()];
}

function formataDataFeriado(dataFeriado)
{
const diaFeriado = dataFeriado.getDate();
const mesFeriado = dataFeriado.getMonth() + 1;
const anoFeriado = dataFeriado.getFullYear();

const dataExibicao = diaFeriado + "/" + mesFeriado + "/" + anoFeriado;

return dataExibicao;
}

export {formataDiaSemana, formataDataFeriado};


Desse modo, através das suas 3 camadas de apoio, a camada de serviço feriados
consegue alcançar seu objetivo.

Você também pode gostar