ElasticSearch com PHP não é magia; é tecnologia!

ElasticSearch
ElasticSearch

Já não é de hoje que a ciência e a tecnologia desmistificaram a magia, então vamos entender um pouco o nosso assunto.

Há alguns anos começaram a aparecer em diversos sites grandes a famosa “busca viva”. De início, parecia ser algo mágico, mas depois foi descoberto que na maioria das vezes o cara por trás disso era o nosso querido ElasticSearch. Ele nada mais é do que um servidor de buscas escrito em Java e baseado no Apache Lucene. Hoje ele e usado por empresas como GitHub, Facebook, TheGuardian, Globo.com e outras…

Quando pensamos no uso do ElasticSearch com PHP não pensamos na busca viva, pois essa fica por conta do Javascript. No PHP nós trabalhamos com a indexação de dados. Uma vez que o ElasticSearch basicamente é um banco de dados, então nossos dados de busca precisam ser indexados nele de alguma maneira, e a maneira mais fácil de fazer isso é com um backend que “escute” suas ações e salve as no ElasticSearch.

Vamos usar o client oficial do ElasticSearch para PHP, o elasticsearch-php. Ele é bem completo, mas tem uma documentação bem incompleta (coisa comum no mundo de hoje).

Para nosso artigo, eu criei uma Factory simples e também um exemplo. Vamos por a mão na massa então.

Instalando o ElasticSearch

A primeira coisa a fazer e instalar o ElasticSearch. Depois, o elasticsearch-php usando o composer. Aqui esta a dependência:

1{
2    "require": {
3        "elasticsearch/elasticsearch": "~1.0"
4    }
5}

Após instalado, podem criar uma factory como a minha que está aqui.

Vamos entender essa Factory, então… Basicamente ela vai criar uma instância do elasticsearch client php para que possamos indexar, buscar e fazer update nos documents dentro do elasticsearch.

O elasticsearch se divide em index (índice), type (tipo) e depois document. O índice é usado, por exemplo, como o nome do meu banco de dados. Já o tipo seria minha tabela e o document são nossos dados.

Bom, a nossa factory se inicia com métodos privados que vamos usar logo e também um construtor na linha :16.

1public function __construct($index){
2        $this->index = $index;
3        $this->client = new Elasticsearch\Client();
4
5        return $this;
6    }

Nosso construtor recebe um index obrigatoriamente, pois independente da nossa ação precisamos de um índice setado. Ela também inicia uma instância do nosso elasticsearch client. Também nessa factory, temos os getters e os setters para acessarmos nossas variáveis privadas.

Bom, então nos já temos o construtor, os getters e os setters. Agora precisamos criar os métodos para indexar e buscar dados do nosso elasticsearch.

Na linha :25 temos o método create:

1public function create()
2    {
3        $params['index'] = $this->index;
4        $params['type'] = $this->type;
5        $params['body'] = $this->data;
6        
7        return $this->client->index($params);
8    }

Nosso método create tem como um índice um tipo e um body. Com esses dados setados, nós vamos chamar o index do elasticsearch cliente e passar esses parâmetros pra ele indexar – vejam que eu não passei um “id”, então ele vai criar um id automaticamente para nós.

Na pratica ficaria assim então:

1$ef = new ElasticFactory('my_project');
2$ef->setType('users');
3
4$data = [
5    'name'=>'Waldemar Neto',
6    'age'=>24,
7    'email'=>'waldemarnt@outlook.com',
8    'born'=>'1990/01/23'
9];
10
11$ef->setData($data);
12$ef->create();

Pronto! Populamos nossos dados e mandamos salvar (notem uma coisa: nosso campo ‘born” e uma data está no padrão yyyy/mm/dd, que o elasticsearch mapeara o tipo dele como date e poderemos usar filtros de data nele no futuro.

Agora na linha :35 eu tenho o método update que é semelhante ao create, porém tem o id e o [‘body’][‘doc’]:

1public function update()
2    {
3        $params['index'] = $this->index;
4        $params['type'] = $this->type;
5        $params['body'][‘doc’] = $this->data;
6        $params['id'] = $this->id;
7
8        return $this->client->index($params);
9    }

Aqui faríamos o mesmo que acima, sá que setariámos o id usando o $ef->setId(<id>). É comum setarmos o id, pois em projetos normais indexamos dados que já usamos no banco de dados, por exemplo, e eles já têm um id.

Queries

Agora vamos ver como funcionam as buscas. Na linha :46 da minha factory criei o seguinte método:

1public function find($query)
2    {  
3        if($this->type){
4            $params['type'] = $this->type;
5        }
6
7        $params['body']['query'] = $query;
8        $params['size'] = $this->size;
9
10        return $this->client->search($params);
11    }

Esse método vai receber uma query e vai chamar o search do elasticsearch client passando os parâmetros da busca.

As queries do elasticsearch normal são com objetos json. A nossa, aqui no php é com arrays mesmo; depois o client transforma essa request em json.

Então vamos fazer uma Match Query buscando por idade:

1$ef = new ElasticFactory('my_project');
2$ef->setType('users');
3$ef->setSize(100);
4$matchQuery=[
5    'match'=> [
6        'age'=>24
7    ]
8];
9
10$matchData = $ef->find($matchQuery);
11if(isset($matchData['hits']['hits'])){
12    foreach ($matchData['hits']['hits'] as $key => $hit) {
13        echo $hit['_source']['name'].'<br/>';
14    }
15}

Vamos entender essa query agora. Primeiro, após instanciar eu setei o size como 100 (pois por padrao, o elasticsearch trabalha com size 10, ou seja mesmo que ele encontre 1000 retornos, ele retornara 10). Depois eu criei um array passando o nome da query que é match (podemos encontrar informações sobre queries na documentação do elasticsearch). Depois eu chamei o meu método find e passei pra ele nosso array com os parâmetros da busca. Agora é so testar o retorno para ver se ele achou algo.

Por padrão, ele sempre nos retornara um array hits com outro array hits dentro e com outro array chamado _source. Então, pra validar se retornou, usamos isset($retorno[‘hits’][‘hits’][‘_source’]) se der true é porque ele nos retornou dados.

Agora vamos ver buscas mais complexas:

1$filter = array();
2$filter['term']['name'] = 'waldemar';
3
4$query = array();
5$query['match']['age'] = 24;
6
7$filteredQuery = [
8    'filtered'=>[
9        'filter'=>$filter,
10        'query'=>$query
11    ]
12];
13
14
15$filteredData = $ef->find($filteredQuery);
16
17if(isset($filteredData['hits']['hits'])){
18    foreach ($filteredData['hits']['hits'] as $key => $hit) {
19        echo $hit['_source']['name'].'<br/>';
20    }
21}

 

Essa será uma filtered query, que é quem entende que para fazer a query, ela tem que atender aos filters que ela possui. Então, primeiro criei um array $filter e usei um term filter (também disponível na documentação do elasticsearch) o meu filter é por term e o campo que eu quero é o nome que possua “waldemar” como valor. A minha query vai ser uma query do tipo match que eu quero trazer as idades(age) de valor 24.

Beleza com esses dois arrays agora eu crio o array da filtered query e passo pra ele o meu array de filter com meu filtro e na query passo o array da query. Pronto! Agora e só passar isso para o find e ver se nos retornou dados.

Agora vamos um pouco mais além nas queries e vamos usar um filter do tipo range, que e muito usado em datas ou em escalas de distância, por exemplo:

1$filter = array();
2$filter['range']['born'] =[
3    'gte'=>'1990/01/20',
4    'lte'=>'1990/01/24'
5];
6
7$query = array();
8$query['match_all'][] = [];
9
10$filteredByBorn = [
11    'filtered'=>[
12        'filter'=>$filter,
13        'query'=>$query
14    ]
15];
16
17
18$filteredBorn = $ef->find($filteredByBorn);
19
20if(isset($filteredBorn['hits']['hits'])){
21    foreach ($filteredBorn['hits']['hits'] as $key => $hit) {
22        echo $hit['_source']['name'].'<br/>';
23    }
24}

A nossa query dessa vez será uma match_all, que traz todos os dados, e vamos filtrar pelas datas usando o range filter, lembrando que para funcionar o range filter o campo no qual estamos buscando precisa ser do tipo date.

Bom galera, espero que tenham gostado. É um exemplo bem básico, mas já dá pra ter uma ideia de por onde começar com essa fantástica ferramenta que é o elasticsearch, que está ganhando o mercado.

——-

Artigo de Waldemar Neto, publicado originalmente no iMasters.

O design responsivo elimina a necessidade de um app?

Design responsivo
Design responsivo

Enquanto alguns usuários se beneficiam dos aplicativos, muitos podem encontrar na construção do site com design responsivo uma forma eficiente para servir seus clientes em smartphones e tablets.

Não é segredo pra ninguém que só se fala em mobile. De acordo com a Forrester Research Inc., 29% das vendas online deste ano (com exceção de comida e viagem) serão feitas a partir de um smartphone ou tablet. O mercado não pode ignorar esses números. O tempo para capitalizar no m-commerce é agora.

Para as empresas de hoje, a questão não é se elas vão abraçar o mobile, e sim como farão isso. É natural assumir que os aplicativos são necessários para alcançar a audiência mobile. De fato, há alguns anos, os apps de mídia prometiam a melhor experiência mobile para os usuários. Recentemente, porém, o advento do design responsivo e outras tecnologias avançadas de web mudaram o jogo do mobile. Hoje, apps podem não ser necessariamente a melhor opção para criar a experiência top no mobile.

Apps possuem algumas limitações. Por exemplo, eles podem geralmente criar barreiras para as vendas porque requerem download, o que implica um passo a mais para o consumidor em potencial. Compradores casuais podem não querer se comprometer tanto a ponto de baixar o aplicativo, especialmente se eles estão à procura de um item em particular e não se importam com o local onde vão encontrá-lo. Os apps para mobile podem funcionar bem para aqueles clientes recorrentes e fiéis à marca que só compram em determinados locais.

Além disso, a manutenção do aplicativo pode ser um problema. Com as múltiplas plataformas e sistemas operacionais a considerar, produzir um app que seja útil para a massa, na verdade, requer desenvolver algumas versões diferentes do app para atender a várias necessidades tecnológicas. Isso significa mais investimento em tempo e recursos, não apenas durante o desenvolvimento inicial do app, mas toda vez que ele precisa ser atualizado. Uma alternativa é optar pelo design responsivo no site para direcionar as necessidades mobile, o que significa que as empresas podem colocar o tempo e recursos em um website e ter a garantia de que todas as atualizações vão refletir instantaneamente nos dispositivos e plataformas.

Com as opções tecnológicas disponíveis hoje, a maioria das companhias pensa duas vezes em investir em desenvolvimento de aplicativos. Porém, existem exceções. Grandes varejistas como a Amazon são beneficiados com os aplicativos por conta da quantidade e da diversidade de produtos em suas lojas. Para marcas que oferecem muito conteúdo, como blogs, vídeos e indústria de notícias, como parte de sua experiência online, também pode valer a pena manter um app.

Para a maioria das empresas, melhorar a experiência do cliente é reduzir as dificuldades no fluxo de compra e, para muitos consumidores, baixar um app é um obstáculo. Não há dúvida de que o mobile é uma preocupação importante hoje no varejo online. O boom dos aplicativos é compreensível, mas eles nem sempre podem ser a melhor opção para alguns varejistas que precisam oferecer um nível alto de experiência aos seus clientes.

—–

Artigo de Rory Dennis, publicado originalmente no iMasters.

Motivos que podem levar o cliente a cancelar seus e-mails

Cancelamento de e-mail marketing
O excesso de mensagens pode ser um dos motivos para o cancelamento

Solicitações de cancelamento do recebimento de e-mail marketing não são boas notícias. Há diversas razões para que as pessoas solicitem o descadastramento (opt-out) de uma lista, e algumas delas podem ser criados por quem envia! Uma taxa alta pode indicar que alguma coisa está bem errada nas suas campanhas.

Mas calma! Vamos analisar, nas próximas linhas, alguns dos principais motivos para que o leitor não queira mais ver seu e-mail marketing.

 

Frequência de envios

Uma das coisas mais irritantes numa campanha de e-mail marketing é ser bombardeado por inúmeras mensagens. Imagine que o leitor recebe não só a sua mensagem, mas também a de diversas outras empresas. Ao final do dia, todas essas campanhas recebidas provavelmente vão para o lixo, porque não há tempo para lê-las. Elas ainda podem parar no descadastro ou, pior ainda, reportadas como spam.

Mas se você raramente envia campanhas para seus clientes, eles não irão se importar em pedir a exclusão da sua lista. Sim, é difícil achar uma linha tênue entre uma quantidade de envios de e-mails que não seja intrusivo ou desinteressante. Vale o bom senso: se você tem muitas novidades, que contá-las em um único e-mail, ao invés de mandar um e-mail para cada novo acontecimento? Faça uma newsletter semanal, por exemplo, com a seleção das melhores ofertas ou notícias. Ou envie sempre que houver promoção, ou uma campanha especial.

É difícil arriscar um número ideal, mas pense você mesmo: quantas vezes eu poderia receber uma newsletter sem que ficasse intrusivo?

 

Conteúdo irrelevante

Seu cliente entrou no seu site e comprou um fogão, por exemplo. Ele também se cadastrou para receber suas campanhas de e-mail marketing. E a primeira mensagem que ele recebe logo após o cadastro é… uma oferta de fogões!

Provavelmente, este cliente não vai querer comprar um fogão tão cedo. Mas ele pode se interessar em uma geladeira, ou em panelas novas. Por isso é importante trabalhar a segmentação da sua base, o máximo possível. Mantenha o interesse dele nas suas mensagens, concedendo brindes, sorteios e promoções exclusivas, por exemplo.

 

Mudança de canal

Nem sempre o cliente te abandona totalmente. Se você disponibiliza outros canais, como redes sociais, pode ser que ele tenha optado em seguir a marca por lá. Essa é uma tendência principalmente dos clientes mais jovens, que preferem estes canais para se relacionar.

Por isso mesmo o conteúdo deve ser bastante atraente, e ter um diferencial com relação aos outros canais. E fala seu público perceber as vantagens de estar cadastrado na sua lista: conte a ele que aquele canal é especial e o motivo.

 

Mesmo com todo meu esforço, o cliente quis cancelar

E a vontade dele deve ser respeitada. Não dificulte a exclusão do e-mail da sua lista, ou não retire o nome dele e continue enviando as mensagens. Além da irritação virtual, isso pode gerar uma campanha negativa da sua marca junto às redes do cliente.

O máximo que se pode fazer, nestes casos é colocar um pequeno questionário na tela de cancelamento perguntando o motivo. Isso servirá para que você veja onde está errando em suas ações, e acertar sua campanha para que ninguém a cancele mais.

Os seis maiores mitos de SEO

SEO
SEO

As estratégias de SEO são dinâmicas se considerarmos que os algoritmos dos motores de busca passam por constantes atualizações de tempos em tempos. A título de exemplo, podemos citar o Google Panda 4.0, que foi o último “update” do buscador mais famoso do mundo e trouxe diversas mudanças nas perspectivas dos especialistas do SEO.

Esse dinamismo cria constantemente diversas novidades e, na mesma proporção, os mitos. Sim, aquelas ideias equivocadas sobre otimização que ganham popularidade na web, mas que não possuem o mínimo embasamento verídico e sequer foram testadas por especialistas.

Acompanhe, a seguir, seis mitos do SEO que podem confundi-lo:

1- SEO é igual a ranking nas redes sociais

Não é bem assim. Evidentemente, um engajamento nas redes sociais contribuirá para a construção de autoridade da marca e, em consequência, classificações elevadas de usuários sobre sua empresa na rede. Porém, existe uma enorme diferença entre correlação e causalidade.

O acúmulo de retweets e curtidas, por exemplo, não conseguirá mover seu site ou página para as primeiras colocações dos buscadores.

Ou seja: não é a publicidade nas redes sociais que irá causar as melhores posições no Google. Isso porque o algoritmo não considera sua autoridade nesses ambientes de interação online, mas principalmente outros fatores.

2- SEO é apenas links e palavras-chave

Trata-se de um mito construído pela própria evolução do SEO, afinal, até pouco tempo, as principais estratégias para ranqueamento eram fundamentadas em construção de links e palavras-chave.

Ambos continuam sendo táticas essenciais para um bom SEO. No entanto, a otimização não é composta apenas de métodos simples, e os buscadores têm relevado cada vez mais a real autoridade do seu negócio, tanto em meio físico quanto virtual. Em suma, isso significa que quanto maior for o investimento em sua marca e na construção do seu negócio, melhor será a sua posição nas pesquisas.

3- SEO Técnico está morto

Os mecanismos de busca estão valorizando o conteúdo e o contexto no qual as palavras-chaves são inseridas. Sim, é fato. Mas isso não quer dizer que táticas como otimização de URLs, metas tag, redirecionamento e outras estratégias de SEO técnicos estejam “mortas”.

É extremamente importante que os especialistas compreendam as noções da parte técnica do SEO para incluí-las durante a otimização de um site, blog ou e-commerce para conseguir melhores resultados.

4- Implementei todas as estratégias. SEO finalizado

Não, não se engane. Na realidade, a otimização nunca está acabada, já que, como mencionamos logo no início, o SEO é dinâmico.

Em uma analogia simples, é como uma estrada repleta de curvas, e é necessário estar constantemente atento às mudanças, melhorando o que já foi feito e implementando novas táticas quando os algoritmos sofrem “updates”.

5- Pagar AdWords garante melhor ranqueamento

Primeiramente, é fundamental lembrar que otimização não é o mesmo que links patrocinados. Enquanto a primeira é trabalhada dentro da busca orgânica – os resultados naturais advindos de pesquisas dos internautas –, o segundo é um serviço de publicidade do Google que não tem nenhuma relação com o SEO.

Portanto, evidentemente, não são comparáveis. Com o AdWords, sua marca será exibida como um anúncio na lista do buscador, mas não será um resultado orgânico.

6- As estratégias para mensurar resultados de SEO nunca mudam

Uma única forma de mensuração não deve existir no cenário de resultados do SEO. Toda estratégia para medir deve refletir dados consistentes, trazendo informações substanciais sobre o que deve ser ajustado, modificado ou recuperado na otimização.

Mas, para que isso seja possível, se acomodar somente em uma estratégia de mensuração não é aconselhável. Novamente, o SEO muda de tempos em tempos, e isso inclui as ferramentas para análise de resultados.

O ideal é fazer estudos aprofundados – e isso inclui estatísticas e análises de comportamento dos internautas –, buscando identificar todas as variáveis do conjunto estratégico de SEO implementado.

—–

Artigo de Hildebrando Trannin, publicado originalmente no iMasters.

Gerenciando dependências com RequireJS

Imagem ilustrativa
Imagem ilustrativa

RequireJS é uma tecnologia desenvolvida de JavaScript para JavaScript cujo propósito é ser a solução das dependências da sua aplicação ou site.

Para dar vida ao cenário, entenda que quando você usa jQuery, por exemplo, você naturalmente tem uma dependência. O controle de dependências não se limita somente à biblioteca de terceiros, porque caso você mesmo tenha criado um script que dependa de outro também seu, o RequireJS também consegue esse poder de gerenciamento para você.

Mas afinal, por que controlar dependências?

Isso torna a sua aplicação mais flexível; mais modular. Às vezes nós temos um script específico para uma página que irá fazer uma simples animação quando passarmos o mouse sobre o menu. Essa animação, por sua vez, depende do $.addClass(); do jQuery – e aí? Como você faz?

Vamos detalhar um pouco mais a necessidade; você possui três páginas, são elas:

  • index.html para a sua página principal;
  • contact.html para a sua página de contato;
  • about.html para a sua página de informações sobre você ou sua empresa.

Elas são simples e compartilham vários recursos entre si. Entretanto, a contact.html possui um formulário de contato e você irá, por fim, usar o jQuery Validation para fazer a sanitização dos seus campos.

Vamos, então, filosofar:

  • Quem precisa do quê? – A página contact.html precisa do jQuery Validation.
  • O jQuery Validation depende de alguém? Se sim, de quem? – Sim, ele depende do jQuery em si.
  • Contact.html seria, então, dependente do jQuery Vaildation e, consequentemente, do jQuery? – Sim.

Ainda não percebeu o “xis” da questão? index.html e about.html não precisam do jQuery Validation e, quem sabe, nem do jQuery em si. É um desperdício imenso injetarmos código desnecessário nessas páginas – mais carregamento, mais dependências por demanda para se preocupar e etc.

Começando

O RequireJS não é um gerenciador de dependências qualquer. Ele é um AMD – Asynchronous Module Definition -, o que significa que suas dependências não são carregadas por meio de um processo síncrono, mas sim assíncrono. Em outras palavras, você requisita e define módulos sob demanda, quando e onde precisar.

Para começarmos de fato, tenha em mente que criaremos um aplicativo do zero com uma boa estrutura de iniciação. Para irmos além, o primeiro passo é fazer o download da última versão – minificada ou não – do RequireJS. Depois, veja a estrutura da nossa aplicação:

1app 
2|--index.html
3`--assets
4   `--js
5      |--main.js
6      `--libs
7         |--jquery.2-1-1.min.js
8         `--require.js

 

  • app/ é a pasta raiz
  • app/index.html/ é a página principal
  • app/assets/ é a pasta com o material da sua aplicação
  • app/assets/js/ é a pasta que comportará o nosso material JavaScript
  • app/assets/js/main.js/ é onde configuraremos os atributos principais do RequireJS
  • app/assets/js/libs/ é a pasta de bibliotecas de terceiros.

Se você levantou essa estrutura, então mãos ao code!

No index.html, dentro do elemento <head></head> , vamos invocar o app/assets/js/libs/require.js e o seu configurador, app/assets/js/main.js/:

1<script data-main="assets/js/main"
src="assets/js/libs/require.js"></script>

Note que estamos matando dois coelhos numa cajadada só – quando você solicita pelo require.js, ele busca pelo seu configurador através do atributo data-main do mesmo elemento invocador (<script></script>). O caminho de diretório é o mesmo que o utilizado em src, mas você pode omitir a extensão .js porque o RequireJS traduz isso para você.

Agora, no main.js, teremos o seguinte script:

1require.config({ 
2  name: 'app',
3  baseUrl: 'assets/js',
4  paths: {
5    'jquery': 'libs/jquery-2.1.1.min'
6  }
7});
8
9require(['jquery'], function ($) { 
10  $('body').append('hello');
11});

O require.config é o objeto em escopo global que o RequireJS manipula e essas são as suas propriedades:

  • name: o nome da sua aplicação;
  • baseUrl: a pasta raíz dos seus scripts JavaScript – note que eles serão sempre relativos;
  • paths: o seu “dicionário” de importação de bibliotecas;
  • ‘jquery’: o nome da biblioteca a ser importada
  • ‘libs/jquery-2.1.1.min’: o arquivo referente à biblioteca – note que, como já falado, o caminho é relativo ao baseUrl, ou seja, libs está dentro de assets/js, o que significa que você pode omitir o caminho já outrora proposto.

Depois da primeira camada de código, temos este fragmento:

1require(['jquery'], function ($) {
2$('body').append('hello');
3});

Que significa que você está requerendo a biblioteca jquery (mesmo nome proposto em paths no main.js) e está assinando ela ao caractere “$”. Então, sempre que você for utilizar um recurso dela, ou seja, do jQuery, resta você chamar pelo cifrão e voi là! Você conseguirá executar os seus códigos jQuery normalmente.

Basicamente, você conseguiu levantar uma aplicação com um mecanismo básico de dependências. O RequireJS vai muito além do que abordei aqui, me vamos abordar mais assuntos dentro disso futuramente.

—–

Artigo de Guilherme Oderdenge, publicado originalmente no iMasters.

É imprescindível que você aprenda programação funcional com Java 8?

 

Java
Java 8

Outro dia resolvi dar uma olhada no Java 8 e, de cara, me deparei com “Java 8 In Action“, publicado por Manning. A primeira coisa que me surpreendeu é como uma das proposições de venda exclusivas do Java 8 é a programação funcional; as funções são, agora, variáveis de primeira classe, você pode passá-las pelo seu código como se fosse um int ou uma String. Essa é uma grande mudança.

Parece que as linguagens funcionais se tornaram mais populares nos últimos anos e há inúmeras para se escolher. Exemplos de linguagens de programação modernas incluem Clojure, JavaScript, Scala, e até mesmo Erlang, inventada na década de 1980, dando um ar retrô na nossa lista.

Então, por que existe essa mudança de direção? Você pode até achar várias razões, mas vamos começar com a premissa de que a indústria de melhores práticas muda ao longo do tempo e até mesmo as linguagens mais populares um dia vão cair em desuso. Imagino que se você ainda é jovem o suficiente, um dia vai olhar para trás e falar: “Lembra quando costumávamos usar o Java?” Antes de verificar o porquê da existência dessa mudança, vamos refletir sobre como chegamos aqui dando uma volta na década de 1980…

Segundo a Wikipedia, o PC da IBM foi lançado em 12 de agosto de 1981. Os primeiros PCs foram entregues com BASIC (1), apesar de os “caras legais” logo terem se cansado disso e mudaram para Turbo Pascal da Borland. A novidade do Turbo Pascal não durou muito tempo, porque a Microsoft comprou a Microsoft C (ou MSC), que logo se tornou, de fato, o padrão. Foi legal porque se você fosse inteligente poderia acessar o hardware diretamente, usando int 21H, int 10H e int 14h e outros, e se me lembro qual interrupção fez o quê, então você é velho como eu (2)…

Existiram outros computadores antes do PC da IBM, incluindo Apple II, Commodore Pet etc., mas o PC da IBM era um PC “adulto” para aplicações voltadas para negócios. Eu me lembro de tentar comprar um para um projeto que fiz em 1985, que custou milhares de libras e você não conseguia um nem por amor nem por dinheiro, todo mundo queria um; no entanto, eu discordo.

No final de 1980, veio o Microsoft Windows SDK, baseado em C, que está por aí desde Windows 1 foi construído (aparentemente a Microsoft não usou janelas sobrepostas no Windows 1, porque copiou a Macintosh da Apple e provavelmente violou suas patentes – mesmo que a Apple tenha, supostamente, roubado a ideia para o Mac da Xerox Parc; se isso é verdade, eu não eu não tenho como confirmar). O SDK realmente decolou no Windows 2, apresentando ao mundo o callback, programação baseada em mensagens; uma ideia que eles supostamente roubaram do X-Windows e Motif no Unix.

Lá pelos meados dos anos 90, linguagens se tornaram orientadas a objeto; classes foram inventadas para unir métodos e dados, introduzindo os conceitos de ocultação de dados e encapsulamento. ‘C’ se tornou ‘C++’ e se você usava o Windows SDK nessa época, então você migrou para Microsoft Foundation Classes; um wrapper OO ao redor do SDK. Essa mudança foi vista como uma coisa boa. Um grande problema com as antigas funções baseadas em linguagens era que você poderia alocar variáveis globais em qualquer lugar em sua base de código e alterá-las usando qualquer função a qualquer momento. Isso, obviamente, causou grandes estragos em vários sistemas, já que você não podia ter certeza de que mudando o estado de uma variável global não introduziria um bug num cantinho escondidinho do seu aplicativo. O outro grande problema com a linguagem C era que você era responsável pela alocação e desalocação de memória e se os ponteiros de memória eram globais, então, quando você os acessava, poderia não ter 100% de certeza que o ponteiro ainda era válido e, se não fosse, você estava perdido.

Junto com as linguagens orientadas a objeto surgiram as metodologias orientadas a objeto, culminando no final de 1990 com o UML. Isso foi uma fusão do Método Booch, OMT de James Rumbaugh e OOSE de Ivor Jacobsen, e eram rigorosas quando se tratava de projetar o software. Todos os tipos de ferramentas estavam disponíveis para o trabalho de documentar e comunicar os seus projetos e, por experiência própria, alguns deles eram de qualidade bem duvidosa, o que acaba levantando a questão: os desenvolvedores realmente estavam usando UML para escrever seus programas UML? Se sim, então esses produtos não eram realmente uma boa propaganda para UML.

Atualmente, você não vê muitas organizações por aí usando UML, embora eu ainda o faça quando preciso de um design direto na minha cabeça. Minha primeira escolha da ferramenta UML é, e sempre será, lápis e papel. É simples e funciona.

Finalmente, em minha breve história da programação, temos o Java. Inicialmente lançado em 1995 e se tornando popular alguns anos depois, o Java foi baseado na ideia de melhoria do C++. Isso, principalmente, porque ele é executado em sua própria máquina virtual, que cuida da alocação e desalocação de memória para você. Tornou-se um verdadeiro padrão das linguagens orientada a objeto.

O detalhe desse cronograma amplamente constituído é o conceito sob pinning de programação imperativa. Em resumo, a linguagem Assembly deu origem a C, C para C++ e OO, e C++ e OO levando para Java – todas as imperativas. A Wikipedia oferece uma boa visão geral de programação imperativa, então eu não vou entrar em detalhes, mas vou resumir a programação imperativa aquela com funções e estado mutável, o que significa que você pode ter variáveis globais e de instância.

Como a programação funcional difere de programação imperativa? A ideia principal é que as funções são dados, assim como inteiros e strings; algoritmos são implementados em termos de chamadas de função (loops while e for não existem, você usa recursão) e as variáveis são sempre locais.

Você poderia ser forçado, de forma enganosa, a pensar que, por ter o conceito de uma função e não de classes, linguagens como C e Turbo Pascal são linguagens de programação funcional. Elas não são. São linguagens de programação imperativas, porque têm os dados de estado.

Então, o que mudou? A resposta que foi dada pelos desenvolvedores Erlang, e que você vai encontrar no livro de Manning Java 8, é que foi o hardware que mudou. “Computadores”, pelo menos os que que você encontrará em uma sala de servidor, são agora multiprocessadores sofisticados, coisas multi-core com terabytes de memória. Tomemos, por exemplo, o servidor HP Proliant DL580 G8; ele tem até quatro processadores, e cada um pode ter até 15 núcleos de 64 bits. Isso é muita coisa, especialmente quando comparado com o Intel 8086 16bit, o PC original da IBM. Supondo que você esteja rodando Unix e que executou o comando top, então o uso máximo do processador seria dado como 6000%. Dado esse aumento considerável no poder das máquinas, os desenvolvedores de software precisam de linguagens que as suportem, permitindo que eles usem com facilidade todo esse poder de processamento, e é aí que entra a programação funcional.

Na programação imperativa, você pode ter variáveis de instância, variáveis globais e estado mutável. Eles podem ser compartilhados entre threads, embora compartilhar esses recursos seja dispendioso e ineficiente em termos de sincronização e bloqueio. É também bem lento e difícil de fazer, pois você precisa evitar conflitos e outros problemas parecidos. A programação funcional elimina todos esses problemas, porque acaba com toda a tediosa perda de tempo com variáveis de instância e estado. Isso significa que você não tem que se preocupar com, bloqueio, sincronização, thread ou processos (chame-os como quiser) pois eles podem ser independentes uns dos outros.

Essa é a teoria, mas isso aguenta exames mais aprofundados? Não nos esqueçamos de que é possível escrever bons programas multi-threaded que usam de forma eficaz os vários núcleos de um multi-core e multi-processador de uma máquina com Java 6 ou 7 imperativo. Assim como linguagens de programação funcional, você tem que pensar sobre o que você está fazendo, planejar um projeto apropriado e executá-lo usando as “melhores práticas” de negócios. Só porque o Java 6 ou 7 é uma linguagem imperativa, você não tem que compartilhar dados entre threads/processos e utilizar sincronização e bloqueio. Isso é só uma questão de design. A conclusão lógica é que você pode fazer issosem programação funcional, que leva, possivelmente, à verdadeira razão por trás da popularidade de linguagens de programação funcional: as pessoas gostam de usá-las!

Você poderia dizer, portanto, que as linguagens funcionais são a “última moda”, mania, tendência moda. Eu tenho que enfatizar que “moda” no desenvolvimento de software não é necessariamente uma coisa ruim e não é nada novo. Se você voltar para a minha história acima, verá que a linha do tempo está cheia de tendências e manias: a adoção de C sobre Turbo Pascal e BASIC, a mudança de paradigma de Orientação a Objeto e até mesmo a mudança para Java com suas promessas de compile once e run anywhere.

É imprescindível que você aprenda programação funcional com Java 8? Pergunte-me daqui a alguns anos…

1 – Todos os Fatos históricos neste artigo são garantidos pela minha memória falha e imprecisa.

2 – Me corrija se eu estiver errado, mas int 21H = Funções MSDOS, int 10H = acesso direto à tela, int 14H = serial I/O.

——-

Artigo de Roger Hughes, publicado originalmente no iMasters.