Recentemente, encontrei um bigode que afirma ser um modelo sem lógica .
No entanto, não há nenhuma explicação de por que ele foi projetado de forma sem lógica. Em outras palavras, qual é a vantagem do modelo sem lógica?
Recentemente, encontrei um bigode que afirma ser um modelo sem lógica .
No entanto, não há nenhuma explicação de por que ele foi projetado de forma sem lógica. Em outras palavras, qual é a vantagem do modelo sem lógica?
Respostas:
Em outras palavras, impede que você dê um tiro no próprio pé. Nos velhos tempos de JSP, era muito comum ter arquivos JSP polvilhados com código Java, o que tornava a refatoração muito mais difícil, já que seu código estava espalhado.
Se você evitar a lógica nos modelos por design (como o bigode faz), será obrigado a colocar a lógica em outro lugar, de modo que seus modelos ficarão organizados.
Outra vantagem é que você é forçado a pensar em termos de separação de interesses: seu controlador ou código lógico terá que fazer a massagem de dados antes de enviar os dados para a IU. Se mais tarde você trocar seu modelo por outro (digamos que você comece a usar um mecanismo de modelo diferente), a transição seria fácil porque você só precisava implementar os detalhes da IU (uma vez que não há lógica no modelo, lembre-se).
Tenho a sensação de que estou quase sozinho na minha opinião, mas estou firmemente no campo oposto. Não acredito que a possível combinação de lógica de negócios em seus modelos seja razão suficiente para não usar todo o poder de sua linguagem de programação.
O argumento usual para modelos sem lógica é que, se você tiver acesso total à sua linguagem de programação, poderá misturar lógica que não tem lugar em um modelo. Acho que isso se assemelha ao raciocínio de que você deve usar uma colher para cortar carne, porque você pode se cortar se usar uma faca. Isso é verdade, mas você será muito mais produtivo se usar o último, embora com cuidado.
Por exemplo, considere o seguinte snippet de modelo usando bigode :
{{name}}:
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
Eu posso entender isso, mas acho o seguinte (usando o sublinhado ) muito mais simples e direto:
<%- name %>:
<ul>
<% _.each(items, function(i){ %>
<li><%- i %></li>
<% }); %>
</ul>
Dito isso, eu entendo que os modelos sem lógica têm vantagens (por exemplo, eles podem ser usados com várias linguagens de programação sem alterações). Acho que essas outras vantagens são muito importantes. Só não acho que sua natureza sem lógica seja uma delas.
name
e items
pode conter JavaScript.
O bigode não tem lógica?
Não é este:
{{#x}}
foo
{{/x}}
{{^x}}
bar
{{/x}}
Muito parecido com isso?
if x
"foo"
else
"bar"
end
E isso não é muito semelhante à (leia-se: quase uma definição de) lógica de apresentação?
if x > 0 && x < 10
) ... Então, embora seja possível usar o Bigode com ou sem lógica, você decide. Afinal, é apenas uma ferramenta.
Um modelo sem lógica é um modelo que contém buracos para você preencher, e não como você os preenche. A lógica é colocada em outro lugar e mapeada diretamente para o modelo. Essa separação de interesses é ideal porque o modelo pode ser facilmente construído com uma lógica diferente ou mesmo com uma linguagem de programação diferente.
Chamamos isso de "sem lógica" porque não há instruções if, cláusulas else ou loops for. Em vez disso, existem apenas tags. Algumas tags são substituídas por um valor, outras nada e outras por uma série de valores. Este documento explica os diferentes tipos de tags Mustache.
O outro lado da moeda é que, em uma tentativa desesperada de manter a lógica de negócios fora da apresentação, você acaba colocando muita lógica de apresentação no modelo. Um exemplo comum pode ser que você queira colocar classes "ímpares" e "pares" em linhas alternadas em uma tabela, o que pode ser feito com um operador de módulo simples no modelo de visualização. Mas se o seu modelo de visualização não permite que você faça isso, então nos dados do seu modelo você não deve apenas armazenar qual linha é ímpar ou par, mas dependendo de quão limitado é o seu mecanismo de modelo, você pode até mesmo precisar poluir o seu modelo com os nomes das classes CSS reais. As visualizações devem ser separadas de Modelos, ponto final. Mas os modelos também devem ser agnósticos quanto ao modo de exibição, e é isso que muitos desses mecanismos de modelo "sem lógica" fazem você esquecer. A lógica vai em ambos os lugares,realmente faz para decidir corretamente para onde vai. É uma questão de apresentação ou de negócios / dados? Em um esforço para ter 100% de vistas primitivas, a poluição apenas pousa em outro lugar menos visível, mas igualmente inadequado.
Há um movimento crescente de volta na outra direção e , com sorte, as coisas vão se concentrar em algum lugar no meio-termo mais razoável.
Isso torna seus modelos mais limpos e força você a manter a lógica em um lugar onde possa ser devidamente testada na unidade.
Essa conversa parece quando os monges da Idade Média debatiam sobre quantos anjos cabem na ponta de um alfinete. Em outras palavras, está começando a se sentir religioso, fútil e focado incorretamente.
Segue-se um mini-discurso (sinta-se à vontade para ignorar):
Se você não quiser continuar lendo ... Minha resposta curta ao tópico acima é: Não concordo com os modelos sem lógica. Eu penso nisso como uma forma de programação de extremismo. :-) :-)
Agora meu discurso continua a todo vapor: :-)
Acho que quando você leva muitas ideias ao extremo, o resultado se torna ridículo. E às vezes (isto é, este tópico), o problema é que levamos a ideia "errada" ao extremo.
Remover toda a lógica da visão é "ridículo" e uma ideia errada.
Dê um passo para trás por um momento.
A pergunta que precisamos nos fazer é por que remover a lógica? O conceito, obviamente, é separação de interesses . Mantenha o processamento da visualização o mais separado possível da lógica de negócios. Por que fazer isso? Ele nos permite trocar visualizações (para plataformas diferentes: móvel, navegador, desktop, etc.) e nos permite trocar mais facilmente o fluxo de controle, sequência de página, alterações de validação, alterações de modelo, acesso de segurança, etc. Também quando a lógica é removido das visualizações (especialmente visualizações da web), torna as visualizações muito mais legíveis e, portanto, mais fáceis de manter. Eu entendo isso e concordo com isso.
No entanto, o foco principal deve ser na separação de interesses. Visualizações não 100% sem lógica. A lógica dentro das visualizações deve se relacionar a como renderizar o "modelo". No que me diz respeito, a lógica nas visualizações é perfeitamente adequada. Você pode ter uma lógica de exibição que não seja uma lógica de negócios.
Sim, no tempo em que escrevíamos páginas JSPs, PHP ou ASP com pouca ou nenhuma separação entre lógica de código e lógica de exibição, a manutenção desses aplicativos da web era um pesadelo absoluto. Acredite, eu sei, eu criei e depois mantive algumas dessas monstruosidades. Foi durante essa fase de manutenção que realmente entendi (visceralmente) o erro dos meus caminhos e dos dos meus colegas. :-) :-)
Assim, o édito do alto (os especialistas da indústria) tornou-se, você deve estruturar seus aplicativos da web usando algo como um controlador de visão frontal (que despacha para manipuladores ou ações [escolha sua estrutura da web]) e suas visualizações não devem conter código . As visualizações se tornariam modelos estúpidos.
Portanto, concordo em geral com o sentimento acima, não pelas especificidades dos itens do edital, mas sim pela motivação por trás do edital - que é o desejo de separações de preocupações entre visão e lógica de negócios.
Em um projeto em que estive envolvido, tentamos seguir a ideia da visão sem lógica ao extremo ridículo. Tínhamos um mecanismo de template desenvolvido internamente que nos permitiria renderizar objetos de modelo em html. Era um sistema simples baseado em tokens. Foi terrível por um motivo muito simples. Às vezes, em uma visão, tínhamos que decidir se devo exibir este pequeno trecho de HTML ... ou não ... A decisão geralmente é baseada em algum valor no modelo. Quando você não tem absolutamente nenhuma lógica em vista, como você faz isso? Bem, você não pode. Tive algumas discussões importantes com nosso arquiteto sobre isso. O pessoal de HTML do front-end que escreveu nossas visualizações ficou completamente paralisado quando se deparou com isso e ficou muito estressado porque não poderia atingir seus objetivos simples. Então, apresentei o conceito de uma instrução IF simples em nosso mecanismo de modelagem. Não posso descrever para você o alívio e a calma que se seguiram. O problema foi resolvido com um conceito simples de declaração IF em nossos modelos! De repente, nosso motor de modelagem ficou bom.
Então, como entramos nessa situação tola e estressante? Nós nos concentramos no objetivo errado. Seguimos a regra, você não deve ter nenhuma lógica em suas opiniões. Isso estava errado. Eu acho que a "regra de ouro" deve ser, minimizar essa quantidade de lógica em suas opiniões. Porque se você não fizer isso, você pode inadvertidamente permitir que a lógica de negócios apareça na visão - o que viola a separação de interesses.
Eu entendo que quando você declara que "Você não deve ter lógica nas visualizações", fica fácil saber quando você está sendo um "bom" programador. (Se essa é sua medida de bondade). Agora tente implementar um aplicativo da web até mesmo de complexidade média com a regra acima. Não é tão fácil de fazer.
Para mim, a regra da lógica nas visualizações não é tão clara e, francamente, é onde eu quero que esteja.
Quando vejo muita lógica nas visualizações, detecto um cheiro de código e tento eliminar a maior parte da lógica das visualizações - tento garantir que a lógica de negócios resida em outro lugar - tento separar as preocupações. Mas quando começo a conversar com pessoas que dizem que devemos remover toda a lógica da visão, bem, para mim, isso soa como fanatismo, pois sei que você pode acabar em situações como as que descrevi acima.
Estou farto do meu discurso retórico. :-)
Felicidades,
David
O melhor argumento que inventei para modelos sem lógica é que você pode usar exatamente os mesmos modelos no cliente e no servidor. No entanto, você realmente não precisa do sem lógica, apenas um que tenha sua própria "linguagem". Concordo com as pessoas que se queixam de que o bigode é limitador inutilmente. Obrigado, mas sou um menino crescido e posso manter meus modelos limpos sem a sua ajuda.
Outra opção é apenas encontrar uma sintaxe de modelo que usa uma linguagem com suporte no cliente e no servidor, ou seja, javascript no servidor usando node.js ou você pode usar um interpretador js e json por meio de algo como therubyracer.
Então você poderia usar algo como haml.js, que é muito mais limpo do que qualquer um dos exemplos fornecidos até agora e funciona muito bem.
Em uma frase: Sem lógico significa que o mecanismo de modelo em si é menos complexo e, portanto, ocupa menos espaço e há menos maneiras de se comportar inesperadamente.
Mesmo que a pergunta seja antiga e respondida, gostaria de adicionar meus 2 centavos (o que pode soar como um discurso retórico, mas não é, é sobre limitações e quando elas se tornam inaceitáveis).
O objetivo de um modelo é renderizar algo, não executar lógica de negócios. Agora, há uma linha tênue entre não ser capaz de fazer o que você precisa fazer em um modelo e ter "lógica de negócios" neles. Mesmo sendo muito otimista em relação ao Mustache e tentado usá-lo, acabei não conseguindo fazer o que preciso em casos bem simples.
A "massagem" dos dados (para usar as palavras na resposta aceita) pode se tornar um problema real - nem mesmo caminhos simples são suportados (algo que o Handlebars.js aborda). Se eu tiver dados de exibição e precisar ajustá-los toda vez que quiser renderizar algo porque meu mecanismo de modelo é muito limitado, isso não será útil no final. E derrota parte da independência de plataforma que o bigode reivindica para si; Tenho que duplicar a lógica de massagem em todos os lugares.
Dito isso, depois de alguma frustração e depois de tentar outros motores de template, acabamos criando o nosso próprio (... mais um ...), que usa uma sintaxe inspirada nos templates .NET Razor. Ele é analisado e compilado no servidor e gera uma função JS simples e autocontida (na verdade, como módulo RequireJS) que pode ser chamada para "executar" o modelo, retornando uma string como resultado. A amostra fornecida por brad ficaria assim ao usar nosso motor (que pessoalmente considero muito superior em legibilidade em comparação com o bigode e o sublinhado):
@name:
<ul>
@for (items) {
<li>@.</li>
}
</ul>
Outra limitação sem lógica nos atingiu ao chamar parciais com Mustache. Embora parciais sejam suportados pelo Mustache, não há possibilidade de personalizar os dados a serem transmitidos primeiro. Portanto, em vez de ser capaz de criar um modelo modular e reutilizar pequenos blocos, acabarei fazendo modelos com código repetido neles.
Resolvemos isso implementando uma linguagem de consulta inspirada em XPath, que chamamos de JPath. Basicamente, em vez de usar / para atravessar para os filhos, usamos pontos, e não apenas strings, números e literais booleanos são suportados, mas também objetos e matrizes (assim como JSON). A linguagem não tem efeitos colaterais (o que é obrigatório para modelos), mas permite "massagear" os dados conforme necessário, criando novos objetos literais.
Digamos que queremos renderizar uma tabela de "grade de dados" com cabeçalhos personalizáveis e links para ações nas linhas e, posteriormente, adicionar linhas dinamicamente usando jQuery. As linhas, portanto, precisam ser parciais se eu não quiser duplicar o código. E é aí que começa o problema se algumas informações adicionais, como quais colunas devem ser renderizadas, fizerem parte do modelo de visualização, e o mesmo para essas ações em cada linha. Aqui estão alguns códigos reais de trabalho usando nosso modelo e mecanismo de consulta:
Modelo de tabela:
<table>
<thead>
<tr>
@for (columns) {
<th>@title</th>
}
@if (actions) {
<th>Actions</th>
}
</tr>
</thead>
<tbody>
@for (rows) {
@partial Row({ row: ., actions: $.actions, columns: $.columns })
}
</tbody>
</table>
Modelo de linha:
<tr id="@(row.id)">
@for (var $col in columns) {
<td>@row.*[name()=$col.property]</td>
}
@if (actions) {
<td>
@for (actions) {
<button class="btn @(id)" value="@(id)">@(name)...</button>
}
</td>
}
</tr>
Invocação do código JS:
var html = table({
columns: [
{ title: "Username", property: "username" },
{ title: "E-Mail", property: "email" }
],
actions: [
{ id: "delete", name: "Delete" }
],
rows: GetAjaxRows()
})
Ele não tem nenhuma lógica de negócios, mas é reutilizável e configurável, além de não ter efeitos colaterais.
row
objeto, em vez de usar nomes estáticos. Por exemplo, se $col.property == 'Something'
então isso resultaria no conteúdo de row.Something
.
Aqui estão 3 maneiras de renderizar uma lista, com contagens de caracteres. Todos, exceto o primeiro e o mais curto, estão em linguagens de modelagem sem lógica.
CoffeeScript (com o construtor Reactive Coffee DSL) - 37 caracteres
"#{name}"
ul items.map (i) ->
li i
Knockout - 100 caracteres
<span data-bind="value: name"/>
<ul data-bind="foreach: items">
<li data-bind="value: i"/>
</ul>
Guiador / bigode - 66 caracteres
{{name}}:
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
Sublinhado - 87 caracteres
<%- name %>:
<ul>
<% _.each(items, function(i){ %>
<li><%- i %></li>
<% }); %>
</ul>
A promessa de modelos sem lógica era, suponho, que pessoas com conjuntos de habilidades mais amplos seriam capazes de gerenciar modelos sem lógica sem dar um tiro no próprio pé. No entanto, o que você vê nos exemplos acima é que, quando você adiciona uma linguagem de lógica mínima à marcação baseada em string, o resultado é mais complexo, não menos. Além disso, parece que você está fazendo PHP da velha escola.
Obviamente, não me oponho a manter a "lógica de negócios" (computação extensiva) fora dos modelos. Mas acho que, ao dar a eles uma pseudo-linguagem para lógica de exibição em vez de uma linguagem de primeira classe, o preço está pago. Não apenas mais para digitar, mas uma mistura hedionda de mudança de contexto que alguém precisa ler.
Concluindo, não consigo ver a lógica dos modelos sem lógica, então eu diria que sua vantagem é nula para mim, mas eu respeito o fato de muitos na comunidade verem isso de forma diferente :)
As principais vantagens de usar modelos sem lógica são:
Concordo com o Brad: o underscore
estilo é mais fácil de entender. Mas devo admitir que o açúcar sintático pode não agradar a todos. Se _.each
for um pouco confuso, você pode usar um for
loop tradicional .
<% for(var i = 0; i < items.length; i++) { %>
<%= items[i] %>
<% } %>
É sempre bom se você puder recorrer a construções padrão, como for
ou if
. Basta usar <% if() %>
ou <% for() %>
enquanto Mustache
usa um pouco de neologismo para if-then-else
(e confuso se você não leu a documentação):
{{#x}}
foo
{{/x}}
{{^x}}
bar
{{/x}}
O mecanismo de modelo é ótimo quando você pode obter modelos aninhados facilmente ( underscore
estilo):
<script id="items-tmpl" type="text/template">
<ul>
<% for(var i = 0; i < obj.items.length; i++) { %>
<%= innerTmpl(obj.items[i]) %>
<% } %>
</ul>
</script>
<script id="item-tmpl" type="text/template">
<li>
<%= name %>
</li>
</script>
var tmplFn = function(outerTmpl, innerTmpl) {
return function(obj) {
return outerTmpl({obj: obj, innerTmpl: innerTmpl});
};
};
var tmpl = tmplFn($('#items-tmpl').html(), $('#item-tmpl').html());
var context = { items: [{name:'A',{name:'B'}}] };
tmpl(context);
Basicamente, você passa seu tmpl interno como uma propriedade de seu contexto. E chamá-lo de acordo. Doce :)
A propósito, se a única coisa em que você está interessado é o mecanismo de template, use a implementação de template independente. Possui apenas 900 caracteres quando reduzido (4 linhas longas):