Récemment, je suis tombé sur une moustache qui est prétendument un modèle sans logique .
Cependant, rien n'explique pourquoi il est conçu de manière sans logique. En un autre mot, quel est l'avantage du modèle sans logique?
Récemment, je suis tombé sur une moustache qui est prétendument un modèle sans logique .
Cependant, rien n'explique pourquoi il est conçu de manière sans logique. En un autre mot, quel est l'avantage du modèle sans logique?
Réponses:
En d'autres termes, cela vous empêche de vous tirer une balle dans le pied. Dans l'ancien temps des JSP, il était très courant d'avoir des fichiers JSP saupoudrés de code Java, ce qui rendait le refactoring beaucoup plus difficile, car votre code était dispersé.
Si vous empêchez la logique dans les modèles par conception (comme le fait moustache), vous serez obligé de mettre la logique ailleurs, de sorte que vos modèles finiront par être épurés.
Un autre avantage est que vous êtes obligé de penser en termes de séparation des préoccupations: votre contrôleur ou code logique devra faire le massage des données avant d'envoyer les données à l'interface utilisateur. Si vous changez plus tard votre modèle pour un autre (disons que vous commencez à utiliser un moteur de modèle différent), la transition serait facile car vous ne deviez implémenter que les détails de l'interface utilisateur (car il n'y a pas de logique sur le modèle, rappelez-vous).
J'ai le sentiment que je suis presque seul à mon avis, mais je suis fermement dans le camp opposé. Je ne pense pas que le mélange possible de logique métier dans vos modèles soit une raison suffisante pour ne pas utiliser toute la puissance de votre langage de programmation.
L'argument habituel des modèles sans logique est que si vous avez un accès complet à votre langage de programmation, vous pouvez mélanger une logique qui n'a pas sa place dans un modèle. Je trouve que cela s'apparente au raisonnement selon lequel vous devriez utiliser une cuillère pour trancher la viande, car vous pourriez vous couper si vous utilisez un couteau. C'est très vrai, et pourtant vous serez beaucoup plus productif si vous utilisez ce dernier, bien que prudemment.
Par exemple, considérez l'extrait de modèle suivant à l'aide de moustache :
{{name}}:
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
Je peux comprendre cela, mais je trouve que ce qui suit (en utilisant un trait de soulignement ) est beaucoup plus simple et direct:
<%- name %>:
<ul>
<% _.each(items, function(i){ %>
<li><%- i %></li>
<% }); %>
</ul>
Cela étant dit, je comprends que les modèles sans logique présentent des avantages (par exemple, ils peuvent être utilisés avec plusieurs langages de programmation sans modifications). Je pense que ces autres avantages sont très importants. Je ne pense tout simplement pas que leur nature sans logique en soit une.
name
et items
pourrait contenir du JavaScript.
La moustache est sans logique?
N'est-ce pas:
{{#x}}
foo
{{/x}}
{{^x}}
bar
{{/x}}
Assez similaire à ça?
if x
"foo"
else
"bar"
end
Et n'est pas que assez similaire à (lire: presque une définition de) la logique de présentation?
if x > 0 && x < 10
) ... Donc, s'il est possible d'utiliser Moustache avec ou sans logique, c'est à vous de décider. Après tout, ce n'est qu'un outil.
Un modèle sans logique est un modèle qui contient des trous à remplir, et non la façon dont vous les remplissez. La logique est placée ailleurs et mappée directement sur le modèle. Cette séparation des préoccupations est idéale car alors le modèle peut facilement être construit avec une logique différente, ou même avec un langage de programmation différent.
Nous l'appelons "sans logique" car il n'y a pas d'instructions if, else ou de boucles for. Au lieu de cela, il n'y a que des balises. Certaines balises sont remplacées par une valeur, d'autres rien et d'autres une série de valeurs. Ce document explique les différents types de balises Moustache.
Le revers de la médaille est que dans une tentative désespérée de garder la logique métier hors de la présentation, vous finissez par mettre beaucoup de logique de présentation dans le modèle. Un exemple courant pourrait être que vous souhaitiez placer des classes «impaires» et «paires» sur des lignes alternées dans une table, ce qui pourrait être fait avec un simple opérateur modulo dans le modèle de vue. Mais si votre modèle de vue ne vous permet pas de le faire, dans vos données de modèle, vous devez non seulement stocker quelle ligne est paire ou impaire, mais en fonction de la limitation de votre moteur de modèle, vous devrez peut-être même polluer votre modèle. avec les noms des classes CSS réelles. Les vues doivent être séparées des modèles, point final. Mais les modèles doivent également être indépendants de la vue, et c'est ce que beaucoup de ces moteurs de modèles «sans logique» vous font oublier. La logique va aux deux endroits,fait réellement pour décider correctement où il va. S'agit-il d'un problème de présentation ou d'un problème commercial / de données? Dans un effort pour avoir une vue à 100% vierge, la pollution atterrit simplement dans un autre endroit moins visible mais tout aussi inapproprié.
Il y a un mouvement croissant de retour dans l'autre sens, et j'espère que les choses se centreront quelque part dans le terrain d'entente plus raisonnable.
Cela rend vos modèles plus propres et vous oblige à conserver la logique dans un endroit où elle peut être correctement testée à l'unité.
Cette conversation ressemble à celle où les moines du moyen-âge débattraient du nombre d'anges pouvant tenir au bout d'une épingle. En d'autres termes, il commence à se sentir religieux, futile et mal focalisé.
Un mini-coup de gueule s'ensuit (n'hésitez pas à ignorer):
Si vous ne voulez pas continuer à lire ... Ma réponse courte au sujet ci-dessus est: Je ne suis pas d'accord avec les modèles sans logique. Je pense que c'est une forme de programmation d'extrémisme. :-) :-)
Maintenant, ma diatribe continue en plein essor: :-)
Je pense que lorsque l'on pousse beaucoup d'idées à l'extrême, le résultat devient ridicule. Et parfois (c'est-à-dire ce sujet) le problème est que nous poussons la «mauvaise» idée à l'extrême.
Supprimer toute logique de la vue est "ridicule" et une mauvaise idée.
Reculez un instant.
La question que nous devons nous poser est de savoir pourquoi supprimer la logique? Le concept est évidemment la séparation des préoccupations . Gardez le traitement de la vue aussi séparé que possible de la logique métier. Pourquoi faire ceci? Cela nous permet d'échanger des vues (pour différentes plates-formes: mobile, navigateur, bureau, etc.) et cela nous permet d'échanger plus facilement le flux de contrôle, la séquence de pages, les changements de validation, les changements de modèle, l'accès à la sécurité, etc. retiré des vues (en particulier des vues Web), il rend les vues beaucoup plus lisibles et donc plus faciles à gérer. Je comprends cela et je suis d'accord avec cela.
Cependant, l'accent doit être mis avant tout sur la séparation des préoccupations. Pas des vues 100% sans logique. La logique dans les vues doit se rapporter à la façon de rendre le «modèle». En ce qui me concerne, la logique dans les vues est parfaitement bien. Vous pouvez avoir une logique de vue qui n'est pas une logique métier.
Oui, à l'époque où nous écrivions des pages JSP, PHP ou ASP avec peu ou pas de séparation de la logique du code et de la logique de vue, la maintenance de ces applications Web était un cauchemar absolu. Croyez-moi, je sais, j'ai créé puis entretenu certaines de ces monstruosités. C'est pendant cette phase de maintenance que j'ai vraiment compris (viscéralement) l'erreur de mes manières et de mes collègues. :-) :-)
Ainsi, l'édit d'en haut (les experts de l'industrie) est devenu, vous devez structurer vos applications Web en utilisant quelque chose comme un contrôleur de vue de face (qui est envoyé aux gestionnaires ou aux actions [choisissez votre cadre Web]) et vos vues ne doivent contenir aucun code . Les vues devaient devenir des modèles stupides.
Je suis donc en général d'accord avec le sentiment ci-dessus, non pas pour les spécificités des éléments de l'édit, mais plutôt pour la motivation derrière l'édit - qui est le désir de séparer les préoccupations entre la vue et la logique commerciale.
Dans un projet auquel j'ai participé, nous avons essayé de suivre l'idée de la vue sans logique à l'extrême ridicule. Nous avions un moteur de modèle maison qui nous permettrait de rendre les objets de modèle en html. C'était un simple système basé sur des jetons. C'était terrible pour une raison très simple. Parfois, dans une vue, nous devions décider, devrais-je afficher ce petit bout de code HTML .. ou pas .. La décision est généralement basée sur une valeur dans le modèle. Quand vous n'avez absolument aucune logique dans la vue, comment faites-vous cela? Eh bien, vous ne pouvez pas. J'ai eu des arguments majeurs avec notre architecte à ce sujet. Les personnes HTML frontales qui écrivaient nos points de vue étaient complètement bloquées quand elles étaient confrontées à cela et étaient très stressées parce qu'elles ne pouvaient pas atteindre leurs objectifs autrement simples. J'ai donc introduit le concept d'une simple instruction IF dans notre moteur de création de modèles. Je ne peux pas vous décrire le soulagement et le calme qui s'en sont suivis. Le problème a été résolu avec un simple concept IF-Statement dans nos modèles! Soudain, notre moteur de création de modèles est devenu bon.
Alors, comment sommes-nous arrivés dans cette situation de stress ridicule? Nous nous sommes concentrés sur le mauvais objectif. Nous avons suivi la règle, vous ne devez avoir aucune logique dans vos vues. C'était faux. Je pense que la "règle de base" devrait être de minimiser cette quantité de logique dans vos vues. Parce que si vous ne le faites pas, vous pourriez par inadvertance laisser la logique métier s'infiltrer dans la vue - ce qui viole la séparation des préoccupations.
Je comprends que lorsque vous déclarez que "Vous ne devez avoir aucune logique dans les vues", il devient facile de savoir quand vous êtes un "bon" programmeur. (Si c'est votre mesure de la bonté). Maintenant, essayez d'implémenter une application Web de complexité même moyenne avec la règle ci-dessus. Ce n'est pas si facile à faire.
Pour moi, la règle de la logique dans les vues n'est pas si claire et franchement c'est là que je veux qu'elle soit.
Quand je vois beaucoup de logique dans les vues, je détecte une odeur de code et j'essaie d'éliminer la plupart de la logique des vues - j'essaie de m'assurer que la logique métier est ailleurs - j'essaie de séparer les préoccupations. Mais quand je commence à discuter avec des gens qui disent que nous devons supprimer toute logique de la vue, eh bien, pour moi, cela sent juste le fanatisme car je sais que vous pouvez vous retrouver dans des situations comme je l'ai décrit ci-dessus.
J'ai fini ma diatribe. :-)
À votre santé,
David
Le meilleur argument que j'ai trouvé pour les modèles sans logique est que vous pouvez alors utiliser exactement les mêmes modèles sur le client et le serveur. Cependant, vous n'avez pas vraiment besoin de sans logique, juste un qui a son propre «langage». Je suis d'accord avec les gens qui se plaignent que la moustache limite inutilement. Merci, mais je suis un grand garçon et je peux garder mes modèles propres sans votre aide.
Une autre option consiste simplement à trouver une syntaxe de modèle qui utilise un langage pris en charge à la fois sur le client et le serveur, à savoir javascript sur le serveur en utilisant node.js ou vous pouvez utiliser un interpréteur js et json via quelque chose comme therubyracer.
Ensuite, vous pouvez utiliser quelque chose comme haml.js qui est beaucoup plus propre que n'importe lequel des exemples fournis jusqu'à présent et fonctionne très bien.
En une phrase: sans logique signifie que le moteur de modèle lui-même est moins complexe et a donc une empreinte plus petite et qu'il y a moins de façons de se comporter de manière inattendue.
Même si la question est ancienne et répondue, j'aimerais ajouter mes 2 ¢ (ce qui peut sembler une diatribe, mais ce n'est pas le cas, il s'agit de limitations et de quand elles deviennent inacceptables).
Le but d'un modèle est de rendre quelque chose, pas d'exécuter une logique métier. Maintenant, il y a une ligne mince entre ne pas pouvoir faire ce que vous devez faire dans un modèle et avoir une «logique métier» en eux. Même si j'étais vraiment positif envers Moustache et que j'essayais de l'utiliser, j'ai fini par ne pas pouvoir faire ce dont j'avais besoin dans des cas assez simples.
Le «massage» des données (pour reprendre les mots de la réponse acceptée) peut devenir un réel problème - même les chemins simples ne sont pas pris en charge (ce que Handlebars.js adresse). Si j'ai des données de vue et que j'ai besoin de les modifier chaque fois que je veux rendre quelque chose parce que mon moteur de modèle est trop limitant, cela n'est finalement pas utile. Et cela vainc une partie de l'indépendance de la plateforme que la moustache revendique pour elle-même; Je dois dupliquer la logique du massage partout.
Cela dit, après une certaine frustration et après avoir essayé d'autres moteurs de modèles, nous avons fini par créer le nôtre (... encore un autre ...), qui utilise une syntaxe inspirée des modèles .NET Razor. Il est analysé et compilé sur le serveur et génère une fonction JS simple et autonome (en fait comme module RequireJS) qui peut être appelée pour "exécuter" le modèle, renvoyant une chaîne comme résultat. L'exemple donné par brad ressemblerait à ceci lors de l'utilisation de notre moteur (que je trouve personnellement bien supérieur en termes de facilité de lecture par rapport à Moustache et Underscore):
@name:
<ul>
@for (items) {
<li>@.</li>
}
</ul>
Une autre limitation sans logique nous a frappé lors de l'appel de partiels avec Moustache. Bien que les partiels soient pris en charge par Moustache, il n'est pas possible de personnaliser les données à transmettre en premier. Donc, au lieu de pouvoir créer un modèle modulaire et réutiliser de petits blocs, je finirai par créer des modèles avec du code répété.
Nous avons résolu cela en implémentant un langage de requête inspiré de XPath, que nous avons appelé JPath. Fondamentalement, au lieu d'utiliser / pour parcourir les enfants, nous utilisons des points, et non seulement les chaînes, les nombres et les littéraux booléens sont pris en charge, mais également les objets et les tableaux (tout comme JSON). Le langage est sans effet secondaire (ce qui est indispensable pour la création de modèles) mais permet de «masser» les données selon les besoins en créant de nouveaux objets littéraux.
Disons que nous voulons rendre une table "grille de données" avec des en-têtes personnalisables et des liens vers des actions sur les lignes, et plus tard ajouter dynamiquement des lignes en utilisant jQuery. Les lignes doivent donc être partielles si je ne veux pas dupliquer le code. Et c'est là que le problème commence si certaines informations supplémentaires telles que les colonnes à rendre font partie du modèle de vue, et tout de même pour ces actions sur chaque ligne. Voici un code de travail réel utilisant notre modèle et notre moteur de requête:
Modèle de tableau:
<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>
Modèle de ligne:
<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>
Appel à partir du code JS:
var html = table({
columns: [
{ title: "Username", property: "username" },
{ title: "E-Mail", property: "email" }
],
actions: [
{ id: "delete", name: "Delete" }
],
rows: GetAjaxRows()
})
Il ne contient aucune logique métier, mais il est réutilisable et configurable, et il est également sans effets secondaires.
row
objet, au lieu d'utiliser des noms statiques. Par exemple, si $col.property == 'Something'
cela donnerait le contenu de row.Something
.
Voici 3 façons de rendre une liste, avec le nombre de caractères. Tous, sauf le premier et le plus court, sont dans des langages de création de modèles sans logique.
CoffeeScript (avec DSL de constructeur de café réactif ) - 37 caractères
"#{name}"
ul items.map (i) ->
li i
Knockout - 100 caractères
<span data-bind="value: name"/>
<ul data-bind="foreach: items">
<li data-bind="value: i"/>
</ul>
Guidon / Moustache - 66 caractères
{{name}}:
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
Soulignement - 87 caractères
<%- name %>:
<ul>
<% _.each(items, function(i){ %>
<li><%- i %></li>
<% }); %>
</ul>
La promesse de modèles sans logique était, je suppose, que les personnes ayant des compétences plus larges seraient capables de gérer des modèles sans logique sans se tirer une balle dans le pied. Cependant, ce que vous voyez dans les exemples ci-dessus, c'est que lorsque vous ajoutez un langage de logique minimale au balisage basé sur une chaîne, le résultat est plus complexe, pas moins. De plus, vous avez l'air de faire du PHP à l'ancienne.
De toute évidence, je ne m'oppose pas à ce que la "logique métier" (calcul extensif) ne soit pas utilisée dans les modèles. Mais je pense qu'en leur donnant un pseudo-langage pour la logique d'affichage au lieu d'un langage de première classe, le prix est payé. Pas seulement plus à taper, mais un mélange odieux de changement de contexte que quelqu'un a besoin de lire.
En conclusion, je ne vois pas la logique des modèles sans logique, donc je dirais que leur avantage est nul pour moi, mais je respecte le fait que beaucoup dans la communauté le voient différemment :)
Les principaux avantages de l'utilisation de modèles sans logique sont:
Je suis d'accord avec Brad: le underscore
style est plus facile à comprendre. Mais je dois admettre que le sucre syntaxique peut ne pas plaire à tout le monde. Si _.each
c'est quelque peu déroutant, vous pouvez utiliser une for
boucle traditionnelle .
<% for(var i = 0; i < items.length; i++) { %>
<%= items[i] %>
<% } %>
C'est toujours bien si vous pouvez revenir à des constructions standard telles que for
ou if
. Utilisez simplement <% if() %>
ou <% for() %>
while Mustache
utilisez un peu de néologisme pour if-then-else
(et déroutant si vous n'avez pas lu la documentation):
{{#x}}
foo
{{/x}}
{{^x}}
bar
{{/x}}
Le moteur de modèles est idéal lorsque vous pouvez réaliser facilement des modèles imbriqués ( underscore
style):
<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);
Fondamentalement, vous passez votre tmpl interne comme une propriété de votre contexte. Et appelez-le en conséquence. Sucré :)
En passant, si le seul élément qui vous intéresse est le moteur de modèle, utilisez l'implémentation de modèle autonome. Ce n'est que 900 caractères une fois minifié (4 longues lignes):