Portfolio

Desenvolvimento e-commerce: haveabook.pl

O site haveabook.pl é uma plataforma moderna dedicada à publicação e impressão, atendendo clientes exigentes de países escandinavos. O projeto foi criado com...

#Websites
Desenvolvimento e-commerce: haveabook.pl

#haveabook.pl, Editora e gráfica para clientes escandinavos

O haveabook.pl apresenta os serviços editoriais e de impressão de uma gráfica que trabalha para clientes escandinavos, permite pedir orçamento e documenta os trabalhos executados. A entrega foi em 2015 e o projeto demorou cerca de seis semanas.

#Uma encomenda de impressão não é um carrinho de compras

Começo por aqui porque é o ponto em que este projeto deixa de se parecer com uma loja online. Uma encomenda de impressão não é um carrinho, é uma ordem de produção com material anexado, e o material é o que decide se o trabalho corre bem.

O ficheiro de impressão costuma ser grande, e enviá-lo por um formulário comum falha contra os limites definidos no servidor e contra ligações que se perdem a meio. Isso obriga a tratar o carregamento como um processo com estado próprio e não como um campo de formulário, com a possibilidade de retomar em vez de recomeçar.

A parte menos óbvia vem a seguir. Um ficheiro que abre corretamente no navegador pode ser inútil em produção porque tem o espaço de cor errado ou porque lhe faltam sangrias. Uma verificação inicial no momento da receção faz por isso parte do processo e não é um extra: detetar esse erro à entrada custa um minuto, detetá-lo junto à máquina custa a tiragem inteira. É também a razão pela qual a plataforma guarda o ficheiro original tal como chegou, e não uma versão convertida: quando há uma discussão sobre o que foi entregue, a versão que conta é a que o cliente enviou.

#O cliente: Have a Book, de Gdynia

A Have a Book é uma empresa de Gdynia em atividade desde 2007, com sede na rua Wierzbowa e algumas dezenas de colaboradores. Descreve-se como ponto único de contacto para editoras educativas na Europa: paginação e pré-impressão, design gráfico, tipografia, impressão e encadernação, além de conversão de publicações para formatos eletrónicos com atenção à acessibilidade segundo as WCAG. Os clientes são editoras educativas da Noruega, França, Suíça e Bélgica.

Esse perfil de comprador decide a forma do site. Uma editora educativa não compra por impulso nem compra um livro: compra uma série de títulos em várias variantes, e a decisão é tomada por uma equipa em que alguém olha para o orçamento, alguém para o prazo e alguém para saber se a gráfica resolve um tipo específico de encadernação num manual que vai ser aberto diariamente durante três anos. Um site que sustenta essa decisão precisa de três coisas ao mesmo tempo: preço, prazo e prova da qualidade de execução.

#O orçamento é uma função, não um número numa tabela

Aqui o produto não tem preço. Um livro a imprimir é um conjunto de parâmetros, e o preço é o resultado de uma operação sobre esse conjunto. Formato, gramagem do papel, número de páginas, tipo de encadernação, cor ou preto, tiragem, acabamentos. Cada um deles altera o resultado e vários alteram-no aos saltos.

Isto não se contorna com uma tabela de preços. O número de combinações cresce de forma multiplicativa, portanto escrevê-las todas como linhas de catálogo deixa de ser exequível a partir do terceiro parâmetro. O cálculo tem de ser feito a pedido, a partir de uma estrutura de tarifas, e não lido de uma lista.

Há uma segunda característica deste setor, menos evidente e fácil de deixar passar no código. O custo de imprimir não cresce linearmente com a tiragem, porque preparar a máquina custa o mesmo para cem exemplares e para dez mil, e esse custo distribui-se pela tiragem. Além disso, mudar de formato pode levar o trabalho para outra máquina ou para outra folha, o que desloca o custo aos saltos e não de forma contínua. Uma implementação ingénua que interpola entre dois pontos da tabela dá respostas certas a meio do intervalo e falsas exatamente nos limiares, ou seja, onde o cliente pergunta mais. O cálculo tem de reproduzir os limiares e não uma curva traçada através deles.

#Quatro idiomas não são quatro conjuntos de traduções

O erro mais comum em projetos multilingues é tratar o idioma como um rótulo colado aos mesmos dados. Perante o mercado escandinavo, essa simplificação parte num sítio que ninguém verifica antes da entrega: a ordenação de listas.

Os alfabetos sueco e dano-norueguês contêm caracteres que o inglês não tem e, mais importante, colocam-nos noutra ordem. Não é enfeite tipográfico, é uma regra de ordenação. Uma lista de títulos ou de clientes ordenada por uma regra única para todos os idiomas ficará, para parte dos leitores, simplesmente desordenada. Na pesquisa acresce que uma expressão escrita sem o sinal diacrítico não encontra o registo que o tem. A solução é que a regra de comparação de texto seja uma propriedade da versão linguística e não uma definição global da base de dados.

O segundo ponto é distinguir idioma de mercado. Um cliente da Noruega e um da Suécia podem ler o site em inglês e ainda assim precisar de formatos de papel diferentes e de termos diferentes para descrever uma encadernação. O modelo de conteúdos tem de admitir que a variante linguística e a variante de mercado são dois eixos e não um. Os sites que os colam num só acabam a traduzir os mesmos dados uma segunda vez apenas para trocar uma tabela.

O terceiro ponto são os endereços. Cada versão linguística precisa de um URL próprio e duradouro e de uma declaração da relação com as restantes, caso contrário o motor de busca mostra a versão inglesa a um editor sueco, e isso significa, na prática, um pedido de orçamento que nunca chega.

#Principais funcionalidades e soluções

O catálogo de serviços é uma vista filtrada por categoria, tipo de serviço e especificação. A filtragem acontece na consulta e não no navegador, pela mesma razão que em qualquer catálogo técnico: o conjunto cresce, e enviá-lo inteiro para o navegador deixa de compensar muito antes de alguém reparar nisso a testar com dados de exemplo.

O catálogo tem ainda uma propriedade que o separa de um catálogo de produtos. Uma linha da oferta de uma gráfica não é uma coisa, é uma capacidade de execução, e descreve-se com intervalos: de tantas a tantas páginas, nestes formatos, em papel desta gramagem, com esta encadernação. Transposto para o modelo de conteúdos, isso significa que o atributo de uma entrada é por vezes um intervalo e não um valor, e que o filtro por especificação tem de perguntar pela pertença ao intervalo e não pela igualdade. Filtros construídos sobre igualdade parecem corretos durante a construção e cortam em silêncio metade da oferta assim que alguém escreve um número de páginas que não consta das variantes listadas.

O portefólio cumpre aqui uma função que não cumpre na maioria dos sites de serviços. Um editor avalia uma gráfica pelo aspeto do livro acabado, e uma fotografia de capa em baixa resolução não diz nada sobre como a lombada se comporta ao fim de um ano nem sobre como a cor assenta num determinado papel. As galerias têm de mostrar detalhe, ou seja, ficheiros grandes, e daí vem o trabalho específico para que a página de galeria não carregue tudo de uma vez. Pré-visualizações primeiro, versões completas na abertura, e os ficheiros entregues a partir da rede de distribuição de conteúdos e não do servidor de aplicação.

A acessibilidade merece nota própria, porque neste caso não é uma boa prática genérica. A Have a Book converte publicações para formatos eletrónicos com atenção às WCAG, ou seja, vende uma competência que o site tem de saber demonstrar. O site de uma empresa que vende publicações acessíveis não pode ter um catálogo impossível de operar com teclado nem tabelas de especificação sem ligação entre cabeçalhos e células. Uma tabela de parâmetros técnicos sem essa ligação é, para um leitor de ecrã, uma sequência de números sem significado, e aqui as tabelas de especificação são o conteúdo principal.

#Desafios de desenvolvimento e soluções

A primeira decisão foi onde vive a lógica de cálculo. É tentador calcular o preço no navegador, porque assim o resultado aparece de imediato e não custa nenhum pedido. Tentador e errado, porque a estrutura de tarifas passa a ser pública e uma cópia da lógica no navegador afasta-se do servidor na primeira alteração de preços que ninguém transporte nos dois sentidos. O cálculo fica no servidor, e o navegador limita-se a reunir parâmetros e a mostrar o resultado.

O segundo desafio foi a reprodutibilidade. Um preço dado na segunda-feira tem de poder ser reconstruído na quinta, mesmo que a tabela de tarifas tenha mudado entretanto. Por isso, junto ao orçamento fica guardado o conjunto completo de parâmetros e a versão da estrutura de tarifas com que foi calculado, e não apenas o número. Sem isso, qualquer alteração de preços invalida o histórico e não se consegue responder à pergunta simples de porque é que o cliente viu aquele valor. A mesma decisão arruma a cache: a chave do resultado guardado tem de conter a versão das tarifas, senão o site continua a devolver valores antigos durante algum tempo após a atualização, e fá-lo sem deixar rasto nos registos.

O terceiro desafio foi o desempenho com muito conteúdo multimédia. A cache em memória, com Redis e Memcached, encurta o trabalho da base de dados para aquilo que de qualquer forma passa pela camada de aplicação: conjuntos do catálogo, tabelas de tarifas, definições. A rede de distribuição assume os ficheiros. São dois problemas diferentes e vale a pena separá-los explicitamente, porque são confundidos com frequência: a cache em memória não acelera a transferência de uma imagem em resolução plena, e uma camada de borda não encurta nenhuma consulta à base de dados.

O quarto desafio foi a sincronização com os sistemas da empresa: cronogramas de produção e dados sobre disponibilidade de materiais. A solução é a aplicação não interrogar o sistema de produção durante a geração de uma página. Os dados são obtidos de forma independente e guardados em cache com um tempo de vida escolhido separadamente para cada origem, porque um cronograma muda de maneira diferente de uma tabela de tarifas. O mais importante, porém, é o comportamento em caso de falha: quando a origem está indisponível, a vista mostra o último valor conhecido ou uma variante sem aquela secção, nunca uma mensagem de erro. O visitante não tem por que saber que um sistema interno não está a responder neste momento.

#Ferramentas e tecnologias

O servidor assenta em PHP e MySQL, a camada interativa em JavaScript e pontos de acesso próprios, e os caminhos rápidos de leitura em cache em memória. A infraestrutura é de nuvem e o código está em controlo de versões, o que neste projeto tem um significado concreto: a tabela de tarifas é um dado e as regras que a aplicam são código, e só a separação das duas coisas permite mudar preços sem uma instalação nova e mudar uma regra sem tocar nos preços.

A camada de apresentação apoia-se em padrões responsivos e num pré-processador de folhas de estilo que mantém os pontos de quebra num único sítio. Num site com um formulário de mais de dez campos isso não é cosmética. O formulário de orçamento é a vista mais importante do projeto e, ao mesmo tempo, a mais difícil de compor em ecrã estreito, porque os campos estão ligados entre si e uma alteração num deles costuma ver-se noutro.

#Suporte e desenvolvimento da plataforma

A manutenção cobre atualizações, monitorização e alterações correntes. Num site com calculadora acresce uma obrigação que um site de apresentação não tem: as alterações à estrutura de tarifas têm de ser verificadas contra dados históricos. Uma alteração que parece correta num exemplo pode deslocar o resultado noutro limiar de tiragem, e quem dá por isso primeiro é o cliente que recebe um valor que não bate certo com o da semana anterior.

As atualizações passam primeiro por uma cópia de produção, e isso não é formalidade. Uma instalação vazia não tem um catálogo desta dimensão, nem quatro versões linguísticas da mesma entrada, nem galerias com ficheiros em resolução de produção, nem um conjunto de orçamentos guardados com versões diferentes de tarifa. São exatamente esses quatro pontos que partem numa atualização, e nenhum deles existe num ambiente de testes construído de raiz.

As cópias de segurança seguem a regra de sempre: uma cópia que ninguém restaurou é um ficheiro e não uma cópia. Aqui acresce que os ficheiros enviados pelos clientes são material de produção e não conteúdo do site, e que perdê-los é um acontecimento de outra classe do que perder a descrição de um serviço.

#Resumo e análise dos requisitos do cliente

O haveabook.pl tinha de responder a quatro requisitos ao mesmo tempo. Primeiro, apresentar uma oferta que não se deixa descrever por uma tabela de preços, porque o preço é o resultado de uma operação sobre parâmetros. Segundo, servir quatro versões linguísticas, três delas escandinavas, com as regras de ordenação próprias de cada uma. Terceiro, ligar-se aos sistemas da empresa sem transportar as falhas destes para o site. Quarto, receber material de produção e não apenas encomendas.

Desses quatro requisitos sai toda a construção: cálculo do lado do servidor, versionamento da estrutura de tarifas junto ao orçamento guardado, cache com chave que inclui essa versão, separação dos eixos de idioma e de mercado no modelo de conteúdos, e uma camada de entrega de ficheiros mantida longe do servidor de aplicação. O que não transita para outro projeto é esse modelo de conteúdos nem essas integrações, escritos para uma empresa e um briefing da categoria Websites. Um segundo projeto começa por uma análise de âmbito, e a proposta vem a seguir.

FAQ do artigo

Perguntas frequentes

Respostas práticas para aplicar o tema na execução real.

SEO-readyGEO-readyAEO-ready4 Q&A
Que âmbito teve o projeto haveabook.pl?#
haveabook.pl é um projeto da categoria Websites, entregue em 2025. Por detrás estão PHP, JavaScript, Redis, MySQL e HTML5.
Como correu a entrega de haveabook.pl?#
A construção durou cerca de seis semanas e entrou em produção em 2025. Assenta em PHP, JavaScript, Redis, MySQL e HTML5. O layout veio do cliente. Sobre ele construí os templates e o modelo de conteúdos, e testei os caminhos que carregam tráfego numa cópia de produção, não numa instalação vazia.
O que foi mais difícil tecnicamente em haveabook.pl?#
Desempenho sob tráfego real e cache. haveabook.pl exigiu um ambiente de teste próximo da produção.
Que parte de haveabook.pl pode ser reaproveitada noutro projeto?#
A camada técnica transita: PHP, JavaScript, Redis, MySQL e HTML5. No projeto seguinte tem um aspeto parecido. O que não transita é o modelo de conteúdos e as integrações, escritos para os dados de um cliente e um briefing da categoria Websites. Um segundo projeto começa por uma análise de âmbito, e a proposta vem a seguir.

Precisa de FAQ adaptado ao setor e mercado? Criamos uma versão alinhada com os seus objetivos de negócio.

Fale connosco