O que há de errado com um nó de extremidade retornando dados HTML em vez de JSON?

75

Quando comecei a aprender PHP (cerca de 5 ou 6 anos atrás), aprendi sobre Ajax , e passei pelas "fases":

  1. Seu servidor retorna dados HTML e você os coloca dentro de um innerHTML do DOM
  2. Você aprende sobre formatos de transferência de dados, como XML (e diz "oooh, então é para isso que é usado) e, em seguida, JSON.
  3. Você retorna JSON e cria sua interface de usuário usando o código JavaScript vanilla
  4. Você muda para o jQuery
  5. Você aprende sobre APIs, cabeçalhos, códigos de status HTTP, REST , CORS e Bootstrap
  6. Você aprende SPA e os frameworks frontend ( Reagir , Vue.js e AngularJS ) e o padrão da API JSON.
  7. Você recebe algum código herdado da empresa e, ao inspecioná-lo, descobre que eles fazem o que é descrito na etapa 1.

Como trabalhei com essa base de código legado, nem considerei que poderia retornar HTML (quero dizer, somos profissionais agora, certo?), por isso tive dificuldade em procurar o ponto de extremidade JSON que estava retornando os dados que as chamadas do Ajax preenchem. Não foi até que eu perguntei "o programador" que ele me disse que estava retornando HTML e sendo anexado diretamente ao DOM com innerHTML.

Claro, isso foi difícil de aceitar. Comecei a pensar em maneiras de refatorar isso nos terminais JSON, pensando em testar os terminais e assim por diante. No entanto, esta base de código não tem testes. Não um único. E são mais de 200 mil linhas. É claro que uma das minhas tarefas inclui propor abordagens para testar a coisa toda, mas no momento não estamos lidando com isso ainda.

Então, eu estou em nenhum lugar, em um canto, imaginando: se não tivermos testes, então não temos nenhum motivo especial para criar esse endpoint JSON (já que não é "reutilizável": ele literalmente retorna dados que só se encaixam nessa parte do aplicativo, mas acho que isso já estava implícito, já que ... retorna dados HTML).

O que exatamente está errado ao fazer isso?

    
por Christopher Francisco 14.03.2017 / 14:47
fonte

12 respostas

112

What's actually wrong with an endpoint returning HTML rather than JSON data?

Nada, realmente. Cada aplicativo tem requisitos diferentes e pode ser que seu aplicativo não tenha sido projetado para ser um SPA.

Pode ser que essas belas estruturas que você citou (Angular, Vue, React, etc ...) não estivessem disponíveis em tempo de desenvolvimento, ou não fossem coisinhas de empresa "aprovadas" para serem usadas em sua organização.

Vou lhe dizer uma coisa: um endpoint que retorna HTML reduz sua dependência em bibliotecas JavaScript e reduz a carga no navegador do usuário, já que ele não precisará interpretar / executar código JS para criar objetos DOM - o HTML é já existe, é apenas uma questão de analisar os elementos e processá-los. Claro, isso significa que estamos falando de uma quantidade razoável de dados. 10 megabytes de dados HTML não são razoáveis.

Mas como não há nada de errado em retornar HTML, o que você está perdendo por não usar JSON / XML é basicamente a possibilidade de usar seu terminal como uma API. E aqui está a maior questão: ela realmente precisa ser uma API?

Relacionados: Não há problema em retornar HTML de uma API JSON?

    
por 14.03.2017 / 15:29
fonte
50

JSON e HTML cumprem dois propósitos semânticos diferentes.

Se você estiver preenchendo uma página da web com dados, use JSON. Se você estiver construindo uma página da Web a partir de partes de páginas da Web, use HTML.

Eles podem soar como se fossem a mesma coisa, mas eles não são, de forma alguma. Por um lado, quando você está construindo uma parte de uma página da web usando HTML retornado pelo servidor, você está trabalhando no lado do servidor. Quando você está vinculando dados a uma página da web, você está trabalhando < em> lado do cliente.

Além disso, você precisa ter cuidado com o HTML para não se vincular a uma página específica. O ponto inteiro de renderizar páginas parciais dessa maneira é que as parciais são reutilizáveis, e se você tornar a parcial muito específica, ela não será composta para outras páginas. O JSON não tem esse problema, porque são apenas dados, não a estrutura da página da Web.

    
por 14.03.2017 / 17:08
fonte
21

O principal problema é que ele acopla o servidor ao cliente, que deve conhecer a estrutura HTML. Isso também torna os endpoints mais difíceis de reutilizar em novas formas ou novas aplicações.

Retornando dados simples e permitindo que o cliente os renderize diminua o acoplamento e aumente a flexibilidade e testabilidade - você pode executar testes de unidade no cliente para dados simulados e executar testes de unidade no servidor para testar os dados desejados.

    
por 14.03.2017 / 17:03
fonte
14

Eu acho que você tem um pouco para trás. Você diz:

we have no test whatsoever, so we have no particular reason to create this JSON endpoint

Um motivo para usar um endpoint adequado seria para que você pudesse testá-lo. Eu diria que não ter testes é uma boa razão para começar a escrever alguns. Isto é, se existe alguma lógica que seria adequada para testar.

200k linhas de código são muito para refatorar e são difíceis de manter. Quebrar alguns endpoints e testá-los pode ser um bom começo.

Outro motivo pode ser separar o servidor do cliente. Se, num futuro distante, o design ou layout do aplicativo for alterado, será mais fácil trabalhar com um formato de dados adequado do que a saída HTML. Em um mundo ideal, você teria apenas que mudar o cliente e não tocar no servidor.

    
por 14.03.2017 / 15:06
fonte
6

Existem 3 maneiras (pelo menos?) de criar uma página da Web:

  • Gere todo o lado do servidor de páginas.
  • Retorne uma página bare bones do código do servidor mais (JavaScript) e faça a página buscar seus dados e renderize no lado do cliente HTML.
  • Retorna uma página parcial mais o código e faz com que o código busque blocos pré-renderizados de HTML que podem ser inseridos na página.

O primeiro está bem. O segundo também está bem. É o último problema.

O motivo é simples: agora você dividiu a construção da página HTML em partes completamente desconectadas. O problema é de manutenção. Agora você tem duas entidades separadas encarregadas de gerenciar os detalhes da interface do usuário. Então você tem que manter CSS e outros detalhes semelhantes em sincronia entre as duas partes separadas. Você mudou a largura da barra lateral? Ótimo. Agora, o fragmento HTML que retorna causa a rolagem horizontal porque suas suposições sobre a largura da barra lateral não são mais válidas. Você mudou a cor de fundo para esse bloco? Ótimo, agora a cor da fonte do seu fragmento HTML colide porque assumiu uma cor de fundo diferente e alguém esqueceu de testar esse endpoint.

O ponto é que você agora dividiu o conhecimento que deve ser centralizado em um único lugar (a lógica da apresentação), e isso torna mais difícil garantir que todas as partes se encaixem corretamente. Ao usar uma API JSON, você pode manter toda essa lógica apenas no front end, ou pode manter tudo isso em seus modelos do lado do servidor, se você renderizar seus dados em HTML para começar. Trata-se de manter o conhecimento / lógica da apresentação em um único lugar, para que possa ser gerenciado de forma consistente e como parte de um único processo. HTML / CSS / JS é difícil o suficiente para se manter em linha reta sem dividi-lo em um monte de pequenos pedaços.

APIs JSON também têm o benefício adicional de disponibilizar os dados de forma totalmente independente da lógica de apresentação. Isso permite que vários apresentadores diferentes , como um aplicativo para dispositivos móveis e uma página da Web, consumam os mesmos dados. Em particular, permite consumir os dados sem um navegador (como aplicativos móveis ou tarefas noturnas do cron); esses consumidores podem nem conseguir analisar o HTML. (Isso, é claro, depende necessariamente de uma situação em que os dados são os mesmos entre os diferentes consumidores, ou pode-se usar um subconjunto do outro.) No entanto, se você precisa dessa capacidade, depende dos requisitos de seu aplicativo específico ao gerenciar sua apresentação lógica é necessária independentemente. Eu diria que, se você implementá-lo na frente, você estará mais bem preparado para o crescimento futuro.

    
por 15.03.2017 / 06:31
fonte
4

Não há nada errado em princípio . A questão é: o que você quer alcançar?

O JSON é perfeito para transmitir dados. Se você enviar HTML e esperar que o cliente extraia os dados do HTML, isso é lixo.

Por outro lado, se você quiser transmitir o HMTL que será renderizado como HTML, envie-o como HTML - em vez de empacotá-lo em uma string, transformando a string em JSON , transmitindo JSON, decodificando-o do outro lado, obtendo uma string e extraindo o HTML da string.

E ontem encontrei o código que coloca dois itens em uma matriz, transformei a matriz em JSON, coloquei o JSON em uma string, coloquei a string dentro de uma matriz, transformei a matriz inteira em JSON, enviei-a para o cliente , que decodificou o JSON, obteve uma matriz contendo uma string, pegou a string, extraiu o JSON da string, decodificou o JSON e obteve uma matriz com dois itens. Não faça isso.

    
por 16.03.2017 / 15:55
fonte
3

Eu diria que não há nada de errado com o servidor retornando um fragmento HTML e a UI designando-o para .innerHTML de algum elemento. Esta é, na minha opinião, a maneira mais fácil de desenvolver código JavaScript assíncrono. O benefício é que o mínimo possível é feito usando JavaScript e, tanto quanto possível, é feito em um ambiente de back-end controlado. Lembre-se de que o suporte a JavaScript nos navegadores varia, mas seu back-end sempre tem a mesma versão dos componentes de back-end, o que significa que fazer o máximo possível no back-end significará o mínimo possível de incompatibilidades de versão.

Agora, às vezes, você quer mais do que apenas um fragmento de HTML. Por exemplo, um código de status e um fragmento de HTML. Em seguida, você pode usar um objeto JSON que tenha dois membros, statusCode e HTML, dos quais o segundo possa ser atribuído a .innerHTML de algum elemento após a verificação do statusCode. Portanto, usar JSON e usar innerHTML não são abordagens exclusivas alternativas; eles podem ser usados juntos.

Usando o JSON, você pode até ter vários fragmentos HTML na mesma resposta, que são atribuídos ao .innerHTML de vários elementos.

Em resumo: use .innerHTML. Torna o seu código compatível com tantas versões de navegador quanto possível. Se precisar de mais, use JSON e .innerHTML juntos. Evite XML.

    
por 14.03.2017 / 15:14
fonte
3

Tudo depende do objetivo da API, mas geralmente o que você descreve é uma violação bastante strong da separação de interesses :

Em um aplicativo moderno, o código da API deve ser responsável pelos dados, e o código do cliente deve ser responsável pela apresentação.

Quando sua API retorna HTML, você está unindo seus dados e sua apresentação. Quando a API retorna HTML, a única coisa que você pode fazer (facilmente) com esse HTML é exibi-lo como parte de uma página maior. De um ângulo diferente, a única coisa boa para a API é fornecer sua página com HTML. Além disso, você espalhou seu HTML no código do cliente e do servidor. Isso pode tornar a manutenção uma dor de cabeça.

Se sua API retornar JSON ou alguma outra forma de dados puros, ela se tornará muito mais útil. O aplicativo existente ainda pode consumir esses dados e apresentá-los adequadamente. Agora, porém, outras coisas podem usar a API para acessar os mesmos dados. Novamente, também, a manutenção é mais fácil - todo o HTML reside em um lugar, portanto, se você quiser reformular todo o site, não precisará alterar sua API.

    
por 15.03.2017 / 00:26
fonte
2

HTML está vinculado a um design e uso específicos.

Com HTML, se você quiser alterar o layout da página, precisará alterar como o html é gerado pela chamada do servidor. Geralmente, isso requer um programador de backend. Agora você tem programadores de back-end, que por definição não são os melhores escritores de html, lidando com essas atualizações.

Com o JSON, se o layout da página for alterado, a chamada do servidor JSON existente não precisará necessariamente ser alterada. Em vez disso, o desenvolvedor front-end, ou até mesmo o designer, atualiza o modelo para produzir o HTML diferente que você deseja dos mesmos dados básicos.

Além disso, o JSON pode se tornar a base para outros serviços. Você pode ter diferentes funções que precisam ver os mesmos dados básicos de maneiras diferentes. Por exemplo, você pode ter um site do cliente que mostre dados sobre um produto em uma página do pedido e uma página interna de vendas para os representantes que mostrem os mesmos dados em um layout muito diferente, talvez junto com outras informações não disponíveis para clientes em geral. Com o JSON, a mesma chamada de servidor pode ser usada em ambas as visualizações.

Finalmente, o JSON pode ser melhor escalonado. Nos últimos anos, nós nos esforçamos demais com os frameworks javascript do lado do cliente. Acho que é hora de dar um passo para trás e começar a pensar sobre o javascript que estamos usando e como isso afeta o desempenho do navegador ... especialmente em dispositivos móveis. Dito isso, se você estiver executando um site grande o suficiente para exigir um farm de servidores ou cluster, em vez de um único servidor, o JSON poderá ser dimensionado melhor. Os usuários darão a você tempo de processamento em seus navegadores gratuitamente e, se você tirar vantagem disso, poderá reduzir a carga do servidor em uma implantação grande. O JSON também usa menos largura de banda, então, novamente, se você for grande o suficiente e usá-lo adequadamente, o JSON é mensuravelmente mais barato. É claro, ele também pode se tornar pior, se você acabar fornecendo bibliotecas de 40 KB para analisar 2 KB de dados em 7 KB de html, então novamente: vale a pena estar ciente do que você está fazendo. Mas o potencial está lá para o JSON melhorar o desempenho e os custos.

    
por 16.03.2017 / 17:15
fonte
1

Não há nada errado com esse endpoint se ele atender aos seus requisitos. Se for necessário cuspir o html que um consumidor conhecido possa analisar com eficácia, por que não?

O problema é que, para o caso geral, você deseja que seus terminais especifiquem uma carga útil que seja bem formada e analisável de forma eficaz por um analisador padrão. E, efetivamente, analisável, quero dizer, analisável de forma declarativa.

Se o seu cliente for forçado a ler a carga útil e forçar a abertura de bits de informação a partir dela com loops e instruções if, ela não será analisável. E o HTML, sendo assim, é muito perdoado em não exigir que ele seja bem formado.

Agora, se você tiver certeza de que seu HTML é compatível com xml, então você é ouro.

Com isso dito, tenho um problema significativo com isso:

I'm gonna tell you this: an endpoint that returns HTML reduces your dependency on JavaScript libraries and reduces the load on the user browser since it won't need to interpret/execute JS code to create DOM objects - the HTML is already there, it's just a matter of parsing the elements and rendering them. Of course, this means we're talking about a reasonable amount of data. 10 megabytes of HTML data isn't reasonable.

É uma má ideia, não importa como você a corte. Décadas de experiência industrial coletiva nos mostraram que, em geral, é uma boa idéia separar dados (ou modelos) de sua exibição (ou visualização).

Aqui você está combinando os dois com o propósito de acelerar a execução de código JS. E isso é uma otimização micro.

Eu nunca vi isso como uma boa ideia, exceto em sistemas muito triviais.

Meu conselho? Não faça isso. HC SVNT DRACONES , YMMV, etc.

    
por 17.03.2017 / 14:00
fonte
0

O JSON é apenas uma apresentação textual de dados estruturados. Um cliente naturalmente precisa ter um analisador para processar dados, mas virtualmente todos os idiomas têm funções do analisador JSON. É muito mais eficiente usar o analisador JSON do que usar o analisador de HTML. Leva pouca pegada. Não é assim com um analisador de HTML.

No PHP, você usa apenas json_encode($data) e cabe ao cliente do outro lado analisá-lo. E quando você busca dados JSON de um serviço da Web, você usa apenas $data=json_decode($response) e pode decidir como usar dados como faria com variáveis.

Suponhamos que você desenvolva um aplicativo para um dispositivo móvel. Por que você precisa do formato HTML quando aplicativos móveis raramente usam o navegador da Web para analisar dados? Muitos aplicativos para dispositivos móveis usam o JSON (formato mais comum) para trocar dados.

Considerando que os celulares geralmente têm planos de medição, por que você quer usar HTML que consome muito mais largura de banda do que o JSON?

Por que usar o HMTL quando o HTML é limitado em seu vocabulário e o JSON pode definir dados? {"person_name":"Jeff Doe"} é mais informativo do que o HTML pode fornecer sobre seus dados, pois define apenas estrutura para analisadores de HTML, não define dados.

O JSON não tem nada a ver com HTTP. Você pode colocar o JSON em um arquivo. Você pode usá-lo para configurações. O compositor usa o JSON. Você pode usá-lo para salvar variáveis simples em arquivos também.

    
por 17.03.2017 / 00:17
fonte
0

É difícil categorizar um certo ou errado. IMO, as perguntas que vou fazer são: " deveria " ou " pode ser feito com menos? ".

Cada endpoint deve se esforçar para se comunicar com o mínimo de conteúdo possível. A relação sinal-ruído é normalmente códigos HTTP < JSON < XHTML. Na maioria das situações, é bom escolher o protocolo menos barulhento.

Eu discordo do ponto sobre o carregamento do navegador do cliente pelo @machado, já que nos navegadores modernos isso não é um problema. A maioria deles está equipada para lidar com códigos HTTP e respostas JSON muito bem. E embora você não tenha testes no momento, a manutenção a longo prazo de um protocolo menos ruidoso seria mais barata do que a acima.

    
por 15.03.2017 / 10:16
fonte

Tags