Levando a Sério o PHP

PHP Hack

O Facebook usa o PHP para a maior parte de sua lógica de aplicativos no lado do servidor, o que é uma escolha incomum nos dias de hoje. Por que escolhemos construir um novo projeto nesta linguagem? Você deveria?

PHP 7, HHVM e Hack. Tecnologia de Desenvolvimento Agile

A maioria dos programadores que apenas deram uma espiada superficial no PHP dizem duas coisas sobre ele: é uma linguagem ruim, que eles nunca usariam se tivessem escolha; e que não entendem como alguns projetos extraordinários e bem-sucedidos o usam. Isso não é uma contradição, mas nos deixa curiosos. O Facebook, a Wikipedia, o WordPress, o Etsy, o Baidu, o Box, o Magento, e mais recentemente, o Slack tiveram sucesso apesar do uso do PHP? Estariam todos melhor expressando sua aplicação em Ruby? Erlang? Haskell?

Talvez não. A linguagem de programação PHP tem muitas falhas, que, sem dúvida, tem diminuído versão a versão, mas o PHP como ambiente tem virtudes que mais do que compensam essas falhas. E as opções para melhorar as falhas no nível de linguagem do PHP são bastante impressionantes. Na balança, o PHP fornece melhor suporte para construir, mudar e operar um projeto bem-sucedido do que os ambientes concorrentes.

Background

Entre as linguagens modernas, o PHP nasceu em um servidor web. Seus pontos fortes estão intimamente ligados ao contexto da execução do lado do servidor orientada por solicitação.

Originalmente, o PHP significava “Personal Home Page”. Foi lançado pela primeira vez em 1995 por Rasmus Lerdorf, com o objetivo de suportar pequenas aplicações web dinâmicas simples, como os livros de visitas e contadores de sucesso que eram populares nos primeiros dias da web.

Desde o início do PHP, ele foi usado para projetos muito mais complicados do que seus criadores previam. Ele passou por várias revisões importantes, cada uma delas trazendo novos mecanismos para manipular aplicações mais complexas. Hoje, é um membro rico em recursos da família MPDPL (multi-paradigm programming languages), que inclui JavaScript, Python, Ruby e Lua. Para quem trabalhou com o PHP nos primórdios, uma página de código PHP contemporânea pode surpreender com traços, closures e geradores.

Virtudes do PHP

Vejamos alguns pontos:

Primeiro, “Estado”. Toda solicitação da web começa em um slate completamente em branco. O namespace e global variables não são inicializados, exceto pelos padrões globais, funções e classes que fornecem funcionalidade primitiva e suporte à time life da página. Ao iniciar cada solicitação a partir de um estado conhecido, obtem-se um tipo de isolamento orgânico de falhas; se o request encontrar um defeito de software e falhar, este erro não interferirá diretamente na execução do request subseqüente t + 1. O estado reside em locais diferentes do heap do programa, que podem atrapalhar aplicações paralelas como bancos de dados, memcache ou o próprio sistema de arquivos. Mas o PHP compartilha essa fraqueza com todos os ambientes concebíveis que permitem persistência. Isolar os pedidos de um do outro reduz o custo da maioria dos defeitos do programa.

Segundo, “Simultaneidade”. Uma solicitação da web individual é executada em um único encadeamento do PHP. Isto parece a princípio como uma limitação simples. Mas como programas são executados no contexto de um servidor da Web, cria-se naturalmente uma fonte natural de simultaneidade disponível: solicitações da web. O uso incorreto de assincronismo localhost (ou até mesmo outro servidor da Web) fornece uma maneira de copiar, copiar e copiar nada compartilhado do paralelismo. Na prática, isso é mais seguro e mais resistente a erros do que a abordagem de bloqueios e estado compartilhado que a maioria das outras linguagens de propósito geral fornece.

Por fim, o fato de os programas PHP operarem em um nível de solicitação significa que o fluxo de trabalho do programador é rápido e eficiente e permanece rápido à medida que o sistema é alterado. Muitas linguagens de produtividade do desenvolvedor afirmam isso, mas se elas não redefinirem o estado para cada solicitação e o loop de eventos principal compartilhar o estado no nível do programa com solicitações, elas quase sempre terão algum tempo de inicialização. Para um servidor de aplicativos típico do Python, por exemplo, o ciclo de depuração será parecido com “pensar; editar; reiniciar o servidor; e enviar alguns pedidos de teste”.

O PHP é mais simples: “pensar; editar; recarregar o ciclo da página” torna os desenvolvedores mais produtivos. Ao longo de um longo e complexo ciclo de vida de projetos de software, esses ganhos de produtividade se somam.

E Quais Restrições ao PHP?

O PHP possui alguns pontos fracos, veja abaixo as reclamações mais comuns:

    1. Conversões de tipo surpresa. Atualmente, quase todos os idiomas permitem que os programadores comparem, por exemplo, inteiros e flutuantes com o operador “>=”. Neste caso é perfeitamente claro o que se espera da comparação. Mas é menos claro o que é comparar uma string e um inteiro com o operador “==”. Diferentes linguagens de programação trazem resultados diferentes. As escolhas do PHP neste departamento são especialmente perversas, levando a surpresas e erros não detectados. Por exemplo, 123 == “123foo” é avaliado como verdadeiro, Mas 0123 == “0123foo” é falso.
    2. Inconsistência em torno de referência e semântica de valor. O PHP 3 tinha uma semântica clara de que a atribuição, a passagem de argumentos e o retorno eram todos por valor, criando uma cópia lógica dos dados em questão. O programador podia (e ainda pode) optar pela semântica de referência com uma anotação “&”. No entanto, isso colidiu com a introdução de recursos de programação orientada a objetos no PHP 4 e 5. Grande parte da notação OO do PHP é copiada do Java, e o Java tem a mecânica de objetos tratados sempre por referência, enquanto os tipos primitivos são tratados pelo valor. Portanto, o estado atual da semântica do PHP é que objetos são passados por referência (escolhendo Java sobre, digamos, C++), tipos primitivos são passados por valor (onde Java, C++ e PHP concordam), mas a semântica e notação de referência mais antigas persistem, às vezes interagindo com o novas versões de maneiras conflitantes.
    3. Filosofia indiferente à falha. PHP tenta, mas é muito difícil manter a requisição viva em execução, mesmo que tenha feito algo profundamente estranho. Por exemplo, a divisão por zero não lança uma exceção, nem retorna o INF, nem encerra fatalmente o pedido. Por padrão, ele avisa e avalia o valor false. Como false é tratado silenciosamente como “0” em contextos numéricos, muitos aplicativos são implantados e executados com divisões não diagnosticadas por zero. Esta questão em particular é alterada no PHP 7, mas o costume de design faz com que continue sendo usado desta forma permeando as bibliotecas também.
    4. Inconsistências na biblioteca padrão. Quando o PHP era jovem, seu público estava mais familiarizado com C, e muitas APIs usavam a linguagem de design da biblioteca padrão C: nomes de letras minúsculas de seis caracteres, sucesso e falha retornados em um valor de retorno inteiro com valores “reais” retornados em um arquivo. Mas com o amadurecimento do PHP, o estilo C de namespacing e “prefixação” com o caracter “_” tornou-se mais difundido: mysql_…, json_…, etc. E mais recentemente, o estilo Java dos métodos “camelCase” de classes e propriedades tornou-se a maneira preferencial de implementação. Então, às vezes, vemos trechos de código que intercalam expressões como o novo DirectoryIterator($path) com if(!($F = fopen($p, ‘w+’))… de uma forma dissonante.

Todos esses são problemas sérios que tornam o processo de desenvolvimento mais difícil e propenso a erros não forçados. Não há trade-off inerente entre as partes boas do PHP e esses problemas. Deve ser possível construir um PHP que limite essas desvantagens enquanto preserva as partes boas.

HHVM e Hack

Hack é conhecido como o sistema sucessor do PHP. É uma linguagem de programação que as pessoas chamam de “sistema de digitação gradual” para o PHP. O ‘sistema de digitação’ significa que ele permite ao programador expressar automaticamente invariantes verificáveis ​​sobre os dados que fluem através do código: essa função pega uma string e um inteiro e retorna uma lista de Fribbles, assim como em Java ou C++ ou Haskell ou muitas outras linguagens. A parte “gradual” significa que algumas partes da base do código podem ser digitadas estaticamente, enquanto outras partes ainda estão em PHP dinâmico. A capacidade de mixá-los permite a migração gradual de grandes bases de código.

É um sistema limpo e bastante ambicioso no que ele permite expressar. Ter a opção de migrar gradualmente um projeto para o Hack, caso ele cresça maior do que o esperado pela primeira vez, é uma vantagem exclusiva do ecossistema do PHP. A verificação de tipos do Hack preserva o “pensamento”; editar; recarregar o fluxo de trabalho da página, porque o verificador de tipos é executado em segundo plano, atualizando incrementalmente seu modelo da base de código quando ele vê modificações no sistema de arquivos. O projeto Hack fornece integrações com todos os editores e IDEs populares, para que o feedback sobre os erros de tipo ocorra assim que você terminar de digitar, assim como na demonstração da Web.

Vamos avaliar o conjunto de riscos reais que o PHP apresenta à luz do Hack:

      1. Conversões de tipo surpresa se tornam erros nos arquivos Hack. Toda a classe de problemas desaparece.
      2. As semânticas de referência e valor são limpas simplesmente banindo as referências antigas no Hack, já que elas são desnecessárias em novas bases de código. Isso deixa para trás as mesmas semânticas objeto-por-referência e tudo-por-valor como Java ou C#.
      3. A falta de consciência do PHP é mais uma propriedade do tempo de execução e das bibliotecas, e é mais difícil para um verificador semântico, como o Hack, acessar diretamente esses sistemas. No entanto, na prática, a maioria das formas de esquecimento de falhas requer conversões de tipo surpresa para ir muito longe. Por exemplo, os problemas que surgem da propagação do “falso” retornado da divisão pelo zero eventualmente cruzam um limite verificado pelo tipo, que falha ao tratar numericamente um booleano. Esses limites são mais freqüentes em bases de código do Hack. Ao tornar mais fácil escrever esses tipos, o Hack diminui a “distância de skid” de muitas execuções com bugs na prática.
      4. Finalmente, inconsistências na biblioteca padrão persistem. O máximo que Hack espera fazer é tornar menos doloroso envolvê-los em abstrações mais seguras.

Hack fornece uma opção que nenhum outro membro popular da família MPDPL possui: a capacidade de introduzir um sistema de tipos após o desenvolvimento inicial e apenas nas partes do sistema em que o valor excede o custo.

HHVM

Hack foi originalmente desenvolvido como parte do HipHop Virtual Machine, ou HHVM, um ambiente JIT de código aberto para PHP. O HHVM oferece outra opção importante para o projeto bem-sucedido: a capacidade de executar seu site com mais rapidez e economia. O Facebook registra uma melhoria de 11,6x na eficiência da CPU em relação ao interpretador do PHP, e a Wikipedia reporta uma melhoria de 6x.

Olhando Para Frente

Neste post começamos com o aparente paradoxo de que o PHP é uma linguagem muito ruim que é usada em muitos projetos de sucesso. Descobrimos que sua reputação como uma língua pobre é, isoladamente, muito bem merecida. O sucesso dos projetos que o utilizam tem mais a ver com propriedades do ambiente PHP, e o fluxo de trabalho de alta cadência que ele permite, do que com o PHP na linguagem. E as vantagens desse ambiente (custo reduzido dos bugs por meio do isolamento de falhas, concorrência segura e alto rendimento do desenvolvedor) são mais valiosas do que os problemas que as falhas do idioma criam.

Além disso, exclusivamente entre os MPDPLs, existe um claro caminho de migração para um meio de desempenho mais alto, mais seguro e mais sustentável, na forma de Hack e HHVM.

*** A OctalMind é uma empresa especializada no desenvolvimento de sistemas de alta tecnologia.