Is it a bad practice to have backbone views which do not depend on any kind of templating system?
Of course, this does not mean that any kind of DOM code will be generated by hand, using hardcoded strings within the views. No no no. I can of course cache the basic layout for each view in DOM elements, set to display:none. However, I want to reduce any kind of value setting within the templates themselves. I'd rather do that using jquery, or any other kind of DOM modifier form within the view itself. This way I save myself the constant discrepancies and the countless hours of efforts that I've exposed my apps and myself to, using Mustache, Handelbars, the Underscore templating system, etc. Having all the view logic in one place makes everything much cleaner, at least in my view. It gives a lot of benefits, such as proper partial rendering, value binding, etc, that I'd need tons of days to spend on if I wanted to implement them with mustache or something.
The only problem that I see might occur is whether the constant checks that I'd do with jQuery will be performing fast enough, but I guess that it shouldn't be such a problem at the end.
What do you think? Good? Bad? Practical?
IMHO not using a template engine is not, per-se, a bad design decision.
Template engines are meant to produce cleaner and more maintainable code, if you think not using them produces cleaner and more maintainable code them you can run without them.
I my opinion is better to use template engines but this is just a matter of taste. I also combine the templates with manual DOM modifications through this.$el.find(".my-element").html( "new value" ); for partial updates.
Templates are good. They save you a lot of time coding and allow you to loop over elements and create multiple elements with very little code.
That said if the render is called too much or you destroy and recreate DOM elements/templates, it costs a lot in performance.
I have a PerfView for backbone that can display 1,000,000 models in a scrollview at 120FPS in chrome. The trick is I only render the template once with all the possible nodes I need then change the content in the DOM when the model changes. Also using an object pool for the DOM elements will let you reuse them. Check out the modelMap property on line 237 (https://github.com/puppybits/BackboneJS-PerfView/blob/master/index.html) on how to semi-automate updating an element so you don't overuse a template.
Related
I'm working within a Javascript + BackboneJS (an MVC framework) + RequireJS framework, but this question is somewhat OO generic.
Let me start by explaining that in Backbone, your Views are a mix of traditional Views and Controllers, and your HTML Templates are the traditional MVC Views
Been racking my head about this for a while and I'm not sure what the right/pragmatic approach should be.
I have a User object that contains user preferences (like unit system, language selection, anything else) that a lot of code depends on.
Some of my Views do most of the work without the use of templates (by using 3rd party libs, like Mapping and Graphing libs), and as such they have a dependency on the User object to take care of unit conversion, for example. I'm currently using RequireJS to manage that dependency without breaking encapsulation too much.
Some of my Views do very little work themselves, and only pass on Model data to my templating engine / templates, which do the work and DO have a dependency on the User object, again, for things like units conversion. The only way to pass this dependency into the template is by injecting it into the Model, and passing the model into the template engine.
My question is, how to best handle such a widely needed dependency?
- Create an App-wide reference/global object that is accessible everywhere? (YUK)
- Use RequireJS managed dependencies, even though it's generally only recommended to use managed dependency loading for class/object definitions rather than concrete objects.
- Or, only ever use dependency injection, and manually pass that dependency into everything that needs it?
From a purely technical point of view, I would argue that commutable globals (globals that may change), especially in javascript, are dangerous and wrong. Especially since javascript is full of parts of code that get executed asynchronously. Consider the following code:
window.loggedinuser = Users.get("Paul");
addSomeStuffToLoggedinUser();
window.loggedinuser = Users.get("Sam");
doSomeOtherStuffToLoggedinUser();
Now if addSomeStuffToLoggedinUser() executes asynchronously somewhere (e.g. it does an ajax call, and then another ajax call when the first one finishes), it may very well be adding stuff to the new loggedinuser ("Sam"), by the time it gets to the second ajax call. Clearly not what you want.
Having said that, I'm even less of a supporter of having some user object that we hand around all the time from function to function, ad infinitum.
Personally, having to choose between these two evils, I would choose a global scope for things that "very rarely change" --- unless perhaps I was building a nuclear powerstation or something. So, I tend to make the logged in user available globally in my app, taking the risk that if somehow for some reason some call runs very late, and I have a situation where one user logs out and directly the other one logs in, something strange may happen. (then again, if a meteor crashes into the datacenter that hosts my app, something strange may happen as well... I'm not protecting against that either). Actually a possible solution would be to reload the whole app as soon as someone logs out.
So, I guess it all depends on your app. One thing that makes it better (and makes you feel like you're still getting some OO karma points) is to hide your data in some namespaced singleton:
var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser();
doSomethingCoolWith(myuser);
in stead of
doSomethingCoolWith(window.loggedinuser);
although it's pretty much the same thing in the end...
I think you already answered your own question, you just want someone else to say it for you : ) Use DI, but you aren't really "manually" passing that dependency into everything since you need to reference it to use it anyways.
Considering the TDD approach, how would you test this? DI is best for a new project, but JS gives you flexible options to deal with concrete global dependencies when testing, ie: context construction. Going way back, Yahoo laid out a module pattern where all modules were loosely coupled and not dependent on each other, but that it was ok to have global context. That global context can make your app construction more pragmatic for things that are constantly reused. Its just that you need to apply that judiciously/sparingly and there need be very strong cases for those things being dynamic.
This is more a question about best practices. When trying to apply MVC-like design pattern in a web application, I often find myself wonder how I should go about updating the View.
For example, if I am to update View_1 who has X number of elements. Is it better to:
A: iterate through each of the X elements, figuring out which ones need to be updated and apply the DOM change at a very fine granularity.
or
B: using the data supplied by Model or some other data structure to regenerate the markup for this entire View and all its enclosing elements, and replace the root element of View_1 in one DOM manipulation?
Correct me if I am mistaken. I heard that rendering engines are usually more efficient at replacing at large chunk of the DOM in one go, than multiple smaller DOM operations. If that is the case then approach B is superior. However, even using template engines, I still sometimes find it difficult to avoid rewrite markups for parts of the view that aren't changed.
I looked into the source code for project Bespin before the renamed it. I distinctly remember that they implemented some sort of rendering loop mechanism where DOM operations are queued and applied in fixed time intervals, much like how games manage their frames. This is similar to Approach A. I can also see the rationales behind this approach. The small DOM operations applied in such manner keeps the UI responsive (especially important for a web text editor). Also this way, the application can be made more efficient by only update the elements that needs to be changed. Static text and aesthetic elements can remain untouched.
Those are my arguments for both sides. What do you guys think? Are we looking for a happy medium somewhere, or one approach is by and large superior?
Also, are there any good books/papers/sites on this particular topic?
(let's assume the web app in question is interaction heavy with many dynamic updates)
It's true that rendering engines usually handle change in large chunks faster than multiple small changes.
tl;dr: The bespin way would be ideal, and if you can, do it in a worker.
Depending on the size of the amount of changes you might want to try to start a worker and do the calculation of the changes inside the worker since long running JS lock up the UI. You might consider using the following flow:
Create a object with a part of the dom tree and also the parent id.
Stringify the object to JSON
Start a worker
Pass in the stringified object into the worker
Receive and parse the string.
Work on changing all the necessary parts of the dom tree that you passed in.
Stringify the object again.
Pass the object back to the main thread.
Parse and extract new dom tree.
Insert into the dom again.
This will be faster if there are many changes and a small tree. If it's a big tree and few changes just doing the changes locally in a copy of the real DOM tree will be faster and then updating the DOM in one go.
Also read googles sites about page speed:
https://code.google.com/speed/articles/
And especially this article:
https://code.google.com/speed/articles/javascript-dom.html
After 3 years of working with various web technologies, I think I finally found a great balance between the two approach: virtual DOM
Libraries like vdom, Elm, mithril.js, and to some extend Facebook React track a thin abstraction of the actual DOM, figures out what needs to be changed, and tries to apply the smallest possible DOM change.
e.g.
https://github.com/Matt-Esch/virtual-dom/tree/master/vdom
I am using Backbone.js for an applciation involving a lot of different views, some nesting other views, and these other views could further nest other views.
Also view presentation depends on certain attributes in the model, for instance, some content is only shown if the user has been authenticated, or another type of an if-check
Coming from the world of Adobe Flex, I am used to declaring my views almost completely using markup, even deeply nested, or composite ones. Flex makes component declaration in markup a piece of cake.
I was kinda hoping that I could achieve the same kind of separation between the pure view presentation and the view logic in Backbone, but so far I've been struggling with that.
The reason for this is that in no way can I manage to declare a composite view using templates only. Thus, I have to resort to using BB's render() method to instantiate subviews and append them to the parent. This is OK ... but if the views get really granular, declaring them using JS is an overkill, because I literally end up appending pure HTML strings, which is a complete mess. This means that it is much better to use templating for those ones, and then just render the template instead of doing all the stuff using JS.
Using both approaches simply breaks any consistency in the application, but I push myself to be OK with it, because I've read a lot of (even professionally written) Backbone code, and I 've seen other people struggling with the same thing.
If I cannot avoid this separation of rendering approaches, then at least I will have to put any certain boundaries of which views should be rendered with a template, and which not, or just partially. The question is what will those criteria be.
My methodology is to have all markup contained in templates.
My conception of Backbone Views is that they are actually Controllers. If you consider a Controller in a more traditional web app framework, their job is to receive events, marshal models, fetch and render templates, passing in models, and to return the resulting output.
In Backbone, the Views are the elements responsible for this task. But, instead of http being in input/output medium, the DOM is the input/output medium.
So, I consider Views to be controllers for a specific area of UI on the screen. They listen for events, marshal models, fetch and render templates, and modify the DOM as a result.
The decision of when to go to the trouble of generating a sub-view vs. perhaps rendering a template in a loop, is fairly loose for me.
If it has the possibility of being used in multiple views, I'll make a View out of it.
If it has any events or user interactions which affect itself, but not really anything in the "parent" object I'll make a view out of it.
If it has any real logic, I'll make a view out of it.
If its a related model, or collection, I'll make a view out of it.
But, in any of these cases, the view does not directly generate HTML - I'll always store the markup in a template.
After reading this Micro templates are dead article. I've become curious:
Whether Using the DOM on the server results in cleaner more maintainable code then templating.
Whether it's more efficient to use jsdom instead of a templating engine.
How to factor jsdom into the View of a standard MVC setup.
And generally in what situations would it be better to use a server-side DOM abstraction, like jsdom rather then a templating engine, like EJS or jade.
The question is specific to node.js and other SSJS
Well, I actually needed JSDom for a small project I built over the weekend in node.js. So, on my server, I had to accept a URL to fetch, grab all of the HTML from the given URL, parse it, and display images to the user so that the user could select a thumbnail from that URL. (Kind of like when you drop a link into the Facebook input box) So, I used a module called Request which allows me to fetch HTML on the server-side. However, when that HTML reached my program, I had no way to traverse it like you do with client-side javascript. Because there was no actual DOM, I couldn't say document.getElementById('someId'). Therefore, JSDom came in handy by giving me a "makeshift" DOM that allowed me to traverse the returned HTML. Now, even though I was still on the server side, JSDOM created a window object very similar to the window object in the browser, and created a DOM out of the returned HTML. Now, even on the server, I was able to get all images by calling window.$('img'). I could target and parse the elements like normal. So, this is just one problem where JSDom turned out to be the solution, but it worked amazingly well. Hope this helps some!
Its a nice abstraction that matches a client side engineers take on how the dom is built and modified. In that respect it is 'cleaner' because there is one mental model. Its also nice because we don't have to mix a kluge of disparate syntaxes from a templating language on top of otherwise clean declarative markup as is the case with even the 'stupidest' templating system, such as mustache.
I would NOT say its more efficient to use jsdom for templating. Go take a gander at google wrt to 'memory leaks with jsdom' for instance. jsdom is rad, and is super useful for tasks like weekend projects for crawling sites, doing non-server related tasks, but I think its slow as shit from a high performance web server perspective.
There are a billion ways to factor this. No method has emerged as a 'standard' way. One way that I've seen is to send down an empty 'template', i.e. a block of html that represents a model in some way, and then use that to bootstrap building your end view from a model. From that article, for example:
<li class="contact" id="contact-template">
<span class="name"></span>
<p class="title"></p>
</li>
This is the 'view' in the classic respect. In the typical web application, it might look something more like:
<li class="contact">
<span class="name"><?= $name ?></span>
<p class="title"><?= $title ?></p>
</li>
To use mvc, one sets up a controller that is vaguely aware of the semantics of the above view and the model it represents. This view is parsed into the/a DOM and accessed via your favorite selector engine. Each time the model this represents changes, you might use change events or callbacks to update the view. For instance:
Lets imagine that 'model' fires a 'change' event every time a property changes.
controller = new Controller({
view: $('#contact-template').clone(), // Assume jquery or whatever
model: aContact
});
// Assume some initialization that sets the view up for the first time
// and appends it to the appropriate place. A la:
// this.view.find('.name').text(model.name);
// this.view.find('.title').text(model.title);
// this.view.appendTo('#contacts')
controller.on('model.name.change', function(name){
this.view.find('.name').text(name);
});
These are what systems like Weld and Backbone.js do for you. They all have varying degrees of assumptions about where this work is taking place (server-side, client-side), what framework you're using (jquery, mootools, etc), and how your changes are being distributed (REST, socket.io, etc).
Edit
Some really useful things you can do with jsdom revolve around integration testing and spidering:
https://github.com/mikeal/spider - general purpose web spider that makes use of node's event based processing and gives you jsdom/jquery to help you easily access the DOM in a programatic way
https://github.com/assaf/zombie - headless browser testing using jsdom/jquery for integration tests
https://github.com/LearnBoost/tobi - similar headless browser testing
Personally, I'd like to see a project that took tobi's approach, but mapped it on top of something like https://github.com/LearnBoost/soda such that we can do cloud based selenium testing without selenese (since imo, it sucks).
A few come to mind:
Sharing views/controllers between server and browser
Data mining / crawling / processing
Transformation for fragments of HTML used in AJAX/realtime stuff
Absolute separation of logic and content by avoiding template tags
And to answer your questions:
maybe. A lot of things affect code quality, but it's a step in the right direction
nope, templating engines will always be faster, since they can pre-compile templates
this probably warrants a new question?
point 2 of your question can be answered by this templating testcase:
go http://jsperf.com/dom-vs-innerhtml-based-templating/300
click the button "Run tests".
be patient, it compares weld vs. a lot of other template engines and gives you the current benchmarks ...
I'm evaluating http://github.com/janl/mustache.js
and I'm thinking about how it will work in general over time with a time. If I just build a giant object, is mustache sufficient to transform it into any form of HTML?
So, my question is. Is there anything that mustache can't do?
(My thought is that it is just tree transformation from JSON to HTML, but I'm not sure how to validate that or gain enough confidence to bet against it)
further clarification
Suppose that all I had was a giant object and then I gave to a mustache template in one iteration; is there anything in HTML that can't be expressed in mustache via its language.
Since Mustache is just a template language in JavaScript, you can do anything you can already do in JavaScript, and JavaScript is Turing complete. So no, there's nothing that you can't do in Mustache; in fact, there's nothing you can do in Mustache that you can't do yourself in JavaScript, it just makes some things more convenient.
When evaluating something like this, instead of determining what it can and can't do, it's more useful to ask "does it make the things that I need to do easy" and "does it make the mistakes I want to avoid hard to make."
For instance, one way to evaluate it would be whether it makes it easy to avoid cross-site scripting (XSS) attacks. According to the documentation "mustache.js does escape all values when using the standard double mustache syntax", so it sounds like it does do a good job of helping prevent these sorts of attacks.
To do a better job of evaluating it, you will need to provide more details on what your requirements are. What are you trying to do? What do you need to integrate with?
edit
Even after your clarification, it's still not exactly clear what you're looking for. Even restricting yourself to expanding a single Mustache template with a single view as input, you can produce any arbitrary string, and thus any arbitrary HTML by just give it that string as input.
If you're asking whether you can perform any arbitrary computation given a template and a view to render, then the answer to that is also yes, because Mustache allows you to call functions in your template, and those functions are written in Javascript, which is Turing complete.
But both of these are trivial answers; you can produce any given output by providing that as input, or you could do any given computation by using a higher-order section. As I said previously, what is possible to do with it is less interesting than what is easy to do with it, and what mistakes are hard to make with it.
I suppose one weakness, that may be the type you're looking for, is that if you need more power than the Mustache system itself provides, you need to pass those functions in as part of the view. Thus, you need to conflate the object that is being displayed with the code that will be used to display it. And if you remove the ability to to call Javascript from the views that are passed into the templates, then you do severely limit what you can do. Given the fact that these objects are known as "views", it seems that it's by design that you mix in the presentation logic with them; this is very different than template systems in which you allow the template to extract values directly from your model objects.
Yes, there are many things you can not do in mustache. Mustache is simpler than some other full-featured template systems ( like the one in Django ). Mustache is a very minimal template system which encourages you to ( through it's lack of features ) to implement "logic-less" templates. This means that some processing that you can do in other template systems must instead be done in code that modifies the data that is sent to the template.
It's not bad template system, it's just a minimal system that aims to be simple and fast.
So, I would say that the answer to this question is: "Yes, there are things you can not do in Mustache ( compared to some other template systems )".