quarta-feira, 6 de setembro de 2017

Zephir: escrevendo extensões para PHP


Resultado de imagem para zephir

Escrever extensões para PHP nunca foi tão fácil
A linguagem PHP é usada hoje em dia em diversas aplicações e sites por toda a internet. É de longe a linguagem mais usada no server side, chegando a ser responsável por mais de 80% das páginas web.
Como você deve saber, o PHP é escrito em C (Assim como Python e Ruby). Além disso, você pode adicionar recursos e funções à linguagem escrevendo extensões em C e compilando-as junto ao interpretador ou como uma biblioteca dinâmica. Drivers de banco de dados, bibliotecas para manipulação do DOM, frameworks fullstacks (Phalcon) e até mesmo algumas funcionalidades do core da linguagem foram escritas como extensões (como a SPL). Você também tem várias e várias extensões disponíveis através do PECL (PHP Extension Community Library).
Repositório oficial da linguagem PHP: https://github.com/php/php-src
Repositório oficial da linguagem PHP: https://github.com/php/php-src
Talvez você se pergunte “porque diabos eu escreveria uma extensão para a linguagem ?” e bem, embora na maioria das vezes provavelmente não seja necessário, há alguns motivos que levam os desenvolvedores a escreverem extensões para PHP:
  • Drivers: Os exemplos mais triviais são drivers para bancos de dados como MySQL e MongoDB. Embora alguns drivers não sejam providos como extensões, esse tipo de aplicação pode tirar grande vantagem em desempenho quando são compiladas. Por falar em desempenho…
  • Desempenho: É fato que o PHP a partir da versão 7+ vêm se tornando cada vez melhor em desempenho. Contudo, suas aplicações escritas em PHP sempre terão o overhead do interpretador e muito provavelmente um código escrito em PHP não vai executar mais rapidamente que o mesmo código escrito em C.
Ok. Escrever drivers para bancos de dados, bibliotecas de manipulação de imagens, entre outras coisas e aproveitar todo o desempenho que C pode oferecer para isso parece tentador, mas há sempre o outro lado da moeda…
  • Desenvolvimento : Escrever, testar, depurar e manter programas em linguagens compiladas e com tipagem estática como C e C++ é geralmente mais complicado do que fazer a mesma coisa com linguagens interpretadas e com tipagem dinâmica como PHP, Javascript ou Python. Isso acaba dificultando o desenvolvimento de novas extensões, principalmente para quem teve pouco ou nenhum contato com C.
  • Zend Engine API: A documentação não ajuda muito. Assim fica meio complicado desenvolver extensões para PHP.
E é aí que entra a Zephir…

Have you met Zephir?

Zephir é uma linguagem de programação de alto nível que permite criar extensões compiladas como bibliotecas dinâmicas para a linguagem PHP. Ela une o melhor de dois mundos: A produtividade advinda da flexibilidade de uma linguagem interpretada e tipagem dinâmica com o desempenho compatível com linguagens compiladas e tipagem estática.
Zephir
Um programa escrito em Zephir gera como produto código C que por sua vez é compilado como uma biblioteca dinâmica e a partir daí pode ser usado no PHP. Uma vez compilada, você pode distribuir essa biblioteca onde quer que queira usar, basta registrar em “php.ini” e ser feliz.
Modelo de compilação da Zephir. Imagem extraída de https://docs.zephir-lang.com/en/latest/motivation.html#compilation-vs-interpretation
Modelo de compilação da Zephir. Imagem extraída de https://docs.zephir-lang.com/en/latest/motivation.html#compilation-vs-interpretation

Instalação

Informações detalhadas sobre a instalação da Zephir podem ser encontradas em:
Zephir
Informações adicionais podem ser encontradas junto ao repositório da Zephir no Github:
Zephir

Zephir: principais características

Zephir tem algumas características que a tornam bastante interessante.
  • Tipagem dinâmica / estática: Zephir consegue tirar vantagem tanto da tipagem dinâmica quanto da tipagem estática. Você consegue no mesmo script usar os dois modos de tipagem sem problemas.
1int a;
2var b;
3let a = 0; // Permitido
4let b = 0; // Permitido
5let b = "Hello"; // Permitido
6let a = "Hello"; // Erro ! Declaramos 'a' como inteiro anteriormente
  • Memory Safe: Zephir foi pensada para ser memory safe, então você não tem variáveis do tipo ponteiro como temos em C. É um detalhe a menos para se preocupar, mas a primeira vista pode parecer estranho para quem lida com ponteiros frequentemente.
  • Multiplataforma: Você pode compilar seu código Zephir / C para bibliotecas dinâmicas em várias plataformas. Arquivos ‘.so’ para Linux/OSX e DLLs para Windows.
  • Built-In methods: Zephir prioriza a programação orientada a objetos, logo não é de se estranhar que alguns arrays e strings sejam tratadas como objetos, assim como alguns tipos primitivos como char e integer. Você pode ver uma lista dos métodos disponíveis aqui.
  • Integração nativa com PHP: Já desenvolve com PHP ? Então você vai se sentir bem à vontade com a Zephir. Na verdade você tem acesso à todas as funções, classes e métodos que tem no PHP. Se um recurso existe no PHP, é certo que você consiga acessá-lo a partir da Zephir.
  • Integração com código/bibliotecas C: Com Zephir, você não fica limitado ao que o PHP também já oferece. Se você já tem um código ou biblioteca escrita em C, pode adicioná-la ao processo de compilação e usar as funções definidas lá.
Há, claro alguns outros recursos interessantes como parâmetros somente de leitura (read-only parameters), e a possibilidade de fazer require em seus arquivos PHP diretamente.
Além disso, Zephir nada deve para as linguagens modernas. Tem suporte a closures e namespaces, além de outros recursos comuns em qualquer linguagem de programação moderna.

Zephir: sintaxe

A sintaxe da Zephir não foge muito do “C-style”, logo temos ‘switch’, ‘while’, ‘if’, e ‘break’ da mesma maneira que em C ou PHP. Operações de atribuição devem ser precedidas pela palavra-reservada ‘let’.
O detalhe fica por conta do ‘for’ que na Zephir é usado exclusivamente para percorrer arrays ou strings. Aliás, falando em arrays, você pode usá-los exatamente como faz no PHP com a diferença de que se usa “:” ao invés de “=>” para atribuir valor à uma chave:
1array data;
2let data = [
3 "a": 1,
4 "b": 4,
5 3: "c",
6 "x": [
7 "Outro array"
8 ]
9];
10var key, value;
11for key, value in data {
12 // Faça alguma coisa usando as chaves e os valores
13}
14for key, _ in data {
15 // Faça alguma coisa usando somente as chaves e ignorando os valores
16}
17for value in data {
18 // Faça alguma coisa usando somente os valores
19}
20for value in reverse data {
21 // Faça alguma coisa usando somente os valores percorrendo o array em ordem reversa
22}
Além disso, qualquer variável deve ser declarada (com tipo ou não) antes de poder ser usada. Logo, as variáveis que receberão os valores a cada iteração sobre o array devem ser declaradas previamente.
Para quem vem do PHP, o suporte à orientação à objetos é exatamente igual ao que temos lá: Temos interfacesclasses e classes abstratas, níveis de visibilidade são os nossos já conhecidos protectedprivate e public, além de constantes. Veja só esta classe de exemplo.
1namespace Extension\Foo;
2use Extension\Bar\AnotherClass;
3/**
4 * Example class
5 */
6class Example {
7const EXAMPLE_CONST = "Hello, Zephir";
8/**
9 * Atributo protected sem tipo definido
10 */
11 protected a {
12 get, set // Getter e Setter definidos
13 }
14/**
15 * Atributo protected com tipo definido
16 */
17 private string a {
18 get, set // Getter e Setter definidos
19 }
20public function __construct() {
21 // Familiar, não ?
22 }
23public function __clone() {
24 // Os demais métodos mágicos também estão disponíveis
25 }
26// Método estático
27 public static function staticMethod() -> int | boolean {
28 // Este methodo deve retornar um inteiro ou um booleano
29 }
30public function exampleMethodA(array options) -> string {
31 // Este método deve retornar uma string
32 }
33private function exampleMethodB(int value, string name = "name") -> boolean {
34 // Este método deve retornar um valor booleano
35 }
36// Este metodo recebe uma variavel sem tipo definido e um booleano
37 protected function exampleMethodC(anyType, boolean ) -> <AnotherClass> {
38 // Este método deve retornar um objeto da classe AnotherClass
39 }
40// Método sem tipo de retorno definido
41 public function exampleMethodC() {
42 return function () {
43 echo "Hello, closures !";
44 }
45 }
46}
Zephir também facilita a criação dos getters e setters para as variáveis. A menos que você tenha alguma lógica nesses métodos, vale a pena usar a construção acima.

Zephir: CLI

Ao instalar Zephir em seu computador você tem acesso à interface de linha de comando da Zephir.
Zephir CLI: praticidade na hora de trabalhar suas extensões
Zephir CLI: praticidade na hora de trabalhar suas extensões
A partir dessa interface, você consegue criar projetos, exportar seu código Zephir para C, gerar stubs ( converte seus arquivos Zephir para arquivos PHP com classes e métodos definidos, sem as implementações ), e fazer build da sua extensão.
Ao fazer build da extensão, o Zephir vai automáticamente instalar a extensão em seu sistema operacional, assim você já poderá testá-la de imediato em sua instalação do PHP.

Zephir: compilação e otimização

Zephir oferece um conjunto de configurações para compilação e otimização do código resultante. Vale a pena dar uma lida, já que são várias opções e cada uma tem uma finalidade.
Zephir
Zephir
Essas configurações são definidas em um arquivo JSON na raiz do projeto da sua extensão. Vale a pena dar uma olhada com carinho nele.
Arquivo config.json de uma extensão
Arquivo config.json de uma extensão

Zephir: resumo da obra e minhas impressões

Zephir é uma linguagem fácil de aprender e fácil de desenvolver. Não à toa cada vez é mais comum se achar um repositório no Github fazendo uso dessa linguagem.
Uma dica que deixo é que vale bastante a pena dar uma lida sobre como funciona o PHP internamente. O site oficial da linguagem PHP tem uma seção sobre isso.
Meu xodó sempre foi C++ e PHP logo em seguida. Mas como linguagem de programação, eu admito que Zephir me encantou. Tem uma sintaxe clara, simples e objetiva. Você não precisa de rodeios para chegar onde quer e isso é de se esperar de uma linguagem que também nasceu com foco em produtividade.
Em resumo é isso: Zephir está aí e você pode tirar bastante proveito dela em suas aplicações PHP, inclusive em pontos onde desempenho é crítico, ou em classes de sua aplicação onde a implementação dificilmente mudará, pode valer a pena migrar parte do seu código para Zephir. Além disso, é mais uma forma de ajudar o ecossistema de PHP a crescer e evoluir.

Nenhum comentário:

Postar um comentário