GraphQL – Conceitos básicos.

Todos nós que trabalhamos com programação, seja na parte front-end ou na parte back-end, já tivemos que construir uma API ou consumir uma.

Neste post, vamos entrar nos conceitos iniciais sobre GraphQL, no entanto faz-se necessário entendermos primeiro o que é API, o que é REST e o que é RESTful, para então compreendermos o que é GraphQL e para que ele serve.

O que é uma API?

Api nada mais é que um acrônimo para o termo em inglês Application Programming Interface que em português significa Interface de Programação de Aplicação.

Ou seja, são instruções, conjuntos de rotinas ou padrões de programação que são disponibilizados por um software para que outro software, seja ele um site, um aplicativo ou até mesmo um sistema que consuma esta API e disponibilize para que outros softwares utilizem suas funcionalidades, porém não se preocupem com a implementação deste software.

Por exemplo, quero consumir uma API que retorne os dados de um usuário, que são nome, e-mail, telefone, endereço e data de nascimento, quando eu passar um id como parâmetro, mas não me interessa como os dados estão salvos e como o software que retorna estes dados está montando isso para mim.

Posso ter uma tabela só com nome e data de nascimento, depois outra tabela com e-mail e telefone e por fim uma outra tabela só com endereço, e os dados serem pesquisados um select de cada vez.

select nome, dataNascimento from usuarios where id = id;
select email, telefone from usuariosIdentificadores where idUsuario = id;
select endereco from logradouros where idUsuario = id;

Ou um select com inner join.

select u.nome, u.dataNascimento, ui.email, ui.telefone, l.endereco from usuarios u inner join usuariosIdentificadores ui on u.id = ui.idUsuario inner join logradouros l on u.id = l.idUsuario where u.id = id;

Ou posso ter uma tabela que tenha todos os dados juntos

select nome, dataNascimento, email, telefone, endereco from usuarios where id = id;

Ou mesmo que estes dados venham de um banco de dados não relacional ou de um arquivo de texto, o que interessa é que quando o desenvolvedor passar:

http://exemplo.com.br/users/1 

Retorne:

{
nome: "José Roberto Bognar Junior",
dataNascimento: "22/09/1983",
email: "bognar_junior@yahoo.com.br",
telefone: 11999990101,
endereco: "Avenida Paulista, 000"
}

O que é REST e RESTful?

Conhecendo o conceito de API, precisamos entender o que é REST e RESTful antes de conhecer o GraphQL.

REST é o acrônimo em inglês para Representational State Transfer, que em português significa Transferência Representacional de Estado.

Ele nada mais é que um estilo de arquitetura de software que define um conjunto de restrições a serem usados para a criação de web services.

Os web services que estão em conformidade com o estilo arquitetural REST, denominados web services RESTful, fornecem interoperabilidade entre sistemas de computadores na Internet. Os web services RESTful permitem que os sistemas solicitantes acessem e manipulem representações textuais de recursos da web usando um conjunto uniforme e predefinido de operações sem estado.

Princípios

REST afirma que a Web já desfrutou de escalabilidade como resultado de uma série de conceitos de projeto fundamentais:

  • Um protocolo cliente/servidor sem estado: cada mensagem HTTP contém toda a informação necessária para compreender o pedido. Como resultado, nem o cliente e nem o servidor necessitam gravar nenhum estado das comunicações entre mensagens. Na prática, muitas aplicações baseadas em HTTP utilizam cookies e outros mecanismos para manter o estado da sessão (algumas destas práticas, como a reescrita de URLs, não são permitidas pela regra do REST).
  • Um conjunto de operações bem definidas que se aplicam a todos os recursos de informação: HTTP em si define um pequeno conjunto de operações, as mais importantes são POST, GET, PUT e DELETE. Com frequência estas operações são combinadas com operações CRUD para a persistência de dados, onde POST não se encaixa exatamente neste esquema.
  • Uma sintaxe universal para identificar os recursos. No sistema REST, cada recurso é unicamente direcionado através da sua URI.
  • O uso de hipermídia, tanto para a informação da aplicação como para as transições de estado da aplicação: a representação deste estado em um sistema REST são tipicamente HTML ou XML. Como resultado disto, é possível navegar com um recurso REST a muitos outros, simplesmente seguindo ligações sem requerer o uso de registros ou outra infraestrutura adicional.

As URLs abaixo podem ser consideradas padrões RESTful.

[GET] http://exemplo.com.br/users/1

[DELETE] http://exemplo.com.br/users/1

[GET] http://exemplo.com.br/users

[POST] http://exemplo/users
Body: { "nome: "Joaquim" }
HTTP Code 201 Created
{ id: 2, nome: "Joaquim" }

GraphQL

Após explicado o conceito de API, REST e RESTful, vamos enfim falar sobre GraphQL.

Se fosse necessário definir em uma palavra o que é GraphQL a palavra seria flexível.

GraphQL, na verdade é mais uma Query Language, ou seja, uma linguagem de inquirir, pesquisar, buscar dados.

GraphQL não é mais um framework ou biblioteca javascript. Na verdade, GraphQL não foi desenvolvido apenas para javascript, podemos utiliza-lo em diversas outras linguagens de programação, tais como:

GraphQL é então mais uma especificação e da mesma forma que o REST serve para consumir dados de um servidor e apresentá-lo para o cliente.

Mas se GraphQL faz a mesma coisa que REST, para que eu preciso dele?

Acalente seu ansioso coração padawan, GraphQL não é a mesma coisa que REST e nem veio para o substituir. Existem grandes diferenças entre os dois, o que veremos mais para frente. Primeiro veremos um pouco mais sobre o GraphQL.

Facebook, sempre ele.

Lá pelo longínquo ano de 2012 o Facebook enfrentou um problema quando precisou mudar suas aplicações mobile, quando sua equipe de desenvolvedores consumia as APIs REST estas retornavam dados em excesso, muitos campos que não seriam utilizados, deixando assim o desenvolvimento não só custoso e complicado, como também fugindo do padrão adotado por eles.

Precisando de uma solução para este caso, eles resolveram adotar um novo padrão, que fosse menos custoso em relação a transferência de dados e também fosse mais flexível.

Pontos positivos do GraphQL

Flexibilidade

Flexibilidade é a palavra que melhor define uma API GraphQL, visto que utilizando apenas uma API e alterando sua query podemos trazer apenas os dados que são necessários para que possamos utilizar, sem precisar pegar todos os dados ou consumir outra API que retorne menos dados.

Carregamento eficiente dos dados.

Hoje em dia a maioria das pessoas utilizam seus celulares para fazer transações, navegar na internet, acessar redes sociais, ler noticias, etc. Sendo assim, trazer dados desnecessários acalenta em demora para que as páginas sejam renderizadas ou os dados sejam carregados nos aplicativos.

Variedade de diferentes estruturas e plataformas de front-end.

Existem inúmeras formas de criar uma estrutura front-end assim como também de consumir uma API REST, sendo assim a criar e dar manutenção em uma destas APIs é extremamente custoso para que todas estas formas sejam atendidas. Com o GraphQL, cada cliente pode acessar com precisão os dados necessários.

Acabar com o Overfetching e o Underfetching

Dois outros problemas também encontrados nas APIs REST são o Overfetching e o Underfetching.

Overfetching é quando uma requisição retorna dados demais, por exemplo, você precisa apenas do nome e do e-mail de um determinado usuário, mas sua API retorna o seguinte:

{
nome: "José Roberto Bognar Junior",
rg: 303338880,
cpf: 31131133399,
endereco: {
logradouro: "Avenida 9 de Julho",
CEP: 01300000,
UF: "SP",
cidade: "São Paulo",
Bairro: "Bela Vista"
...
},
...
telefone: 11999990001,
email: "bognar_junior@yahoo.com.br"
}

Underfetching significa que uma requisição não retornou o suficiente das informações necessárias. E o cliente terá que fazer solicitações adicionais para buscar tudo o que precisa. Por exemplo o nome do usuário e os posts que ele fez no blog.

Primeiro você precisaria buscar o usuário minharota/usuarios e retornaria por exemplo:

[
{
id: 1,
nome: "Bognar"
},
{
id: 2,
nome: "Eduardo"
},
{
id: 3,
nome: "Ricardo"
},
{
id: 4,
nome: "Ana Maria"
},
]

Depois precisaria buscar os posts pelo id do usuário minharota/usuarios/1/posts e ai sim retornaria os posts deste usuário

[
{
id: 109,
titulo: "RxJS – O poder e a magia dos operadores.",
conteudo: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam odio."
},
{
id: 182,
titulo: "Funções Geradoras - Javascript.",
conteudo: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam odio."
},
{
id: 291,
titulo: "React – Hooks entendendo o conceito.",
conteudo: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam odio."
},
]

Em GraphQL passando na query algo como:

query {
Usuario(id: 1) {
nome
posts {
titulo
}
}
}

Teríamos como retorno

{
"data": {
"Usuario": {
"nome": "Bognar",
"posts": [
{ "titulo": "RxJS – O poder e a magia dos operadores." },
{ "titulo": "Funções Geradoras - Javascript." },
{ "titulo": "React – Hooks entendendo o conceito." },
]
}
}
}

Vimos que a requisição com o GraphQL é bem mais simples, passamos apenas os dados que queremos receber e utilizamos apenas uma chamada para trazer tanto o usuário quanto os posts dele.

Referências

wikipedia – API (Inglês)

wikipedia – REST (Inglês)

O que é API? REST e RESTful? Conheça as definições e diferenças!

graphql.org (Inglês)

howtographql.com(Inglês)

Stay hungry. Stay foolish.

thats-all-folks

Funções Geradoras – Javascript

Definição

Podemos definir uma função geradora como, uma função que pode ser interrompida e depois continuada.

Como assim, interrompida e depois continuada?

Segundo o site da mozilla:

A declaração function* (palavra chave function seguida de um asterisco) define um função geradora (generator function), que retorna um objeto Generator.
Geradores são funções cuja execução pode ser interrompida e posteriormente reconduzida. Seus contextos (de associações de variáveis) ficarão salvos entre cada recondução.


https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/function*

Quando combinadas com Promisses, são ferramentas muito poderosas, por diminuírem ou mesmo eliminarem problemas de callback, o famoso Callback Hell.

Uma função geradora quando chamada não é executada imediatamente, ao invés disso um objeto iterator é retornado e quando o método next() deste objeto é executado o conteúdo da função geradora será processado até encontrar a palavra-chave yield

O método next() retorna um objeto com dois valores, value e done. Onde value é o valor que é retornado e done é um valor booleano que indica se aquele valor é o último ou não.

Exemplos

Função geradora simples

A função acima é um exemplo simples de generator e o seu retorno será:

Perceba que os três primeiros objetos tem os valores que estão no yield mais o done que é falso.

Na quarta chamada do método next() o value é undefined e o done é true, significando que já executou toda a função e não existe mais retorno.

Função geradora infinita

A função acima, nunca terá como retorno done igual a true, pois toda vez que a executamos, incrementamos a variável index. E por mais que tenhamos um “while(true)” não teremos um loop infinito, já que pausamos a execução da função e retornamos quando invocamos o método next() novamente.

Seu retorno será:

Repare que ele retornou apenas o atributo value, já que a função foi invocada desta formar:

console.log(gen.next().value);

Função invocando outra função geradora.

Podemos tem uma função geradora que no seu corpo invoca outra função geradora, que irá executar um código independente da primeira função.

Repare que o parâmetro é passado de uma função para outra e os cálculos são realizados de forma independente em cada uma das funções.

Seu retorno será:

Abaixo algumas referências sobre o assunto e um vídeo do canal NBK Mundo Tech do @nbkhope

Referências:

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/function*

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Operators/yield

Vídeos:

Faça download do código aqui!

Stay hungry. Stay foolish.

thats-all-folks

React – Hooks entendendo o conceito.

Em outubro de 2018 aconteceu nos Estados Unidos em Las Vegas, Nevada, a ReactConf e dentre as novidades uma que chamou a atenção e causou um burburinho na comunidade de desenvolvedores foi uma nova feature chamada de hooks.

Dependendo de quando estiver lendo este post, a implementação do hooks ainda estará em Alpha, ou seja, não faz parte da versão corrente da biblioteca.

Mas o que são Hooks?

Hooks são um conjunto de novas funcionalidades que dentre outras coisa permitem ao desenvolvedor controlar o state de uma forma mais simples, mais rápida e mais intuitiva.

Sua implementação deu-se a partir da versão 16.7.0-alpha.0 e a promessa é que o desenvolvedor consiga transitar gradativamente do padrão utilizado atualmente para o hooks sem Breaking Changes e sem quebrar muito a cabeça, podendo no inicio até utilizar as duas formas.

Compreendendo o Hooks.

Para entendermos esta nova feature vamos criar um projeto chamado todo-hooks.

Configurando o projeto.

Eu criei usando o create-react-app, pois sou preguiçoso e não queria ter o trabalho de configurar o webpack.

create-react-app todo-hooks

Se precisar relembrar como instalar o create-react-app e como criar um projeto leia, React – Primeiros Passos e React – Criando o primeiro componente.

Feito isso temos que alterar a versão do react e do react-dom, pois na data que criei este exemplo em Novembro de 2018 a versão do react instalada ainda não possuía os hooks.

Após instalado vamos entrar na pasta do projeto.

cd todo-hooks

E alterar as versões.

npm install react@16.7.0-alpha.0 --save   
npm install react-dom@16.7.0-alpha.0 --save

Fica a sua livre escolha deletar ou não os arquivos que não vamos usar, como também fica criar uma pasta de componentes para guardar todos os nossos componentes dentro.

Como não sou um primor em CSS utilizei este exemplo de todo do site w3schools e adaptei para o nosso projeto.

Não se preocupe com o CSS que ele estará disponível no download junto com todo o projeto no final da página.

Sem enrolar mais vamos ao código.

App.js

app

Aqui não existe mistério, o arquivo app é básico, apenas chama a TodoApp e renderiza na tela.

todo.js

todo1

Neste primeiro pedaço do arquivo todo.js importamos o useState do react e também  o componente que usaremos para mostrar a lista na tela.

Perceba que no começo do componente que não é uma classe e sim uma função definimos nosso estado da seguinte forma:

const [text, setText] = useState('');
const [items, setTodo] = useState([]);

Estamos indicando que os atributos do state que serão modificados são o text e o items. E as funções que serão responsáveis por modificar estes atributos são a setText e a setTodo.

Para compararmos, no contexto atual, ou seja, na versão corrente, teríamos algo como:

constructor(props) {
  super(props);
  this.state = {
    text: '',
    items: []
  };
}
this.setState({
  text: e.target.value
});
this.setState({
  items: items.concat(newItem)
});

toogle

A função toogleChecked() varrerá os itens e alterará aquele que foi clicado para que ele seja formatado com “text-decoration: line-through”.

A função removeItem() varrerá os itens e retornará os que forem diferentes do id passado, sendo assim, retirando da lista de todo aquele que foi clicado.

return

No código acima apenas renderizamos os elementos na tela, não tem nenhuma novidade quanto a forma anterior.

todoList.js

todoItem

O componente todoList é bem simples e serve apenas para varrermos os itens que se encontram no todo.

todoItem.js

todoItemjs

E por fim o todoItem que será responsável por cada parte do lista, marcando como feito ou deletando os itens.

Lista de Hooks.

Os Hooks são classificados em básicos e adicionais da seguinte forma:

Hooks básicos:

  • useState
  • useEffect
  • useContext

Hooks adicionais:

  • useReducer
  • useCallback
  • useMemo
  • useRef
  • useImperativeMethods
  • useMutationEffect
  • useLayoutEffect

Nós usamos apenas o useState no nosso exemplo.

Vamos acrescentar o useEffect apenas para indicar quantos itens já temos na lista ou qual item estamos adicionando nela.

useeffect

O resultado será:

Explicando o Hooks básicos.

O useState permite ler e armazenas as informações de maneira mais fácil e prática no state, eliminando alguns componentes de classes e substituindo por componentes funcionais.

O useEffect é o hook que utilizamos para executar funções que necessitam ou realizam algum efeito no componente, por exemplo, mutations, subscriptions, timers e logging. Tem o mesmo efeito que os componentDidMount e componentDidUpdate tem nas classes.

O useContext é um hook que permite você utilizar o Context passando o state entre os componentes Provider(de onde vem o state) e Consumer(quem receberá) de forma mais fácil e rápida.

Conclusão.

Os hooks vieram para ajudar ao desenvolvedor escrever componentes de forma mais simples e legível.

Não será preciso refatorar todas as classe e todo o projeto. Eles não quebrarão seu código e você poderá inclusive escrever das duas formas até se acostumar com eles.

Os hooks também não matarão o redux, inclusive podem ser utilizados com ele.

É preciso cuidado ao utilizar hooks como o useMutationEffect e o useLayoutEffect, pois os mesmo podem causar efeitos indesejados e problemas de desempenho.

Vídeo da ReactConf 2018

Referências:

Documentação oficial React Hooks (Inglês)

Showmethecode (Português)

Blog getty.io (Português)

Everything you need to know about react hooks(Inglês)

Template TODO w3schools(Inglês)

RxJS – O poder e a magia dos operadores

Nos posts anteriores, RxJS – Entendendo o conceito na prática e RxJS – Programação Reativa em JavaScript, falei sobre Observer, Observable, Subject e Subscribe, que são as bases do RxJS. No entanto não falei sobre os operadores, que são partes essenciais da biblioteca, que deixam o serviço mais fácil e permitem que o código assíncrono complexo seja facilmente composto de maneira declarativa.

Mas o que são os operadores?

Eles são métodos do objeto Observable, que chamados não alteram a instância Observable existente. Em vez disso, eles retornam um novo objeto Observable, cuja lógica de assinatura é baseada no primeiro Observable.

Em resumo um operador é uma função pura que cria um novo Observable com base no atual e o anterior permanece inalterado.

Criando testando os primeiros operadores.

Vamos criar um arquivo chamado operators1.js e nele vamos digitar o seguinte código:

const { from } = require('rxjs');
const { first, last } = require('rxjs/operators');

const source = from(['Corinthians', 'Palmeiras', 'São Paulo', 'Santos']);

const firstValue = source.pipe(first());
const lastValue = source.pipe(last());

firstValue.subscribe(val => console.log(`Primeiro Valor: ${val}`));
lastValue.subscribe(val => console.log(`Último Valor: ${val}`));

O exemplo acima é um dos mais básicos que podemos fazer com os operadores da biblioteca RxJS.

Nas duas primeiras linhas estamos apenas importando os operadores da biblioteca, como fizemos nos exemplos anteriores.

Já na terceira linha temos o operador from que é um operador de criação e:

  •  Pode ser usado para converter uma promisse em um observable;
  • Em arrays e iterables, todos os valores contidos serão emitidos como uma sequência;
  • Pode ser usado para emitir uma string como uma sequência de caracteres.

No nosso exemplo estamos usando o from para emitir uma sequência em uma array com o nome dos times.

Logo abaixo temos os operadores pipe, first e last.

O operador first é um operador de filtro e retorna o primeiro valor de uma sequência qualquer.

O operador last também é um operador de filtro e retorna o último valor de uma sequência.

Já o pipe é um caso à parte, com ele nós podemos vincular os operadores, incluindo combinar vários operadores e ter apenas um retorno.

Acalme os ânimos que faremos isso mais tarde, jovem padawan.

E as duas últimas linhas apenas imprimimos os valores no console.

Extraindo o poder dos operadores.

Vamos a um exemplo um pouco mais complexo. Imagine que estão 3 pessoas em um rodízio em uma pizzaria. As pizzas são divididas em doces e salgadas e são passadas aleatoriamente, podendo os sabores serem repetidos diversas vezes enquanto as pessoas estiverem ali.

Cada pessoa tem uma peculiaridade quanto as pizzas:

  • A primeira comerá apenas 5 pedaços de pizzas salgadas, desde que às pizzas não sejam apenas de Mussarela. E comerá também apenas 3 pedaços de pizzas doces.
  • Já a segunda pessoa comerá apenas as pizzas doces
  • E por fim a terceira pessoa comerá todas as pizzas que forem oferecidas, só que não repetirá nenhum sabor.

Parece um pouco complexo não é mesmo? Temos que fazer algumas validações, cada pessoa quer uma coisa, parece complicado.

Resumindo:

  • pessoa1: Apenas 5 salgadas diferentes de Mussarela e 3 doces;
  • pessoa2: Apenas pizzas doces;
  • pessoa3: Todas as pizzas sem repetir sabor

Ai que está o poder dos operadores da biblioteca RxJS. Eles diminuirão muito as linhas de código e deixarão ele bem mais legível.

Mãos na massa.

Separarei o código em várias partes para explicar minuciosamente, mas no link do GitHub, ele estará completo.

Vamos criar um arquivo chamado operators2.js e digitar o seguinte código:

const { Subject, from } = require('rxjs');
const { filter, take, distinct, skipWhile, merge } = require('rxjs/operators');

Essa primeira parte estamos importando os operadores que utilizaremos no código, então sem nenhuma novidade, já vimos isso outras vezes.

Vou explicar cada operador assim que ele aparecer.

class Pizza {
  constructor(name) {
    this.name = name;
  }
}

class PizzaSalagada extends Pizza {
  constructor(name) {
    super(name);
    this.type = 'Salgada'
  }
}

class PizzaDoce extends Pizza {
  constructor(name) {
    super(name);
    this.type = 'Doce'
  }
}

Esta segunda parte do código estamos definindo as classes que iremos utilizar para criar os objetos. Cada pizza terá o nome e o tipo, se é doce ou salgada.

Fiz assim, pois com o advento do ES6 e este cada vez mais presente no nosso dia a dia temos que nos acostumar com o uso das classes, que já estas são muito utilizadas em outras linguagens de programação como Java ou C# e também no TypeScript(TypeScript – Interface e Class).

Nossos objetos pizza serão simples, mas se criássemos objetos complexos esta também seria uma forma.

const pessoa2 = new Subject();
const pessoa3 = new Subject();

const pizzasPessoa1 = new Array();
const pizzasPessoa2 = new Array();
const pizzasPessoa3 = new Array();

const calabresa = new PizzaSalagada('Calabresa');
const mussarela = new PizzaSalagada('Mussarela');
const portuguesa = new PizzaSalagada('Portuguesa');
const aliche = new PizzaSalagada('Aliche');
const frango = new PizzaSalagada('Frango');
const pepperoni = new PizzaSalagada('Pepperoni');
const quatroQueijos = new PizzaSalagada('Quatro queijos');
const vegetariana = new PizzaSalagada('Vegetariana');

const prestigio = new PizzaDoce('Prestigio');
const chocolate = new PizzaDoce('Chocolate');
const romeuJulieta = new PizzaDoce('Romeu e Julieta');
const pizzas = [
  calabresa,
  mussarela,
  calabresa,
  portuguesa,
  aliche,
  frango,
  portuguesa,
  calabresa,
  portuguesa,
  pepperoni,
  quatroQueijos,
  vegetariana,
  chocolate,
  prestigio,
  romeuJulieta,
  prestigio,
  chocolate,
];

No código acima criamos os objetos que trabalharemos, os subjects que serão responsáveis para ouvir tratar os dados, as arrays que guardarão os dados e os objetos de Pizza.

Por fim criamos um array que contem os objetos criados, perceba que alguns dados estão duplicados, pois em um rodízio de pizza um sabor passa mais que uma vez.

Atente-se que não criamos a pessoa1, pois como ela tem algumas peculiaridades veremos duas formas de tratar os dados com os operadores.

pessoa2
.pipe(
  skipWhile(pizza => pizza.type === 'Salgada')
)
.subscribe(
  pizza => pizzasPessoa2.push(pizza)
);

pessoa3
.pipe(
  distinct()
)
.subscribe(
  pizza => pizzasPessoa3.push(pizza)
);

setPizza = (pizza) => {
  pessoa2.next(pizza);
  pessoa3.next(pizza);
}

pizzas.forEach(pizza => setPizza(pizza));

Agora temos as iterações com as duas pessoas que já declaramos como nossos subjects, o método subscribe já foi falado antes em RxJS – Entendendo o conceito na prática, assim como o operador pipe, que foi falado no começo do post.

 

Tanto no subscribe da pessoa2, quando no subscribe da pessoa3 estamos alimentando a array relativa aquela pessoa. O que aparece de diferente agora são os operadores skipWhile e o distinct.

O operador skipWhile é um operador de filtro e ele ignora os valores se a opção fornecida for verdadeira, no nosso caso ele ignorará as pizzas que forem do tipo salgada, pois a pessoa2 só comeria as pizzas doces.

O operador distinct também é um operador de filtro, ele não permitirá que os valores sejam duplicados, sendo assim a pessoa3 que iria comer todas as pizzas não repetindo o sabor, também teve seu problema resolvido.

A função setPizza recebe como parâmetro um objeto pizza e chama os métodos next dos nossos subjects para que os valores sejam iterados.

E por último temos um loop forEach no nosso array de objetos pizzas, que passará para a função setPizza() uma pizza por vez.

Sendo assim matamos dois terços do nosso problema, os da pessoa2 e pessoa3, no entanto ainda não matamos o problema da pessoa1 e podemos resolver de duas formas.

Resolvendo o problema da pessoa1.

A primeira forma é criar dois subjects para a pessoa1, um pessoa1Salgada e pessoa1Doce, criar os pipes para cada uma e alimentar a mesma array, desta forma.

const pessoa1Salgada = new Subject(); 
const pessoa1Doce = new Subject();

// Código omitido
......

pessoa1Salgada
.pipe(
  filter(pizza => pizza.type === 'Salgada' && pizza.name !== 'Mussarela'),
  take(5)
).subscribe(
  pizza => pizzasPessoa1.push(pizza),
);

pessoa1Doce
.pipe(
  filter(pizza => pizza.type === 'Doce'),
  take(3)
).subscribe(
  pizza => pizzasPessoa1.push(pizza),
);

// Código omitido
......

setPizza = (pizza) => {
  pessoa1Salgada.next(pizza);
  pessoa1Doce.next(pizza);
  pessoa2.next(pizza);
  pessoa3.next(pizza);
}

Aqui temos mais dois operadores novos o filter e o take.

O operador filter, não preciso falar que é um operador de filtro, não é mesmo. E ele funciona exatamente igual o filter do JavaScript, ele retorna um resultado se a condição for verdadeira, ou seja, no primeiro caso se o tipo da pizza for salgada e diferente de mussarela e no segundo caso se for doce.

O operador take também é um operador de filtro, entretanto ele é um limitador, por exemplo ele retornará apenas a quantidade de registros que lhe for informado, no primeiro caso 5 e no segundo caso 3.

A segunda forma de fazer é usando o operador merge. E é a que faremos agora.

pizzasSalgadas = (pizza$) => pizza$.pipe(
  filter(pizza => (pizza.type === 'Salgada' && pizza.name !== 'Mussarela')),
  distinct(),
  take(5)
);

pizzasDoces = (pizza$) => pizza$.pipe(
  filter(pizza => pizza.type === 'Doce'),
  take(3)
);

const sourcePizzas$ = from(pizzas);
const salgadas$ = pizzasSalgadas(sourcePizzas$);
const doces$ = pizzasDoces(sourcePizzas$);

salgadas$.pipe(merge(doces$)).subscribe(
  pizza => pizzasPessoa1.push(pizza)
);

Criamos duas funções, pizzasSalgadas() e pizzasDoces() e ambas recebem um observable como parâmetro e retornam um pipe com os filtros já criados.

Os filtros são os mesmo que os anteriores, o que mudou foi apenas um distinct a mais nas salgadas, só para mostrar que podemos enfileirar operadores dentro do pipe como e quantos quisermos.

Após as funções criamos uma variável chamada sourcePizzas$ que recebe como valor o retorno do operador from.

O operador from é um operador de criação e já foi explicado no primeiro exemplo.

O que estamos fazendo é transformando um array de pizzas em um observable.

Depois passando o observable para as funções pizzasSalgadas() e pizzasDoces() guardamos seus retornos as variáveis salgadas$ e doces$, que como recebem um observable se tornam um observable.

E por final a mágica acontece, juntamos os dois observables em um único observable utilizando o operador merge, que é um operador de combinação.

E no final para ver o resultado no nosso console podemos utilizar

console.log(`pizzasPessoa1: ${JSON.stringify(pizzasPessoa1, null, 2)}`);
console.log(`pizzasPessoa2: ${JSON.stringify(pizzasPessoa2, null, 2)}`);
console.log(`pizzasPessoa3: ${JSON.stringify(pizzasPessoa3, null, 2)}`);

Dentro do console.log utilizamos o template literals para exibir os dados e utilizamos também o JSON.stringify que formatará os dados de maneira mais agradável e como estamos mais acostumados.

Nota: Quando declaramos as variáveis com o cifrão($) ou dollar sing, queremos dizer que aquela variável é um observable.

Para rodar os exemplos basta ter o node instalado, navegar até a pasta onde eles estão e digitar:

node operators1
node operators2

E o resultado para o primeiro exemplo será:

Primeiro Valor: Corinthians
Último Valor: Santos

E para o segundo exemplo:

pizzasPessoa1: [
  {
    "name": "Calabresa",
    "type": "Salgada"
  },
  {
    "name": "Portuguesa",
    "type": "Salgada"
  },
  {
    "name": "Aliche",
    "type": "Salgada"
  },
  {
    "name": "Frango",
    "type": "Salgada"
  },
  {
    "name": "Pepperoni",
    "type": "Salgada"
  },
  {
    "name": "Chocolate",
    "type": "Doce"
  },
  {
    "name": "Prestigio",
    "type": "Doce"
  },
  {
    "name": "Romeu e Julieta",
    "type": "Doce"
  }
]
pizzasPessoa2: [
  {
    "name": "Chocolate",
    "type": "Doce"
  },
  {
    "name": "Prestigio",
    "type": "Doce"
  },
  {
    "name": "Romeu e Julieta",
    "type": "Doce"
  },
  {
    "name": "Prestigio",
    "type": "Doce"
  },
  {
    "name": "Chocolate",
    "type": "Doce"
  }
]
pizzasPessoa3: [
  {
    "name": "Calabresa",
    "type": "Salgada"
  },
  {
    "name": "Mussarela",
    "type": "Salgada"
  },
  {
    "name": "Portuguesa",
    "type": "Salgada"
  },
  {
    "name": "Aliche",
    "type": "Salgada"
  },
  {
    "name": "Frango",
    "type": "Salgada"
  },
  {
    "name": "Pepperoni",
    "type": "Salgada"
  },
  {
    "name": "Quatro queijos",
    "type": "Salgada"
  },
  {
    "name": "Vegetariana",
    "type": "Salgada"
  },
  {
    "name": "Chocolate",
    "type": "Doce"
  },
  {
    "name": "Prestigio",
    "type": "Doce"
  },
  {
    "name": "Romeu e Julieta",
    "type": "Doce"
  }
]

O post ficou um pouco extenso, no entanto apenas arranhamos os operadores da biblioteca RxJS. Existem muitos outros e muitas formas de utilizá-los que não foram abordadas aqui, por isso sugiro que procure mais sobre os operadores e bons estudos.

Referências:

https://rxjs-dev.firebaseapp.com/api

https://www.learnrxjs.io/

http://reactivex.io/rxjs/manual/index.html

RxJS – Entendendo o conceito na prática.

Após estudarmos o que é o RxJS neste post: RxJS – Programação Reativa em JavaScript, vamos aplicar o conceito na prática.

Lembrando o problema.

Na nossa situação hipotética tínhamos um site de streaming de vídeo e quando clicássemos nos filtros tínhamos que criar um breadcrumb e manter estas informações, tanto de uma página para outra, quanto se clicássemos em um filme para ver as informações dele e voltássemos para a página de filtros.

Entendendo os conceitos.

Observable.

Em RxJS temos um objeto que se chama Observable, ele emite itens ou envia notificações para seus observadores(observers) chamando os métodos dos observadores.

Subscribe.

Este método é como conectamos um observer(observador) a um Observable. O observador implementa algum subconjunto dos seguintes métodos:

  • onNextUm Observable chama esse método sempre que o Observable emite um item. Este método toma como parâmetro o item emitido pelo Observable.
  • onErrorUm Observable chama esse método para indicar que não conseguiu gerar os dados esperados ou encontrou algum outro erro. Não fará mais chamadas para onNext ou onCompleted. O método onError usa como parâmetro uma indicação do que causou o erro.
  • onCompletedUm Observable chama esse método depois de ter chamado onNext pela última vez, caso não tenha encontrado nenhum erro.

Entendido o conceito acima vamos ao código.

A primeira coisa que devemos fazer é ter o node instalado e fazer download do RxJS

Primeiros Passos com NodeJS.

npm install rxjs

Após instalada a biblioteca vamos criar um arquivo chamado observable.js e digitar o seguinte código:

const { Observable } = require('rxjs');
const breadcrumb = new Array();

const observable = Observable.create(function (observer) {
  observer.next('Filmes');
  observer.next('Aventura');
  observer.next('Espacial');
  observer.next('Star Wars');
  observer.complete();
});

observable.subscribe({
  next: link => breadcrumb.push(link),
  error: err => console.error(`​Mostra se algo der errado: ${err}`),
  complete: () => console.log(breadcrumb.join("->"))
});

Para rodar o exemplo basta entrar na pasta em que você salvou o exemplo e fez download da biblioteca RxJS e utilizar o seguinte comando:

node observable

E será exibido no console:

console

Detalhe a extensão .js não precisa ser digitada.

Perceba que ele formou o breadCrumb inteiro, todos os links que passamos, mas esta não é a forma que ficará no final, fizemos assim apenas para estudar o observable.

Entendendo o código.

Na primeira linha apenas importamos o observable e na segunda linha criamos a variável breadCrumb como um array.

Na terceira linha criamos uma variável observable e atribuímos para o seu valor o observable chamando a função create().

A função create() recebe uma outra função que tem um observer como parâmetro e ele será responsável por chamar os métodos que irão alimentar este observable.

E dentro da função create temos o observer chamando o método do next() quatro vezes, passando os caminhos por parâmetro e por último chamando a função complete, que diz que já terminamos de alterar aquele observer.

Após criarmos e alimentarmos o observable, vamos chamar o subscribe dele.

Como eu disse anteriormente o subscribe vai conectar o observer ao observable. Por isso toda hora que chamamos o observer.next() dentro do observable ele dá um push() no array breadcrumb para salvar o caminho.

A o método error só será chamado se acontecer algum erro no percurso e irá imprimir na tela uma mensagem e o erro.

E o método complete irá imprimir na tela o breadcrumb em si, criando uma string e separando por “->”, através do join(), como vimos na imagem do console.

Ok, criamos o breadcrumb, mas não é exatamente isso que queremos, não é mesmo?

Queremos e precisamos que cada clique em um link guarde o caminho clicado e retorne apenas aquele caminho. E quando navegarmos para outra página e voltarmos para a pesquisa tenhamos o caminho escolhido guardado.

Subject.

Para isso não usaremos o observable e sim o subject, que é um tipo especial de observable, que permite que os valores sejam multicasts para muitos observables. Enquanto os observables puros são unicast (cada observer subscrito possui uma execução independente do observable), os subjects são multicast.

Todo subject é um observable. Internamente o subscribe deste subject não invoca uma nova execução que forneça valores. Ele simplesmente registra o observer fornecido em uma lista de observers, da mesma forma que o addListener() geralmente funciona em outras bibliotecas e linguagens. Ele contém todos os métodos que o observable  contém next(v), error(e) e complete(). Para alimentar um novo valor para o subject, basta chamar next(valor), e ele será enviado para os observers registrados para ouvir o assunto.

Usando o subject para resolver nosso problema.

Agora vamos criar um arquivo chamado breadcrumb.js e digitar o seguinte:

const { Subject } = require('rxjs');
const path = new Subject();
const breadcrumb = new Array();

pushBreadcrumb = link => {

  if (breadcrumb.indexOf(link) !== -1) {
    breadcrumb.splice(breadcrumb.indexOf(link), breadcrumb.length)
  }
  breadcrumb.push(link)
}

path
.subscribe(
  link => pushBreadcrumb(link)
);

click = link => {
  path.next(link);
  console.log(breadcrumb.join("->"));
}

click('Filmes');
click('Aventura');
click('Espacial');
click('Star Wars');

console.log(`---------------`);

click('Aventura');
click('Espacial');

Explicando o código acima temos nas três primeiras linhas a importação do subject, ao invés do observable, criamos um novo subject chamado path e criamos um array com o nome de breadcrumb.

Criamos também uma função chamada pushBreadcrumb, que recebe um parâmetro e testa se este parâmetro já está dentro da array breadcrumb, se sim ele corta a partir do parâmetro até o final a array.

E por quê isso?

Por exemplo a partir do momento que nós navegamos até “Star Wars” e voltamos para “Aventura” afim de ver outros filmes de aventura, ele irá retirar todo o caminho para que o breadcrumb não mostre informações erradas.

E por fim a função é responsável por dar um push() no breadcrumb passando o link que foi recebido como parâmetro.

Abaixo da nossa função temos o path que é nosso subject chamando o subscribe que é o método que conecta o observable.

Este método é igual ao método subscribe do primeiro exemplo, no entanto nós omitimos o error e o complete, por não querer tratá-los.

E o next, recebe um parâmetro chamado link e retorna uma função que é a pushBreadcrumb que falamos acima.

Criamos também a função click(), que será responsável por passar um link para next do observable path e escrever no console o breadcrumb.

No final nós chamamos a função click(), passando cada categoria que clicamos no menu do site.

E o resultado será esse.

breadcrumb

Um detalhe é que simulamos quando estamos em “Star Wars” e clicamos no breadcrumb para voltarmos direto para “Aventura”.

No próximo post vou falar sobre os operadores da biblioteca RxJS e o quão poderosos e funcionais eles são, diminuindo muito o código e ajudando muito na hora de fazer filtros e outras coisas mais que fazemos no dia-a-dia.

RxJS – Programação Reativa em JavaScript

Você já ouviu falar em programação reativa, Observer Pattern, Iterator Pattern e RxJS?

Estava estudando como de resolver um problema de forma simples e objetiva e me deparei com os conceitos de Observer Pattern e programação reativa.

Antes de explicar o que é cada conceito, vamos primeiro entender qual é o problema.

Entendendo o problema.

Vamos imaginar que temos um site de streaming de vídeos e estes vídeos são categorizados por: Filmes, Séries, Documentários.

E cada categoria também tem seus filhos, por exemplo Terror, Comédia, Ação, Romance e Aventura, etc…

E cada filho de cada categoria também, tem seu filho, por exemplo Aventura, tem Western, Heróis, Espacial, etc…

E cada filho do filho de cada categoria também, tem seu filho, por exemplo Espacial temos Star Trek, Star Wars, etc…

Então posso escolher o seguinte filtro: Filme->Aventura->Espacial->Star Wars e escolher o Episódio III e colocar na minha lista de favoritos, para que eu possa assistir mais tarde.

Só que ao navegar na lista de favoritos e voltar eu perco meu filtro, volto para o início da busca e tenho que refazer toda a busca novamente. Vamos supor outra situação, navego para dentro das especificações do filme para ver as informações, ano, atores, resumo e quando volto também perco o filtro.

Como manter este filtro?

Temos diversas formas de gravar estes filtro, mas vamos abordar duas como exemplos, localStorage e gravar no banco.

Tanto um quanto o outro eu preciso, todas as vezes que entrar em uma categoria e no filho dela, pegar os dados, tratar eles e gravar, ou seja, fazer várias requisições para o banco ou gravar várias vezes no localstorage, o que pode onerar um pouco nossa aplicação.

Como resolver este problema de forma mais simples?

Para resolver este problema sem ter que utilizar o localStorage e nem gravar no banco podemos utilizar a biblioteca RxJS que trabalha utilizando o conceito de programação reativa.

O que é RXJS?

RxJS é o acrônimo de Reactive Extensions for JavaScript.

Podemos definir RxJS como:

  • Uma biblioteca javascript que traz o conceito de “programação reativa” para a web, para transformar, compor e consultar fluxos de dados. Desde simples matrizes de valores(Array), a séries de eventos e fluxos complexos de dados.
  • E uma biblioteca para composição de programas assíncronos e baseados em eventos usando sequências observáveis.
  • Fornece um tipo de núcleo, os tipos de satélites do Observer Pattern, (Observable, Schedulers, Subjects) e operadores inspirados em Array tais como, map, filter, reduce, every, etc… Para permitir manipular eventos assíncronos em coleções de dados.

O RxJS combina o padrão Observer com o padrão Iterator e a programação funcional para preencher a necessidade de uma maneira ideal de gerenciar seqüências de eventos.

Observer Pattern.

O padrão Observer oferece um modelo de assinatura no qual os objetos se inscrevem em um evento e são notificados quando o evento ocorre. Esse padrão é a base da programação orientada a eventos, incluindo o JavaScript. O padrão Observer facilita o bom design orientado a objetos e promove um acoplamento flexível.

Quando trabalhamos com JavaScript, acabamos escrevendo muitos manipuladores de eventos, que são funções que serão notificadas quando um determinado evento for disparado. Essas notificações, opcionalmente, recebem um argumento de evento com detalhes sobre o evento.

O paradigma de evento e manipulador de eventos em JavaScript é a manifestação do padrão de design do Observer. Outro nome para o padrão Observer é Pub/Sub, abreviação de Publicação/Assinatura.

Iterator Pattern.

O padrão Iterator permite que os clientes realizem loop de forma efetiva em uma coleção de objetos.

Uma tarefa de programação comum é percorrer e manipular uma coleção de objetos. Essas coleções podem ser armazenadas como uma matriz ou talvez algo mais complexo, como uma estrutura de árvore ou gráfico. Além disso, podemos precisar acessar os itens na coleção em uma determinada ordem.

O padrão Iterator resolve esse problema separando a coleção de objetos da passagem desses objetos implementando um iterador especializado.

Muitas linguagens possuem Iterators embutidos suportando construções do tipo ‘for-each’ e interfaces IEnumerable e IEnumerator. No entanto, o JavaScript suporta apenas loop básico na forma de instruções for, for-in, while e do while.

O padrão Iterator permite que os desenvolvedores de JavaScript projetem construções de looping que sejam muito mais flexíveis e sofisticadas.

Programação reativa.

A programação reativa é apenas uma maneira diferente de criar aplicativos de software. Essencialmente, seu software é construído para “reagir” às mudanças que acontecem (como eventos de cliques, dados sendo buscados, etc) ao invés da maneira típica de escrever software onde explicitamente escrevemos código (também conhecido como programação “imperativa”) para lidar com essas mudanças.

Programação reativa é programar com fluxos de dados assíncronos, ou seja, que não se realizam ao mesmo tempo ou no mesmo ritmo de desenvolvimento em relação a outros fluxos ou eventos.

Sua importância é devida ao crescimento da internet e a demanda de aplicativos e operações em tempo real, os deixando mais dinâmicos. Para isso ela é baseada em quatro pilares.

  • Responsivo: As aplicações  precisam responder o mais rápido possível ao usuário, simplificam os tratamentos de erros e os tratam com rapidez e eficácia.
  • Resiliente: As aplicações precisam ser resistentes as falhas, um erro não pode travar o sistema todo, mesmo se uma falha aconteça em um módulo ou serviço o restante da aplicação precisa funcionar e esse erro tem que ser corrigido o mais rápido possível.
  • Elástico: A aplicação tem que ser escalável, ou seja, suportar vários acessos e usuários sem comprometer sua performance. Precisam aumentar ou diminuir os recursos de hardware quando necessário.
  • Orientado a mensagens: As aplicações devem ser assíncronas, passando mensagens de um componente para outro para estabelecer fronteiras entre os componentes e garantir baixo acoplamento, isolamento, transparência na localização e provêem meios para delegar o tratamento de erros através de mensagens.

Mais sobre programação reativa pode ser visto em O Manifesto Reativo.

Conceitos da RxJS.

Visto todas estas informações acima vamos falar sobre os conceitos da biblioteca em si. Estes conceitos essenciais resolvem o gerenciamento de eventos assíncronos e são:

  • Observable: representa a ideia de uma coleção invocável de valores ou eventos futuros.
  • Observer: é uma coleção de retornos de chamada que sabe como escutar os valores entregues pelo Observable.
  • Subscription: representa a execução de um Observable, é principalmente útil para cancelar a execução.
  • Operators: são funções puras que permitem um estilo de programação funcional de lidar com coleções com operações como map, filter, concat, reduce, etc.
  • Subject: é o equivalente a um EventEmitter e a única maneira de transmitir um valor ou um evento para vários Observadores.
  • Schedulers: são despachantes centralizados para controlar a simultaneidade, permitindo-nos coordenar quando o cálculo ocorre em, e. setTimeout ou requestAnimationFrame ou outros.

Resolvendo nosso problema.

Para resolver nosso problema de forma simples sem precisar fazer as requisições no banco e nem precisar gravar e buscar toda hora no localStorage, podemos um observable que será alimentado toda vez que o usuário escolher um filtro e será lido toda vez que o usuário voltar para a página de lista de filmes, poupando a aplicação de fazer requisições desnecessárias.

A implementação do exemplo ficará para o próximo post, para ser detalhada passo a passo.

Referências:

Site Oficial do RxJS

Observable Pattern

Iterator Pattern

https://martinfowler.com/articles/collection-pipeline/#NestedOperatorExpressions

https://thinkster.io/tutorials/learn-rxjs-observables/what-is-rxjs

O Manifesto Reativo

TypeScript – Interface e Class

Em orientação à objeto, classe e interface são estruturas que ajudam na construção de um objeto.

Uma interface é um conjunto de métodos e propriedades que descrevem um objeto, porém não inicializa nem os implementa.

Uma classe é uma estrutura ou plano, que a partir dela podemos criar objetos que compartilham uma mesma configuração, propriedades e métodos.

Como vimos nos posts anteriores, TypeScritpt – Primeiros passos e TypeScript – Tipos de dados, diferentemente do JavaScript o TypeScript é tipado e orientado à objeto e por isso a implementação de classe e interface é bem comum.

Interface.

Entenda a interface como um contrato de um objeto, ela que define quais os métodos ou propriedades um objeto terá, quais serão obrigatórias, quais serão opcionais, quais poderão ser alteradas e quais serão apenas de leitura

Exemplo:

interface Carro {  
  readonly motor: string;
  readonly portas: number;
  combustivel: string;
  cor?: string;
  airBag?: boolean;
}

let omega: Carro = {
  motor: "4.1", 
  portas: 2, 
  combustivel: "Gasolina"
}

omega.cor = "preta";
omega.combustivel = "Gás";

/**
 * A IDE de desenvolvimento apontará um erro,
 * pois motor é readonly
 */
//omega.motor = "3.0";
console.log(omega);

No exemplo acima declaramos uma interface chamada “Carro“, perceba que ela tem cinco propriedades, “motor“, “portas“, “combustivel“, “cor” e “airBag“.

As propriedades motor, portas e combustivel são propriedades obrigatórias na implementação da nossa interface. Só que motor e porta são readonly, ou seja, após implementadas estas propriedades não podem ser alteradas.

cor e airBag são propriedades que são opcionais(podem ou não serem implementadas). E isso fica explícito quando usamos o ponto de interrogação(?) antes de tipar a variável. Todas as variáveis que tem o ponto de interrogação(?) são variáveis opcionais.

Readonly ou const?

Uma dúvida frequente é quando usar readonly e quando usar const(para saber mais de const acesse: Var, Let e Const em JavaScript).

Segundo a própria documentação do TypeScript:

A maneira mais fácil de lembrar se você deve usar readonly ou const é perguntar se você está usando uma variável ou uma propriedade. As variáveis usam const, enquanto as propriedades usam readonly.”

Classes.

Entenda a classe como a estrutura de um objeto, por exemplo temos uma classe animal e um objeto cachorro que herda as características do objeto animal, também temos uma classe gato que também herda as características de animal, só que tem suas peculiaridades, assim como o cachorro.

Exemplo:

class Animal {
  name: string;
    constructor(name: string) { 
      this.name = name; 
    }
    move(distance: number = 0) {
      console.log(`${this.name} se move por ${distance}m.`);
    }
}

class Dog extends Animal {
  constructor(name: string) { 
    super(name); 
  }
  move(distance = 15) {
    console.log("Corre...");
    super.move(distance);
  }
}

let buddy = new Dog("Buddy");

O exemplo acima exemplifica o que foi dito, criamos a classe animal, e a classe cachorro(Dog), herda as características do animal, poderíamos implementar as peculiaridades do cachorro na própria classe, mas ainda sim ele herdarias as características do animal.

Modificadores:

As classes tem modificadores em suas propriedades que definem o nível de acesso que cada uma terá. E são eles:

  • public;
  • private;
  • protected.

Public: É o modificador padrão, toda a variável que for declarada sem um modificador de acesso automaticamente se torna pública.

Private: Quando utilizamos o modificador private em uma variável, esta não pode ser acessada fora da classe que a contém.

Protected: O modificador protected é bem parecido com o private, mas se difere porque uma classe que herda de outra pode acessar as variáveis com este modificador.

Assessores:

Quando temos uma propriedade private, podemos acessa-la através dos Getters e Setters, isso dá ao TypeScript uma maneira mais refinada de ter um controle sobre a propriedade do objeto, como Java e C#.

Para exemplificar os conceitos acima vamos implementa-los em um exemplo:

class Person {
  public name: string;
  private _age: number;
  protected height: number;

  public get age() : number {
    return this._age;
  }

  public set age(v : number) {
    this._age = v;
  }
}

class Employee extends Person{
  setHeight(height: number){
    this.height = height;
  }
}

let employee = new Employee();

employee.name = "Bognar";
employee.age = 35;
employee.setHeight(1.84);

//Indicará erro
//employee._age = 35;
//employee.height = 1.84;

console.log(employee)

Note que a classe Person tem os três modificadores de acesso que falei anteriormente.

Na propriedade name o modificador é o public, por isso que employee.name não dá erro quando atribuímos o valor “Bognar” para ela.

A propriedade _age é privada, perceba que ela começa com um underscore( _ ) para diferenciar dos métodos get() e set() que também chamam age.

O get() e o set() da propriedade conseguimos acessar, por isso que quando atribuímos employee.age não dá erro, pois não acessamos diretamente a propriedade _age e sim seu set().

A propriedade height de Person é declarada como protected, por isso não conseguimos acessar ela diretamente em employee. Mas podemos acessar ela na classe Employee e assim criar um método que a torna visível fora da classe, setHeight() e ai sim conseguimos atribuir um valor para ela.

Se tentarmos acessar employee._age ou employee.height direto, a IDE de desenvolvimento, no meu caso o Visual Studio Code, indicará um erro, falando que as propriedades não são acessíveis.

erroClass

Referências:

https://www.typescriptlang.org/index.html

https://pt.wikipedia.org/wiki/Interface_(programa%C3%A7%C3%A3o_orientada_a_objetos)

https://pt.wikipedia.org/wiki/Classe_(programa%C3%A7%C3%A3o)

TypeScript – Tipos de dados

Uma das maiores diferenças do TypeScript para o JavaScript é a tipagem de suas variáveis. Em JavaScript podemos atribuir um valor numérico para uma variável e logo depois mudar este valor para booleano, para uma string, um array ou mesmo um objeto e tudo estará ok.

Veja o exemplo abaixo:

let qualquer = 1;
console.log(qualquer, typeof qualquer );

qualquer = 'String';
console.log(qualquer, typeof qualquer );

qualquer = true;
console.log(qualquer, typeof qualquer );

qualquer = [1, 2, 3, 4, 'String', true, 5, 6, 'STRING', false];
console.log(qualquer, typeof qualquer );

qualquer = {
  name: 'Bognar',
  date: new Date(),
  article: 'TypeScript',
  publish: true
};

console.log(qualquer, typeof qualquer );

Já no TypeScript temos os tipos bem definidos e são eles:

  • String
  • Boolean
  • Number
  • Array
  • Tuple
  • Enum
  • Any
  • Void

Tipos básicos

String

String é um tipo básico e fundamental no JavaScript tanto para construção aplicativos web e mobile quanto para a construção de programas no lado do servidor. Como em outras linguagens, usamos o tipo string para nos referirmos a tipos de dados textuais. Assim como o JavaScript, o TypeScript também usa aspas duplas (“) ou aspas simples (‘) para envolver os dados da string.

Podemos definir uma variável string da seguinte forma:

let text: string = 'Valor da string';
text = 'Mudei o valor';

Se tentarmos alterar o valor de text para um número por exemplo 3 o depurador do Visual Studio Code indicará o seguinte erro:

errostring

E a linha que estamos alterando também indicará erro.

Number

No TypeScript assim como no JavaScript, todos os números são valores de ponto flutuante e recebem o tipo number. Além dos literais hexadecimais e decimais, o TypeScript também suporta literais binários e octal introduzidos no ECMAScript 2015.

let num: number;
num = 4;
num = 5 + 8;

let anotherNum: number = 5.8;
let hexNum: number = 0xf00d;
let binaryNum: number = 0b1010;
let octalNum: number = 0o744;

Boolean

Sem dúvidas é o tipo mais básico de dados que tanto o JavaScript quando o TypeScript tem, ele recebe apenas o valor true/false.

let isValid: boolean = true;
isValid = false;

Tipos complexos

Fora estes tipos básicos temos também o array, tupla(tuple) e enum.

Array

O array é um tipo muito utilizado em JavaScript. E em TypeSript podemos declará-la de duas maneiras.

A primeira é utilizando o tipo do elemento seguido por [] (colchetes).

let arr: string[] = ['Arroz', 'Feijão', 'Couve', 'Bisteca de Porco'];

A segunda é utilizando o tipo Array genérico.

let arrGeneric: Array<string> = ['Arroz', 'Feijão', 'Couve', 'Bisteca de Porco'];

Tuple(Tupla)

Os tipos de tupla permitem que você expresse um array onde o tipo e um número fixo de elementos é conhecido, mas não precisa ser o mesmo.

let tuple: [string, number, string, number];
tuple = ['hello', 1, 'world', 2];

console.log(tuple[0]);
console.log(tuple[1]);

No exemplo acima temos um número definido de elementos na array, 4 e ele são duas strings e dois números

Se definirmos a tupla alterando as ordens que os tipos foram de declarados mais uma vez o Visual Studio indicará um erro;

tuple = [1, 'hello', 2, 'world'];

erroTupla

Enum

Enum é um tipo de dados que não existe no JavaScript mas foi adicionado ao TypScript com o intuito de fornecer nomes mais amigáveis a conjuntos de valores numéricos. Enums são muito comuns em linguagens como Java e C#.

enum Color {Red, Green, Blue, Yellow};
enum AnotherColor {Red = 1, Green = 2, Blue = 4, Yellow};

Se imprimirmos o enum Color, veremos que os valores de Red será 0, Green será 1, Blue 2 e Yellow será 3.

Assim como se imprimirmos o enum AnotherColor, Red será 1, Green 2, Blue 4 e Yellow que não foi atribuído valor será 5.

Tipos especiais

Temos também outros dois tipos de dados o any e o void.

Any

Any é um tipo de dados muito utilizado para quem está migrando do JavaScript para o TypeScript ou quem está recebendo os dados de uma outra biblioteca e não sabe seu valor.

E ele literalmente quer dizer qualquer um. Então declarando uma variável como o tipo any podemos atribuir qualquer valor para ela.

let qualquer: any;
qualquer = 'String';
qualquer = 4;
qualquer = true;

Void

O tipo void é muito usado junto com funções, serve para dizer que o valor é vazio, não é atribuído nada.

function print(msg: string ): void {
  console.log(`Função sem retorno: ${msg}`);
}

print('Escreve algo na tela');

Obs: Declarar variáveis do tipo void não é útil porque você só pode atribuir undefined ou null a elas.

 

TypeScript – Primeiros passos

JavaScript é sem dúvidas uma das linguagens de programação mais utilizadas no mundo, tudo por causa dos seus recursos e da sua grande flexibilidade.

Podemos programar client-side, server-side, mobile, games, etc. Tudo isso usando apenas o JavaScript.

A linguagem é fácil, simples e de rápida aprendizagem, mas contém um problema que se agrava quando desenvolvemos aplicações complexas e robustas.

Diferente de outras linguagens como Java, C# e outras fortemente tipadas, JavaScript não possui tipos, classes e aquela velha e famosa orientação a objetos que tanto vimos no segundo, terceiro e quartos semestres da faculdade, mesmo com a implementação do ES6, tudo é transpilado para JavaScript puro.

ES6:

class Veiculo {
    constructor(ano, modelo, cor) {
        this.ano = ano;
        this.modelo = modelo;
        this.cor = cor;
    }
}

JavaScript puro:

"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Veiculo = function Veiculo(ano, modelo, cor) {
  _classCallCheck(this, Veiculo);

  this.ano = ano;
  this.modelo = modelo;
  this.cor = cor;
};

Outro problema também são os programadores que migram de linguagem fortemente tipada para o JavaScript sentem uma dificuldade de adaptação.

Pensando nisso um engenheiro da Microsoft e sua equipe de desenvolvimento resolveram criar o TypeScript.

Este engenheiro não é ninguém menos que Anders Hejlsberg, que esteve envolvido na criação e no desenvolvimento do Turbo Pascal e do Delphi quando trabalhava para a Borland. E depois foi um dos desenvolvedores do C# e da plataforma .Net na Microsoft

Ok, mas o que é o TypeScript?

TypeScript é um superconjunto de JavaScript desenvolvido pela Microsoft que adiciona tipagem e alguns outros recursos a linguagem.

O TypeScript é projetado para o desenvolvimento de grandes aplicativos e transpilado para JavaScript. Como o TypeScript é um superconjunto de JavaScript, os programas JavaScript existentes também são programas TypeScript válidos.

O TypeScript pode ser usado para desenvolver aplicativos JavaScript que executam tanto do lado do cliente quanto do lado do servidor(Node.js).

O TypeScript suporta arquivos de definição que podem conter informações de tipo de bibliotecas JavaScript existentes, assim como os arquivos de cabeçalho C ++ podem descrever a estrutura dos arquivos de objetos existentes. Isso permite que outros programas usem os valores definidos nos arquivos como se fossem entidades TypeScript digitadas estaticamente.

Existem pacotes de terceiros para bibliotecas populares, como jQuery, MongoDB e D3.js. Pacotes TypeScript para os módulos básicos do Node.js também estão disponíveis, permitindo o desenvolvimento de programas Node.js dentro do TypeScript.

Instalando o TypeScript.

Para instalar o TypeScritp é fácil, basta ter o node instalado no seu computador e instalar com o npm globalmente.

npm install -g typescript

Após instalado vamos criar o primeiro código utilizando TypeScript.

Criando um código com TypeScript.

Como sempre devido a “Maldição do Hello World” vamos criar nosso primeiro código imprimindo no console o Hello World. Mas primeiro vamos criar uma estrutura de pastas que será utilizada para todos os nossos exemplos.

TypeScript |
           |-> src |
                   |-> HelloWorld |
                                  |-> HelloWorld.ts

Vamos criar uma pasta TypeScript e dentro dela uma pasta src, dentro desta pasta src outra pasta que será o nome do exemplo que criaremos e dentro dela finalmente o arquivo .ts

Esta estrutura é necessária, pois iremos configurar o Visual Studio Code para transpilar o código TypeScript para JavaScript automaticamente.

HelloWorld.ts

const saudacao: string = 'Hello World!';

console.log(saudacao);

Acima é um exemplo de uma constante saudação declarada como um tipo string e atribuída o valor de ‘Hello World!’, depois seu valor é exibido no console.

Para transformarmos este código em JavaScript precisamos utilizar o seguinte comando:

tsc HelloWorld.ts

E isso nos gerará um código assim:

var saudacao = 'Hello World!';

console.log(saudacao);

Porém cada vez que alterarmos o código precisaremos rodar o comando novamente, isso pode e provavelmente irá nos causar dor de cabeça. Mas para que isso não aconteça vamos configurar o Visual Studio Code fazendo que este processo seja automático.

Criando o tsconfig.json

Dentro da pasta TypeScript e fora da pasta src crie um arquivo chamado tsconfig.json e nele digite:

{
  //Opções de compilação
  "compilerOptions": {
    //Qual a versão do ecmascript será compilada
    "target": "es5",
    //Geração de módulo padrão
    "module": "commonjs",
    //Criará um source map
    "sourceMap": true,
    //Salvar e gerar automaticamente o arquivo javascript
    "watch": true
  },
  //Quais pastas serão transpiladas
  "include": [
    "src/**/*"
  ]
}

Este arquivo será responsável por compilar o TypeScript para JavaScript e também toda e qualquer alteração que for feita no arquivo TypeScript ele automaticamente recompilará.

Feito isso temos que configurar o Visual Studio Code para que ele rode o processo. Então vá em :

Visualizar -> Paleta de comando -> Executar tarefa de compilação -> TypScript\tsconfig.json

E pronto agora toda vez que você alterar o arquivo.ts o arquivo.js será atualizado e um arquivo.js.map será criado.

Quando e onde utilizar o TypeScript?

Podemos utilizar o TypeScript quando quisermos uma maior segurança nas nossas aplicações, quando precisarmos que elas sejam fortemente tipadas, com sólidos conceitos de orientação à objeto e quando tivermos programadores de outras linguagens como C# e Java se aventurando pelo JavaScript.

Várias bibliotecas e frameworks já utilizam TypeScript ou dão suporte a ele como :

  • React
  • React Native
  • Angular
  • Vue
  • Node
  • Knockout
  • Dojo 2
  • Glimmer
  • WebChat
  • ASP.NET core

Este artigo foi mais para conhecermos o TypeScript e sua configuração inicial para que possamos nos próximos colocar a mão na massa e conhecer tudo o que ele pode nos oferecer.

Referências e links:

Site oficial do TypeScript

Wikipedia TypeScript

Wikipedia Anders Hejlsberg

Twitter.com @typescriptlang

GitHub Microsoft/TypeScript

 

React – Componentes de Classe e Funcionais

Como vimos nos posts anteriores, React – Primeiros Passos e React – Criando o primeiro componente, react é uma biblioteca que controla os componentes da nossa aplicação web e estes componentes podem ser divididos da seguinte forma:

  • Componentes de classe
  • Componentes funcionais

Componentes de classe

Os componentes de classe na verdade não são específicos do react, eles são uma implementação que surgiu no ES6.

Classe nada mais é que uma função especial na qual você pode definir utilizando a palavra reservada class.

Um componente de classe no react sempre extende o Component, da biblioteca.

Vamos entender melhor criando um exemplo.

Para criarmos um componente vamos utilizar o create-react-app.

create-react-app blog-component

Caso não tenha instalado leia este post.

Depois de criado o projeto, basta navegar até ele.

cd blog-component

Dentro da pasta iniciar o projeto.

npm start

Ou se tiver com o yarn instalado utilizar o comando

yarn start

localhost-react

Podemos apagar tudo dentro da pasta src, menos o arquivo index.js e vamos criar uma pasta components dentro da pasta src e um arquivo App.js dentro da pasta components.

Temos também que alterar o index.js para que ele não mais utilize as referências dos arquivos que apagamos.

O arquivo index.js ficará assim:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';

ReactDOM.render(<App />, document.getElementById('root'));

Agora faremos no nosso componente App.js um componente de classe.

 

import React, { Component } from 'react'
export default class App extends Component {
  render() {
    return (
      <div>
        <h1>Hello Word!</h1>
      </div>
    )
  }
}

Pronto, como declaramos nosso componente como classe já o torna um certo?

Errado.

Uma das coisas que o site do react diz é que um componente de classe só será utilizado quando este componente precisar controlar o estado, senão poderemos utilizar um componente funcional.

Componente Funcional.

Os componentes funcionais são literalmente funções javaScript, eles recebem um único argumento de objeto “props” e retornam um elemento react válido.

Este elementos são chamados de componente ou elementos burros, pois eles não tratam o state.

Geralmente utilizamos estes elementos para, mostrar dados, mostrar imagens, criar listas, aplicar estilos entre outros.

Em contrapartida utilizamos o componente de classe quando precisamos buscar algo em uma api, temos que controlar o estado deste componente, quando chamamos outros componentes e em casos que precisamos de algo mais complexo.

Um componente funcional seria mais ou menos assim.

Vamos criar um componente chamado Title.js na pasta componets. E vamos digitar o seguinte código.

import React from 'react';
export default (props) => {
  return (
    <div>
      <h1>{props.title}</h1>
    </div>
  )
}

Como iremos apenas exibir um título neste componente não necessariamente precisa ser um componente de classe, pois não controla nenhum estado, apenas recebe uma propriedade e a exibe ela na tela.

 

Basta importar no App.js e colocar no lugar da tag h1 que utilizávamos para exibir a mensagem na tela.

import React, { Component } from 'react';
import Title from './Title';

export default class App extends Component {
  render() {
    return (
      <div>
        <Title title='Hello World'/>
      </div>
    )
  }
}

E então passamos como parâmetro o title, que será o mesmo exibido em props.title.

Um exemplo mais completo.

Imagine que você tenha uma lista e dentro desta lista você precise aplicar um estilo para cada elemento desta lista, você pode usar um componente de função chamando outro componente de função, pois você não irá alterar o estado em nenhum deles.

Primeiro vamos alterar o App.js para que ele receba uma lista no state contendo vários cursos.

Depois vamos importar um componente que iremos criar chamado CoursesList.js.

import React, { Component } from 'react';
import Title from './Title';
import CoursesList from './CoursesList';

export default class App extends Component {
    state = {
        courses: [
            "React", 
            "React Native",
            "JavaScript",
            "Node"
        ]
    }
    render() {
        return (
            <div>
                <Title title='Hello World'/>
                <CoursesList list={this.state.courses}/>
            </div>
        )
    }
}

Abaixo do componente Title que já estava no nosso código, passamos o componente CoursesList que irá receber um parâmetro list com o valor de this.state.courses.

CoursesList.js

import React from 'react';
import Course from './Course';

export default (props) => {
  return (
    <div>
      {props.list.map(course => <Course title={course}/>)}
    </div>
  )
}

O componente CoursesList, embora vá chamar outro componente ele não precisa ser um componente de classe, pois ele não tem um estado para manipular, ele apenas faz um map() em uma lista que ele recebeu via propriedade(props) e passa para o componente Course através da propriedade title estes dados para serem tratados.

Course.js

import React from 'react';

export default (props) => {
  return (
    <div>
      <p style={{ color: 'red' }}>{props.title}</p>
    </div>
  )
}

Por fim o componente Course.js, este componente também é um “componente burro” ou funcional.

Ele é mais um componente que não trata o estado, apenas recebe um parâmetro, aplica um estilo, definindo a cor vermelha para os cursos e mostra na tela.

Referências

https://reactjs.org/docs/components-and-props.html