Olá Habr! Apresento a você a tradução de
The Joy of Haxe. O caso de amor do FontStruct com uma linguagem de programação negligenciada .
Uma tentativa grosseira de reproduzir o logotipo Haxe no editor de fontes FontStructRecentemente, abrimos o código fonte para a parte mais importante do nosso módulo de criação de fontes. Esta é a biblioteca
fonthx para criar fontes TrueType, e está escrita em
Haxe .
Não há praticamente nenhum código neste artigo. Se você está interessado apenas no código, pode familiarizar-se com ele no
github , e seu trabalho é mostrado
no exemplo do editor de fontes de pixel mais simples criado usando a biblioteca fonthx.
Independentemente de você estar ou não familiarizado com o Haxe, o projeto fonthx pode ser do seu interesse, pois demonstra alguns recursos surpreendentes do idioma pouco conhecido fora da comunidade Haxe - em particular, a capacidade de escrever código em um bom idioma com mais compilação / tradução não é apenas em Javascript, mas também em muitas outras plataformas, no caso de fonthx, essas plataformas são JVM (o código do projeto é traduzido em Java), o código nativo (C ++ ou C #), o NodeJS ou o WASM.
Eu posso ser chamado de poliglota convencido. Como muitos outros desenvolvedores, escrevo código em diferentes idiomas e, respeitando as sérias intenções daqueles que preferem se especializar em apenas um idioma, também temo todos os fãs e golpistas evangélicos que falam sobre um idioma verdadeiramente verdadeiro. Mas o que me levou a usar uma linguagem de nicho como o Haxe para criar os principais componentes do FontStruct e também escrever este artigo? E o que é Haxe?
Haxe
O Haxe é uma linguagem de programação moderna e fortemente tipada, com alguns recursos interessantes e uma pequena biblioteca padrão.
O recurso mais significativo de um idioma é sua capacidade de compilar o mesmo código para diferentes plataformas de destino.
A maioria dos desenvolvedores está familiarizada com o conceito de desenvolvimento "isomórfico" quando um programador escreve o código do servidor e do cliente em um idioma. Na maioria das vezes, Javascript ou TypeScript é usado como uma linguagem desse tipo, mas também pode ser usada qualquer outra linguagem capaz de compilar em Javascript. Haxe vai muito mais nessa direção, abrindo uma série de oportunidades adicionais interessantes. É possível compilar um arquivo executável, um aplicativo Java, um módulo WASM, um aplicativo NodeJS, um aplicativo baseado em navegador, um aplicativo móvel e até bibliotecas para linguagens como PHP, Lua ou Python a partir de uma base de código no Haxe.
Na FontStruct, aproveitamos esta oportunidade desenvolvendo os principais componentes de nosso aplicativo Haxe. Os módulos do servidor são compilados como servlets Java e os módulos do cliente são compilados como aplicativos JS. Embora atualmente focemos principalmente nessas duas plataformas de destino (além do NodeJS para executar testes de velocidade), também estamos considerando o uso das ferramentas fornecidas pelo ecossistema Haxe para criar aplicativos móveis em C ++. Além disso, o uso do Haxe no futuro pode permitir a criação de um aplicativo de desktop nativo (não baseado no Electron).
Devido ao fato de o Haxe suportar tantas plataformas-alvo, melhor do que ninguém (pelo menos para nossas tarefas) implementa a idéia de "escrever código uma vez - execute-o em qualquer lugar", melhor do que qualquer ferramenta que eu encontrei nos últimos vinte anos. Isso dá a sensação de que o mesmo código pode ser compilado para qualquer plataforma ou tempo de execução.
Processo de adoção do Haxe
FontStructor - Editor de fontes grátis em FontStruct.comHá mais de 10 anos, quando o FontStruct foi lançado, o Adobe Flash foi usado para o editor de fontes FontStructor, bem como para widgets para visualização de fontes. E para criar fontes TrueType no servidor, foi utilizado um código completamente independente, escrito em Java.
Versão antiga do Flash do editor FontStructor. Todos os controles nele foram desenhados no Flash. Observe as barras de rolagem estranhas nos painéis à esquerda. Com o tempo, o menu principal na parte superior da página divergiu visual e funcionalmente do menu html usado no restante do site. Não há DOM ou CSS aquiEmbora o FontStruct tenha sido e continue sendo um grande sucesso, nossas soluções técnicas iniciais não passaram no teste do tempo. O desenvolvimento de padrões da Web e a falta de suporte a plug-in em plataformas móveis tornaram o Flash inadequado para uso em aplicativos da Web. Também tivemos que lidar com a duplicação de código entre um servidor Java e um cliente Flash, bem como entre o Flash e outras partes do cliente escritas em HTML / JS / CSS. Era necessário sincronizar constantemente entre si as três bases de código, tanto em termos de funcionalidade quanto de design.
Em 2013, começamos a considerar a possibilidade de usar o Haxe, em particular, como um meio de traduzir o editor FontStructor do Flash para o HTML5. Em nossa pesquisa inicial, descobrimos que já havia ferramentas disponíveis para converter automaticamente o código ActionScript em Haxe (
as3hx ) e até a
porta Haxe da estrutura MVC
do Robotlegs que usamos na versão Flash. E então começamos o experimento de portar o cliente.
Início lento e problemático
Nosso primeiro ano de relacionamento com Haxe foi acompanhado por indecisão e dúvida.
Por várias razões, e não menos importante, devido aos recursos limitados que pudemos dedicar a ela, o processo de transferência acabou sendo bastante lento. Como
outros autores já
observaram , a ferramenta para converter automaticamente o código do ActionScript em Haxe (as3hx) acabou sendo muito útil, mas não sem desvantagens - o código obtido com ele precisou ser revisado e editado adicionalmente. Durante esse processo, ficou claro que nossa base de código era inchada e incorreta em seu design; portanto, paralelamente à transferência, decidimos fazer melhorias, diminuindo ainda mais o progresso. Além disso, o Haxe era um novo idioma para nós, então, inevitavelmente, cometemos erros ao estudar esse idioma e suas ferramentas.
De longe, nosso maior erro foi a decisão de usar adicionalmente uma estrutura de interface do usuário de terceiros no Haxe.
Para o Haxe, existem muitas estruturas (talvez até muitas) que fornecem uma API unificada para renderizar gráficos em várias plataformas.
O OpenFL e o
NME são exemplos dessas estruturas e fornecem ferramentas para a criação de aplicativos Haxe para plataformas móveis e até consoles. Ao fazer isso, eles fornecem uma implementação da API do Flash para renderizar gráficos. Tudo isso parecia muito tentador - poderíamos transferir nosso aplicativo para HTML5 usando a API familiar e, talvez, até criar aplicativos para Android e iOS ao mesmo tempo!
Portanto, decidimos usar o OpenFL para portar nosso aplicativo para a Haxe.
Não quero desrespeitar o OpenFL (quero até dizer que: “O problema não está no OpenFL, mas em nós”). O OpenFL é um projeto fantástico que se mostrou bem em muitos projetos, e podemos voltar a ele no futuro, mas depois de portar cerca de 90% de nosso aplicativo para a Haxe, decidimos abandoná-lo.
O OpenFL acabou sendo uma dependência muito mais séria do que esperávamos. Foi originalmente planejado que seria usado apenas como uma biblioteca externa para a nossa interface do usuário, mas no final, o OpenFL estava arrastando suas próprias ferramentas para criar projetos, formatos de arquivo especiais para descrever projetos, além de dependências externas adicionais. Talvez isso se deva ao fato de que, como a maioria do ecossistema Haxe, o OpenFL tenta atender às necessidades dos desenvolvedores de jogos independentes, enquanto se desenvolve rapidamente e a principal atenção em seu desenvolvimento é dedicada à adição de novas funções, não à estabilidade.
O mais importante para nós foi que o código HTML5 gerado usando o OpenFL é ideal para jogos, mas não é adequado para aplicativos como o FontStruct. Tudo o que queríamos no final era exibir no navegador uma árvore DOM normal que pudéssemos estilizar com CSS, e não um conjunto de elementos de tela ou sprites criados pelo OpenFL.
Precisávamos de HTML5 regular, não uma tentativa de replicar o Flash em um navegador sem usar plug-ins adicionais.
Diversão
Assim que abandonamos o uso do OpenFL e percebemos que poderíamos fazer o que quiséssemos usando apenas o Haxe, tudo foi mais rápido, fácil e, finalmente, muito mais divertido.
E trabalhar com Haxe é divertido. Pode-se dizer que foi criado por especialistas em diversão - desenvolvedores de jogos independentes. Os desenvolvedores de jogos precisam de uma compilação rápida, além de uma base de código única para criar aplicativos para computadores desktop, navegadores, iOS, Android e consoles. Os desenvolvedores de jogos precisam de um código produtivo e estável. E o Haxe fornece todos esses ótimos recursos, e não apenas para desenvolvedores de jogos.
Não tenho medo de expressar a ideia de que um dos maiores problemas da Haxe - o tamanho relativamente pequeno de sua comunidade e a escassez relacionada de seu ecossistema - também é sua vantagem em termos de experiência para o desenvolvedor. Ao trabalhar com a Haxe, é improvável que você gaste horas pesquisando e pesquisando informações sobre o estouro de pilha, ou analisando e comparando diferentes lições sobre um tópico de interesse, além de estudar a API de alguma nova estrutura ou biblioteca - essas respostas, lições e as bibliotecas podem muito bem não existir. E, se houver, provavelmente serão os únicos materiais sobre esses tópicos. Com o Haxe, você mesmo resolverá os problemas de programação (!), Gravará as bibliotecas ou, sem experimentar o menor sentimento de culpa, reinventará ou portará a roda sozinho. Isso é divertido e dá liberdade, e é isso que muitos desenvolvedores buscam após estruturas intermináveis e desenvolvimento moderno relacionado à cópia de código de diferentes fontes. Usando o princípio de "menos é melhor", o Haxe não é único, mas é sua vantagem definitiva.
Haxe oferece ao programador oportunidades únicas. Dá uma sensação especial de incrível descoberta e alegria. Usando o Haxe, com sua capacidade de compilar código para muitas plataformas de destino, existe a sensação de que o programador está livre de uma das dependências mais fundamentais de todas as existentes - o próprio tempo de execução.
Renderer FontStruct
O lançamento do nosso primeiro componente Haxe para o site FontStruct em abril de 2015 foi um evento estranho e inesperado.
A galeria é uma parte central do FontStruct: listas pesquisáveis e classificáveis de milhares de fontes criadas em nossa plataforma. Desde o início de 2008, tivemos problemas constantes com a velocidade de download e com o desempenho das visualizações de fontes na própria galeria e em outras páginas do site.
A parte da página da galeria FontStruct em que a visualização das fontes criadas na plataforma é mostrada. Inicialmente, cada item de visualização individual era apresentado com um filme em Flash de carregamento lento!Como as fontes FontStruct ("FontStructions") são armazenadas em um formato proprietário e são frequentemente editadas, é impossível usá-las para renderizar como fontes TrueType comuns. Isso significava a incapacidade de criar imagens de bitmap no servidor para visualizar fontes (usando a biblioteca FreeType).
Para "resolver" esse problema, nos primeiros dias do FontStruct, usamos filmes em Flash separados para elementos da galeria. Cada filme do Flash baixou e analisou dados em nosso formato proprietário e depois mostrou a imagem no cliente para visualização. Ao exibir na página 20 ou mais desses clipes, cada um dos quais baixou dados e tentou desenhar uma fonte, o tempo de carregamento e o consumo de recursos da máquina do usuário aumentaram significativamente, e a situação foi agravada com o tempo, à medida que as fontes desenvolvidas em nosso editor se tornaram cada vez mais e mais complexo.
No final, usamos uma solução híbrida sofisticada: na primeira vez em que analisamos a fonte, usamos um filme em Flash que gerava uma imagem para visualização e, em seguida, essa imagem era capturada e salva no servidor como arquivos PNG. E para a visualização dos seguintes usuários, os salvos no servidor PNG já foram usados. - Esse truque estranho melhorou bastante o tempo de carregamento da página, mas estava sujo e, finalmente, errado ou algo assim. A decisão certa seria escrever um módulo de servidor completamente novo - por exemplo, em Java ou PHP - para carregar e analisar dados de fontes e, em seguida, criar um bitmap com base neles, mas simplesmente não tínhamos os recursos para fazer isso.
Enquanto isso, o processo de transferência do Fontstructor para Haxe estava progredindo muito lentamente, e estávamos longe do lançamento. Mas chegamos longe o suficiente para entender que o novo código Haxe pode resolver nossos problemas com a visualização de fontes na galeria.
Já tínhamos o código Haxe para carregar e analisar nosso formato de fonte. Tínhamos código para renderizar glifos (no Canvas em HTML5 ou em sprites no Flash). Também tínhamos todos os componentes necessários para resolver o problema no lado do cliente. Podemos adaptar esse código para uso no servidor?
Sim Depois que percebemos isso, o processo foi muito rápido. Inicialmente, pensamos em usar o C ++ e a biblioteca do Cairo para renderizar fontes (na esperança de poder escrever uma extensão para PHP ou algum módulo CGI), mas decidimos usar o Java. "Como é maravilhoso poder fazer uma escolha tão fundamental com apenas algumas linhas de código e compilação condicional!" Também podemos usar o NodeJS e o node-canvas para isso, mas já estávamos familiarizados com o processo de criação e implantação de servlets Java, e o Java tem todas as funções necessárias para desenhar e manipular bitmaps. Provavelmente não gostamos de escrever código em Java, mas com o Haxe, isso não é mais necessário.
Esse código de renderização de alto nível pode ser compilado e executado no cliente (JavaScript) e no servidor (na JVM)Como resultado, levamos apenas alguns dias para fazer alterações em nossa base de código e um novo renderizador foi lançado. Durante a noite, melhoramos significativamente o desempenho da galeria FontStruct, nos livramos do uso de hacks sujos e, mais importante, lançamos nosso primeiro componente no Haxe para a batalha. Percebemos que o Haxe é capaz de surpreender e tem recursos muito maiores do que esperávamos dele.
Adeus ao Flash (e c Vanilla Java)
Em novembro de 2015, ou seja, após 7 meses, lançamos com sucesso o primeiro módulo cliente Haxe - a versão HTML5 do widget para visualização de fontes. Eu acho que nossos usuários quase não perceberam as mudanças, o que, por um lado, desaponta, mas, em última análise, é um indicador do sucesso dessa iniciativa.
Agora, tínhamos apenas um módulo Flash no site - o editor FontStructor, e levamos mais um ano para finalmente lançar sua versão HTML5 em novembro de 2016. Chegou a hora de finalmente abandonar o código AS3 e declarar o FontStruct livre do Flash.
Nova versão HTML5 do FontStructor lançada em 2016Em agosto de 2018, transportamos o módulo de geração de fontes FontMortar para a Haxe. Essa última porta nos permitiu abandonar completamente o código escrito em Java.
Não estou pronto para usar o Haxe para tudo. Sim, eu sei que existem projetos nos quais ele é usado como a principal ferramenta para todos os aspectos do desenvolvimento da Web, mas estou muito feliz com a excelente estrutura
Symfony como base de nosso aplicativo da Web. O FontStruct continua a usar muitas linguagens de programação diferentes, mas a introdução do Haxe nos permitiu reduzir o tamanho e a complexidade das partes mais importantes do nosso código. Para nossa pequena organização, essa simplificação se mostrou vital para manter e desenvolver a plataforma.
Mergulhando mais fundo no Hux
Se esta é a primeira vez que você ouviu falar de Haxe e minha história lhe interessou, então só tenho que listar mais alguns fatos sobre ele.
- O suporte ao idioma por parte do IDE é bastante decente e está em constante aprimoramento; os módulos do IntelliJ Idea e do Visual Studio Code estão em desenvolvimento.
- O Haxe fornece ferramentas para trabalhar com código e bibliotecas nativas , para que não limite seus recursos, impondo apenas um pequeno subconjunto das funções disponíveis. Se você estiver desenvolvendo para JavaScript, terá a oportunidade de usar qualquer biblioteca JavaScript, por exemplo, vários binders estarão disponíveis para trabalhar com o React. Para o FontStructor, usamos vários módulos npm, como o Interactive.js e o Opentip. Escrever pastas para eles levou apenas alguns minutos.
- A Haxe possui um sistema robusto de tipo avançado com recursos como parametrização de tipos , classes e métodos genéricos , tipos abstratos e inferência de tipos .
- O Haxe possui macros extremamente poderosas que fornecem acesso ao AST em tempo de compilação, o que permite aos desenvolvedores adicionar suas próprias construções de linguagem e gerar código dinamicamente.
- Apesar de não haver muitos recursos no Haxe na Internet, existe um repositório de bibliotecas que cobre as necessidades gerais de desenvolvedores fora da biblioteca padrão (além disso, no Github você pode encontrar ainda mais repositórios que não estão representados no haxelib - aprox. Translator) .
- Por último, mas não menos importante, Haxe tem uma comunidade muito talentosa e receptiva .
Conclusão
Os desenvolvedores mais experientes estão prontos para a mudança, mas são cuidadosos ao escolher as tecnologias usadas. Provavelmente, em algum momento, a maioria de vocês também sentiu vontade de mudar a linguagem de programação dentro da estrutura do projeto, especialmente quando novas linguagens modernas e com muitos recursos interessantes aparecem. Tivemos o cuidado de escolher Haxe, pensando em quanto tempo nosso relacionamento duraria. Nossos pensamentos sobre ele eram algo assim :Parece ótimo, mas tem uma comunidade tão pequena. O que acontecerá com ele em 5 anos? O site parece ser normal, mas por algum motivo não parece moderno. E isso não inspira confiança.
Não parece tão bem documentado.
Isso não é para desenvolvedores de jogos independentes?Após cinco anos de uso do Haxe, estou sinceramente surpreso por não me arrepender de nossa escolha dessa tecnologia. Apesar de todas as deficiências e dificuldades causadas por eles, apesar da comunidade relativamente pequena e da ausência de grandes patrocinadores corporativos, a Haxe está cumprindo totalmente suas tarefas. Com Haxe, sinto liberdade e independência de qualquer plataforma. Agora, temos uma única base de código para os principais componentes do FontStruct, enquanto antes havia dois deles. Nos últimos meses, as versões mais recentes dos servlets responsáveis por gerar fontes e imagens para visualização nunca falharam. O novo editor de HTML5 e o widget de visualização agora funcionam em todos os navegadores, incluindo dispositivos móveis, enquanto que antes tínhamos que trabalhar com tecnologia ultrapassada e obsoleta.E, além dos benefícios práticos, trabalhar com Haxe traz alegria e um senso de mágica, a alegria de Haxe !