24h: Toyota sofre acidente espetacular, e DeltaWing está fora

O choque entre uma Ferrari 458 retardatária e um dos dois Toyota TS030 Hybrid foi até agora o acontecimento mais assustados da 80ª edição das 24h de Le Mans. Lá pela sexta hora de duração, o Toyota pilotado por Antony Davidson ultrapassava a Ferrari GTE de Piergiuseppe Perazzini quando o italiano inexplicavelmente jogou seu carro na direção do outro, como se não tivesse visto o monstro japonês no retrovisor na hora de fazer a tomada de curva.

O Toyota Hybrid voou e girou, com movimentos coreografados pelas estruturas aerodinâmicas, que não se provaram assim tão eficientes na hora de evitar piruetas no ar. Felizmente ninguém se machucou.

A nossa torcida pelo estranho DeltaWing acabou logo depois, quando o outro Toyota restante, pilotado naquele momento por Kazuki Nakajima, também parece não perceber que havia um carro ao seu lado na entrada de uma curva. Ruim para a equipe da Nissan, que abandona o experimento, e pior para a Toyota, pois o Hybrid de Nakajima sofreu danos que parecem ter inviabilizado a disputa pela vitória.

[youtube http://www.youtube.com/watch?v=puZa681uVXU]
Jalopnik Brasil

 

A análise de sistemas na construção de softwares

Quando se fala em desenvolvimento de softwares, para quem tem bons conhecimentos de programação (ou não), é simples dizer a palavra “mágica” que quase sempre já está na ponta da língua: “Eu tenho a solução!”, afirmam. Contudo, isso é um grande equívoco que profissionais/empresas cometem.

O que alguns profissionais não entendem é que nem sempre o cliente sabe o que quer ou nem sempre consegue expressar o que pensa. E em muitos casos, expressam totalmente o contrário do que realmente queriam passar. É fácil entender isso, levando em consideração pontos tais como: falta de conhecimento de tendências, falta de sensibilidade, falta de conhecimento técnico, entre outros fatores que podemos enumerar. E, consequentemente, há um gasto excessivo de investimento e mão de obra e frustrações dos dois lados são inevitáveis.

É provável que você já deve ter se deparado com vários casos parecidos. Na prática, é bem comum no início do projeto uma conversa informal com o cliente e depois de quase tudo pronto ele dizer que não era bem aquilo que se esperava. Outro caso, é a mudança contínua das iterações do projeto para atender ao nível “alto” de satisfação do cliente (que nunca está satisfeito).

A verdade sobre esses fatores são muitas. A começar pelo preço de custo/benefício, “tempo” e a pressão dos gestores em sua equipe para construírem softwares com tempo cada vez menor, e, contudo, a falta de planejamento sério e de chegar a um nível maduro de entendimento do que realmente o cliente espera do produto final.

Conseguir bons requisitos não é tarefa fácil, e, nem tão pouco, empresas estão interessadas em investir neste tipo de profissional. Investir neste processo, gasta-se um tempo de planejamento, mas algo necessário, ou seja, levando-se pelo ponto de vista maduro, é algo que se ganha lá na frente da iteração do projeto.

Estudos indicam que requisitos detectados depois do software implementado ou erros em sua análise são até 20 vezes mais caros de se corrigir que qualquer outro tipo de erro. A ilustração abaixo mostra a realidade na construção de softwares e podemos até dizer (desconsiderando alguns passos) que em determinados tipos de serviços mais informais, isso também acontece.

Essa é uma realidade não apenas no desenvolvimento de softwares, mas é algo corriqueiro e que acontece em nosso cotidiano. Para isso, basta precisarmos de um serviço específico de uma determinada área que desconhecemos, um tipo de conserto de um aparelho, etc. Nestas situações, recebemos muitas opiniões e “conselhos” do que realmente não se deve fazer. Mas, em alguns casos, encontramos algum bom profissional que realmente está atento a nossa necessidade e provê uma solução ao problema.

“Um bom profissional sabe comunicar o seu jargão técnico com o jargão informal do seu cliente.”

Outro ponto que alguns profissionais (mesmo os melhores) não entendem, é o fato que o cliente não é obrigado a saber/entender de um determinado assunto ou uma necessidade. Isso eu chamo de visão, ou seja, alguns profissionais têm (e conquistam o cliente), outros não. Saliento a importância em dar à atenção ao cliente e se dedicar em ouvir sua história de forma a entender o que ele quer e para que ele quer.

Especificamente falando de softwares, a análise é fundamental, pois em sua construção, um dos maiores desafios no desenvolvimento é o da construção do sistema certo, que preencha as necessidades dos usuários a um preço razoável. E para que isso aconteça, é preciso atingir boa comunicação e boa compreensão do mundo dos usuários (é onde entra a Análise de Sistemas). Este artigo é uma abordagem bem superficial de uma análise de softwares, onde há várias iterações, bem como sua documentação, no qual a documentação dos requisitos e de casos de uso é uma forma “contratual” entre a equipe de desenvolvimento e o cliente a respeito do software que será desenvolvido. Mas, o artigo aborda um ponto de vista que se deve ter na hora de construir software de qualidade.

Por outro lado, posso afirmar que o grande desafio do analista não se limita apenas em implementar melhores soluções tecnológicas, mas sim em mudar a cultura de uma empresa. Estudar, se dedicar e se especializar no que faz é parte da vida do profissional, mas, saber lidar com essas situações divergentes é o que faz o grande diferencial do profissional e o sucesso no que se faz.

Fonte: http://www.rafaelamaral.com.br

Long Polling com #PHP

Olá Pessoal !
Como mostrei a forma de se fazer um Long Polling utilizando Node.JS ( Long Polling com Node.JS ) , irei mostrar agora a forma de se fazer com PHP.

Importante !

Funcionar funciona, apesar de não ser tão eficiente quanto ao long polling feito utilizando node.js, não foram testados os efeitos colaterais no servidor, tais como desempenho e concorrência de uso, afinal estamos utilizando PHP.

A Técnica

Bom, para começar eu gostaria que vocês lessem o post do Long Polling com Node.JS para entender um pouco mais da técnica utilizada, o que na verdade só é uma técnica e aplicando o que foi proposto por ela:

  • Abrir a conexão e não deixar que esta seja fechada sem resposta
  • Se a conexão for fechada por algum motivo, tentar reabrir
  • Não fechar a conexão até ter uma resposta esperada

Vocês irão ter um Long Polling com sucesso, então vamos lá .!

Lógica, Codificação

Criei quatro arquivos { “index.php” , “data.txt” , “server.php” , “client.js” } o data.txt contém os dados que serão mostrados, mas antes disso será feita uma comparação lógica, que se baseia em NÃO emitir uma resposta se : ‘os dados do data.txt estiverem vazios, se o conteúdo do data.txt for igual ao conteúdo requisitado’

Conteúdo requisitado ? quando recebemos uma resposta do servidor, que obviamente só vamos receber se houver conteúdo, nos capturamos o que foi retornado e enviamos por query string de volta ; Por que ? para comparar se o conteúdo atual ou futuro do data.txt é diferente, pois não vamos responder ou perguntar algo que já sabemos, lembrando que a mesma coisa vale para um banco de dados.

Nosso código PHP ficaria assim:

<?php
       while ( true ) {
              $data = file_get_contents ( 'data.txt' ) ;
              $requested = isset ( $_GET [ 'content' ] ) ? $_GET [ 'content' ] : null ;
              if ( strlen ( $data ) > 0 && $requested !== $data ) {
                     echo $data ;
                     break ;
              } else {
                     sleep ( 2 ) ; // vamos dar um intervalo !
                     continue ;
              }
       }

O que fizemos ? iniciamos um loop infinito, logicamente se ele não for parado a requisição nunca vai terminar, a mesma coisa vale pra quando entramos na página que contém esse código ( server.php ) , e então lemos o conteúdo do arquivo, e procuramos pelo índice content na query string , duas comparações simples ( se a quantidade de caracteres de $data for maior que zero e se $requested for diferente de $data que é o conteúdo do text, emitimos a resposta e paramos o loop , nesse caso a requisição é fechada, feito isso o resto é simples.

Agora, o lado do cliente ( jscript ) , basta criar uma função que é responsável por enviar a requisição para ‘server.php’, e quando esta for fechada ( Http Code 200 ) , criamos a requisição novamente .. e assim por diante ( recursividade )

$ ( document ).ready ( function ( ) {
       $ ( '#ready' ).on ( 'click' , function ( ) {
              startPolling = function ( content ) {
                     content === undefined || $ ( '#response' ).html ( content ) ;
                     var qs = { 'content' : content } ;
                     $.get ( 'server.php' , qs , function ( data ) {
                            startPolling ( data ) ;
                     } ) ;
              } ;

              startPolling ( undefined ) ;
       } ) ;
} ) ;

Só precisamos disso .. bem simples e direto , a unica coisa que tem de demais no código acima, é a recursividade, como eu disse que faz parte da técnica, a conexão precisa ser reaberta caso fechada, e ela só é fechada quando temos a resposta esperada , para testar basta criar um arquivo html e colocar o seguinte código

<html>
       <head>
              <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
              <script type="text/javascript" src="client.js"></script>
       </head>
       <body>
              <input type="button" value="ready" id="ready">
              <div id="response"></div>
       </body>
</html>

Isso é tudo .. agora façam seus testes, não apliquem uma técnica dessa pra algo que possa ser resolvido de outra forma, estude outras maneiras e principalmente, avaliem o custo benefício de cada uma delas, o que foi demonstrado acima funciona, você evita ficar enviando requisições ao servidor quando ele está respondendo o que você não quer , me faz lembrar o burro do shrek .

Abraços, e boa sorte !

 

Long Polling com Node.JS

Bem, esse é um assunto muito interessante e bastante discutido, trata-se de aplicações em tempo-real ( comet ) , nesse caso uma conexão aberta com o servidor aguardando respostas. Enquanto não temos HTML5 em todos navegadores, para poder utilizar os WebSockets, temos que utilizar técnicas Comet para desenvolver aplicações em realtime, como podemos fazer isso !? Podemos utilizar a técnica Long Polling !

Long Polling

É uma técnica comet, que permite que a conexão fique aberta, aguardando uma resposta do servidor para esta ser fechada e reaberta novamente, a diferença do AJAX Polling, que fica enviando requisições mesmo o servidor respondendo ‘não tenho nenhuma resposta’ consecutivamente, isso acaba prejudicando a aplicação e criando um excesso de requisições no servidor, observa-se uma long polling em ação com a imagem abaixo 

Na prática, o que é ?

A conexão deve ser sempre aberta, o que não pode acontecer é essa conexão ser fechada, e o cliente não tentar reabri-la, daí não estamos respondendo de volta. Com Node.JS, temos um Daemon ( Disk And Execution Monitor ) , que lida com todas as requisições recebidas e enviadas ou seja o serviço é independente tanto de resposta, quanto de recebimento, nesse caso temos handlers ( manipuladores ) para as requisições feitas, e dessa forma, manipulamos essas requisições, é aí que entra a mágica !

Com Node.JS, guardamos todos os manipuladores em um objeto de manipuladores, para que possam ser utilizados de acordo com as requisições feitas, logo seguinte trecho de código

var http = require ( 'http' ) ; // Módulo HTTP do Node.JS ( Nativo )
var handlers = new Object ( ) ; // Objeto de manipuladores

Dessa forma, ficam acessíveis a todos , a variável ‘handlers’ é global para todo código portanto, não se preocupem muito com o escopo, além do mais para o que vamos utiliza-la, não teremos esse tipo de problema, vamos criar o servidor HTTP (http.createServer)

var http = require ( 'http' ) ; // Módulo HTTP do Node.JS ( Nativo )
var handlers = new Object ( ) ; // Objeto de manipuladores 

var url = require ( 'url' ) ;
var server = http.createServer ( function ( request , response ) { 

       response.send = function ( httpCode , data , contentType ) {
              var $data ;
              if ( data instanceof Object ) {
                     $data = new Buffer ( JSON.stringify ( data ) ) ;
              } else $data = data.toString ( ) ;
              this.writeHead ( parseInt ( httpCode ) , {
                     'Content-Type' : contentType.toString ( ) ,
                     'Content-Length' : $data.length
              } ) ;
              this.end ( $data ) ;
       } ;

       var path = url.parse ( request.url ).pathname.toString ( ) ;
       if ( path !== null || path !== undefined ) {
              if ( path in handlers !== false ) {
                     if ( typeof handlers [ path ] === 'function' ) {
                            handlers [ path ] ( request , response ) ;
                     }
              }
       }
} ).listen ( 8080 , function ( ) {
       console.log ( 'Servidor iniciado !' ) ;
} ) ;

Vamos precisar do modulo ‘url’ para fazer o parser de urls, ou seja as urls de requisição, é necessário o require desse modulo, logo depois, a adição de um método auxiliar para emitir respostas para o cliente, trata-se do método send no objeto response, que emite respostas de acordo com os parâmetros passados, contentTypecomo todos conhecem, o tipo do conteúdo que está sendo enviado, o código http e os dados, logo abaixo o parser do path da url, testando se este não é nulo ou indefinido , e testando também se este path está registrado como um handler, o que esperamos que seja.

Importante !

Os handlers são mapeados de acordo com o path, o que seria esse path ? é exatamente o que estará no lugar de [path] em ‘http://127.0.0.1:8080/[path]‘.
Mas porque o handler é mapeado dessa forma !? porque essa é a forma mais fácil, existem outras, podemos fazer por query string enviando o parâmetro handler com o nome do handler em questão.

Se esse handler for uma função, o que esperamos que seja, executamos ele passando os objetos request e response para poder manipular logo, não colocamos um monte de if’s dentro da closure ( fica feio não !? ), vamos adicionar cada handler necessário no objeto de forma diferente ! então, vamos ter o seguinte código

var messages = [ ] , callbacks = [ ] ;

handlers [ '/message' ] = function ( request , response ) {
       var message = url.parse ( request.url , true ).query.text ;
       var $ = {
              text : message.toString ( ) ,
              appendMessage : function ( callBack ) {
                     messages.push ( this ) ;
                     callBack ( this ) ;
              }
       }.appendMessage ( function ( message ) {
              while ( callbacks.length > 0 ) {
                     callbacks.shift ( ).callBack ( [ message ] ) ;
              }
       } ) ;
       response.writeHead ( 200 , { } ) ;
       response.end ( null ) ;
} ;

Primeira parte feita, criei um array para mensagens ( o que será armazenado nele ? todas as mensagens que são enviadas, ficam ali ), vocês podem colocar um setInterval para remover as mensagens a cada 1 minuto, pra não manter um array enorme de mensagens antigas :P , então crio um objeto que representa uma mensagem, nesse objeto, tem o método appendMessage que é executado após a criação do objeto, esse método adiciona a mensagem na lista (this) e executa o callBack passado por parâmetro, essa é a parte mais importante para tudo funcionar corretamente

O callBack .. o que é, e pra que serve nesse contexto ?

O callback é quem vai notificar todas as conexões abertas, e é exatamente por isso que ele é executado quando uma mensagem é adicionada, se uma mensagem é adicionada, algo mudou no servidor, temos então que notificar aos clientes que esperam esta mudança acontecer, se não notificarmos, o cliente vai ficar com a conexão aberta esperando uma resposta que sabemos que não será enviada. Portanto, chamamos o callback logo após a mensagem ser adicionada na lista

Temos então, a parte que envia a mensagem, deixando claro aqui também, lembre-se de emitir um HTTP-Code 200 para que a conexão não fique aberta, por isso emito o header e executo o método end pra enviar a resposta para o requisitante e fechar a conexão, agora a parte que faz o polling:

handlers [ '/polling' ] = function ( request , response ) {
       if ( messages.length === 0 ) {
              callbacks.push ( {
                     callBack : function ( $messages ) {
                            response.send ( 200 , {
                                   messages : $messages
                            } , 'text/json' ) ;
                     }
              } ) ;
       } else {
              response.send ( 200 , {
                     'messages' : messages
              } , 'text/json' ) ;
              messages = [ ] ;
       }
} ;

Simples não !? verifico se o array de mensagens é vazio, se for adiciono um cliente esperando resposta na lista de callBacks, porque este deve manter a conexão, observem também que eu NÃO dou fim na requisição, a função callBack que é adicionada na lista só é chamada quando uma mensagem é enviada ( algo muda no servidor ) , então o próprio servidor já vai notificar quando houver novas mensagens, caso o array já tenha mensagens, respondo a requisição e mando as mensagens que estão no array, logo após limpo a lista de mensagens, no lado do cliente teríamos algo semelhante ao seguinte fragmento de código

$ ( document ).ready ( function ( ) {
       function startPolling ( data ) {
              if ( data instanceof Object ) {
                     for ( var i in data.messages ) {
                            // ... exibe as mensagens
                     }
              }
              $.ajax ( {
                     url : 'http://127.0.0.1:8080/polling' ,
                     method : 'GET' ,
                     success : function ( data ) {
                            startPolling ( data ) ;
                     }
              } ) ;
       }
} ) ;

O que vai acontecer ? vamos requisitar novas mensagens quando houver, essas mensagens serão mostradas e vamos requisitar de novo procurando por novas, só que a conexão vai ficar aberta, até termos novas mensagens e enquanto a conexão estiver aberta uma nova não é criada, no console do google chrome aba network, mostra que não estamos trafegando dado algum, mas a requisição está pendente ou seja, esperando uma resposta

Demonstração rápida com cURL

Uma breve demonstração disto em ação, pode ser feita utilizando cURL, vou abrir 4 janelas do prompt-de-comando, em três delas, eu vou iniciar o polling, e na última, vou enviar uma mensagem, observem o resultado

-- Janela 1
C:>curl http://127.0.0.1:8080/polling
{"messages":[{"text":"Hello!"}]}
-- Janela 2
C:>curl http://127.0.0.1:8080/polling
{"messages":[{"text":"Hello!"}]}
-- Janela 3
C:>curl http://127.0.0.1:8080/polling
{"messages":[{"text":"Hello!"}]}
-- Janela 4
C:>curl http://127.0.0.1:8080/message?text=Hello!

Bem legal não é !? e você, sabe outra técnica ? alguma dica para melhorar o long-polling ? apresente-se !