then they wrote template languages on top of the template language to separate layout and logic again ( PHP vs Twig/Smarty )
so maybe we need to step back a little and figure out how to write a language that wouldn't need a different syntax for logic and layout. This family of languages exists already, but since current developers grew up with C like languages, it is not that popular.
IMHO the best compromise is direct support for XML syntax inside languages (which Javascript had at some point with E4X) because I don't think anyone will be able to make developers use LISP like languages on a wide scale. JSX, with some modifications and standardisation could also be a solution.
Here's a function that always returns true - but it could do any kind of data access. It is just plain Clojure.
(defn selected? [] true)
Here is a datastructure that represents html: [:h2 {:class (when (selected?) "selected")} "Hello"]
Calling the function hiccup.core/html on that datastructure yeilds an html string like this: "<h2 class='selected'>Hello</h2>"
So that's great for _strings_ right? But there is an awesome library for ClojureScript called Reagent. And it uses those simple datastructures to generate react components!! I put some more examples at: http://hiccup.spaceThe ability to copy snippets of HTML from web, or old code when refactoring, or from Clojure/Hiccup to another language & framework, or changes from developer tool, or familiarity for new engineers, or not having to care about what flavor of HTML is hip today is a huge productivity boost for me.
I would love to see push for template strings [1] in Clojure, it should be trivial with macros. It would only take some time for IDEs to catch up. They're good. So good they've even influenced Python 3 to add them.
(defui my-component [x]
"<h2 class=(when (selected? x) ["selected"])>Hello</h2>")
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... (defui my-component [x]
<h2 class=(when (selected? x) ["selected"])>Hello</h2>)
It's possible to macro the above to the code below, without any language extensions. IntelliJ has powerful nested DSL introspection, it would be neat if Cursive allowed to hook into this through defui's metadata for highlighting. I was a hater of JSX until I used it. Now I hate eDSLs. :D (defn my-component [x]
[:h2 {:class (when (selected? x) ["selected"])} "Hello"])It helps that Clojure's syntax is based on s-expressions, and s-expressions are already isomorphic to HTML/XML.
So in a way, you're still mixing your templates and your code, but you happen to be using the same syntax for both. Which is arguably an improvement.
The equivalent would be something like
function() selected { return true }
["h2", {class: function() {if (selected()) {return "selected"}}}, "Hello"]
Not as clean, but still usable IMOThe worst I've seen is a bit of confusion between models and controllers. But views are usually as clean as the Gods of MVC commanded.
Not a good thing, IMO, since it makes the syntax way more complicated, but there you have it.
Where I work right now, we use the newer versions of ASP.NET that come bundled with the Razor templating engine, which uses .cshtml files. You can write C# inside the files much the same way you can write JavaScript in a JSX file, it makes creating forms and such a breeze.
Big bonus is that moving from writing server-side logic to client-side logic doesn't require much of a context switch, and you can use the same objects to represent your data on both sides. If I spend all day moving between half a dozen different languages that get compiled by a dozen different tools, it can get a little exhausting.
Razor seems to have been born out of a frustration someone had with writing
return "<div>" + model.name + "</div>";
Razor is basically a DSL for C# string concatenation, where everything not escaped with an @ is a string literal to be concatenated. This means it's fairly unopinionated about structuring code. React, on the other hand, forces you to define components- ideally, pure functions from properties to JSX (which is just sugar for JS). This means composition is the default solution to everything. Razor doesn't place nearly as much emphasis on composable components, and the mechanisms it has for doing so, like helpers or calls to RenderPartial, are clunky and worlds away from the first-class component support of React.While it's technically possible to write Razor code with a React-style focus on composition, the syntax and architecture of viewmodels/templates actively pushes you away from doing so. In my experience, most Razor ends up like a C# translation of PHP, and I think that's really the paradigm Razor inherited. Razor has been around since 2011, which significantly predates the Cambrian explosion of clientside js frameworks, so it makes sense.
No you don't. Look at Wicket for how to do this right: everything is a component, the only thing[1] your templates contain is a) markup (which is 100% valid, using a namespace for the only wicket-specific part) and b) ids that indicate that a given tag will be replaced with a component. Everything else is handled by the component hierarchy in code, using proper OO polymorphism (it's also a great example of proper use of OO, with classes left with only the correct extension points, and classes or methods declared "final" if the developers don't intend to support custom ones going forwards). You end up making truly reusable components that can be very small - even something like an address input is a component defined in terms of smaller components.
I wish there were Wicket equivalents in other languages.
[1] There are a few other conveniences, but they really are minimal
> b) ids that indicate that a given tag will be replaced with a component
With that in mind, your disagreement is contradicted by this statement because logic has just been described to update the view. Logic is necessary to generate a view of the data for the user.
With JSX, keeping all of this code closer together that is intrinsically tied together increases cohesion, by definition. Subjectively, this makes it easier to manage UI because one only have too check one place for all the pieces. For further exploration of this idea, check out the intro of this video on separation of concerns vs technology. [1]
On a separate point, it sounds like one must imperatively update the UI with Wicket, which is objectively more complex than what React affords, which is stateless UI. Time is removed from the equation, which also makes things easier to reason about.
[1] https://www.youtube.com/watch?time_continue=275&v=x7cQ3mrcKa...
There is no logic in the "template". No looping, no branching. Only inert ids. There is logic in determining which component replaces each id, but that logic lies in the code, not the template.
> it sounds like one must imperatively update the UI with Wicket, which is objectively more complex than what React affords, which is stateless UI.
Not so. Wicket clearly separates its state into models, you write UI that depends on a model as a function of that model. It leads to a very declarative/functional style, where the only "magic" is encapsulated and explicitly managed. (You do have to declare which changes update which UI (for performance reasons), but you can make that "always re-render the whole page" if that suits your use case).
Again, changing view to mean "template" is a strawman.
> Wicket clearly separates its state into models > You do have to declare which changes update which UI (for performance reasons),
Separating state isn't the same as no state. Also imperatively updating the UI on state changes is stateful. Which increases complexity, which for most people makes code hard to reason about.
> but you can make that "always re-render the whole page" if that suits your use case
Anything can be made to do anything, so this point is moot. If this model was trivially applied, would it lead to flickering, lower performance, losing scroll position, losing selection, or losing input focus?
Call it what you like. The point is that clear separation between logic and markup can be done and is valuable.
> Separating state isn't the same as no state.
Any web page that has inputs or controls is necessarily stateful - otherwise where does the input go?
> Also imperatively updating the UI on state changes is stateful.
There's nothing imperative about it. Have you looked seriously at Wicket or are you just throwing buzzwords around?
You concede the original point. To your new point, saying something is valuable doesn't make it valuable. Why? It decreases cohesion, which is not good.
> Any web page that has inputs or controls is necessarily stateful - otherwise where does the input go?
If this is a serious question, it's too far off any original point to teach you unfamiliar concepts. Learn about what stateless, declaratively, & imperatively UI means so there aren't strawmans, and so you can weigh in on these discussions.
> There's nothing imperative about it. Have you looked seriously at Wicket or are you just throwing buzzwords around?
Please do not dilute conversations on here by name calling. Imperative & state are basic computer science terms... o_O
No. Your original claim was that you need to mix logic and layout. You don't.
> If this is a serious question, it's too far off any original point to teach you unfamiliar concepts. Learn about what stateless, declaratively, & imperatively UI means so there aren't strawmans, and so you can weigh in on these discussions.
It's not me who needs to learn what those words mean. Either you're just trolling, you don't understand the terms, or you don't understand wicket.
You can go the other way...just put the logic in the controller to format data and otherwise build the model in a way that is cognizant of the view. But, then you've just "polluted" the controller with the view.
One approach at solving this is frameworks like Wicket, which (in spite of shortcomings) encourages the use of view components in a way that allows them to render a more organic model. Yes, you may write some Java to render specialized components, but you're at least using the same language and being specific about writing rendering code that is also reusable.
It sounds to me like you are arguing that because people will put logic in templates, and this leads to ugly template languages, we should just program in ugly template languages rather than doing any separation of logic from templates.
<div data-scope="users"><div data-attr="name"></div></div>
Now I have everything I need to process this html with my logic to turn it into
<div id="users"> <div id="user_1"> Frank </div> <div id="user_2"> Bob </div> </div>
edit: I wish downvotes required commenting on why you're downvoting.
I understood your claim fine. I'm trying to explain why it might be considered false (and I did already say I consider the arguments each way basically hair splitting).
Either way, I _think_ I have a better understand of potential conflicting views. Thanks for taking the time to explain.
You need some sort of logic in your views, no matter what system you use, i. e. loops or formatting dates.
Because people are raised on the "don't mix logic & layout" maxim, they feel dirty when they write sich logic in their usual language.
.. so they invent template languages...
... that then expand to be turing-complete and basically offer everything their primary language offered in the beginning.
So you end up with a new language to learn, which is usually clunky and ugly just for the bragging rights of "not mixing logic & views". Which is completely stupid. Views can (and almost always need) to contain some logic and the best language for that is the one you're using everywhere else.