Skip to content
This repository has been archived by the owner on Jul 12, 2020. It is now read-only.

Review from Samuel Clay #361

Closed
addyosmani opened this issue Mar 5, 2013 · 5 comments
Closed

Review from Samuel Clay #361

addyosmani opened this issue Mar 5, 2013 · 5 comments

Comments

@addyosmani
Copy link
Owner

Tell us a bit about your professional background, as it relates to the topic of the book:

I worked on Backbone.js in its infancy, when Jeremy Ashkenas and I created DocumentCloud's numerous open-source projects.

YOUR ASSESSMENT

Please comment on the manuscript’s aims and scope.

Developing Backbone.js Applications covers a wide spectrum of Backbone and JavaScript related technologies. It does a beautiful job of clearly defining the component parts of Backbone, as well as hitting on multiple use cases. There is wide coverage of multiple testing frameworks and a rich assortment of koans used to both learn Backbone and unit test it. This book's aim is to familiarize the reader with the foundations used to build complex single page apps (SPAs), and then successfully test, deploy, and build on top of these apps.

Who do you believe the target audience is? Please be specific about what knowledge you assume of the readership of this book.

I believe there are two target audiences for this book: novice JavaScript developers who know jQuery, and intermediate JavaScript developers who have home-rolled their own MVC to manage an existing app and are looking for a clear migration to Backbone. My assumption is that Backbone is accepted as a particularly clean and modular JavaScript framework that could be used in almost any existing or new project, and that the readers of this book are looking for the industry-accepted application layer in their stack. That means some less experienced developers will purchase this book having heard on forums and in their limited experience that Backbone is the way to go. So it is likely that they are looking to start using conventions in the Backbone style, with more breadth coverage of topics while leaving more of the depth coverage to advanced books.

On the other hand, it's also likely that many in the target audience have rolled their own MVCs to tackle the growing complexity of their apps and are looking for a less opinionated framework that can offer them a stronger foundation, yet integrates cleanly because it is less opinionated and modular enough to be overwritten in parts for easier integration.

Does the approach seem useful and appropriate for the intended audience?

Between the two types of audience members I expect to see — jQuery novices looking for a foundation, and more experienced developers who haven't yet used Backbone — I think they are both served well by the various sections in the book. Between the fundamentals of Backbone and the Appendix, which both lay out the basic building blocks for the design pattern used by Backbone, to the section on modular development, a developer has all the tools necessary to build their own single-page applications.

Do you feel there is a need for this book?

Yes, I was surprised one has not already been written. Backbone's been out for nearly 2.5 years now! And from day one it was clear that Backbone was simple and concise enough to merit investment and time from the community.

What does this book offer in terms of content and approach that other books do not?

Haven't seen another Backbone book, apart from chapters in other books (which I also have not read). But considering the many blog posts written on Backbone.js, I have yet to see anything even approaching the comprehensiveness and single voice (consistency is undeniably important here) that this book manages to achieve.

Please comment on the table of contents.

The organization is as follows: intro, fundamentals and building blocks, two examples, extending backbone, common problems, modular development, more extensions, unit testing, and the appendix. I believe the two extensions sections should go further back in the book since they are not likely to be used by most developers who use Backbone. Because fewer developers are going to extend Backbone with jQuery Mobile, or Marionette/Thorax, it makes sense to push them back. The module development chapter has 3x as many subsections as any other chapter, so it could benefit from either splitting into component parts, or moving the AMD documentation to its own chapter.

Is the material technically accurate?

Yes, and I submitted a pull request to fix the few typos and trivial mistakes that I found.

Are there any topics that should be added/deleted, emphasized/de-emphasized?

I believe the section on AMD could be de-emphasized without hurting the rest of the book. There are few developers who will go that route of modularization and proactive dependency management. For the most part, most developers are going to have all of their JavaScript loaded on the page and then initialized.

I personally would have focused more on QUnit, the unit testing framework that Backbone.js uses, and less on Jasmine, which features semantics that are less Backbone-like than QUnit.

Perhaps turning the Appendix into its own chapter that focuses on decomposing the MVC for the use of learning about the structure of backbone (its own backbone, so to speak).

And the Common Problems section could be its own book, but my experience has simply revolved around hearing developer's gripes about the framework when asking them for their feedback and experience in using Backbone.

Is the organization and order of presentation appropriate?

As I mentioned above, the more frequently used parts of Backbone would benefit by being placed near the front (Appendix, unit testing, examples like the paginator and both exercises), whereas modular dependency management and backbone extensions are on more of a pick-and-choose basis.

Are there any elements you would like to see added/removed, increased/decreased (such as figures, code samples, call outs)

More examples of apps that touch every component (model, collection, view, and router) is always better. As many use cases as possible. The issue is that many use cases share 80% of their abstractions, so the book would become very repetitive. I would have liked to see more screenshots of the work in progress during the todo app, similar to how detailed the book library app is.

Do you have any other suggestions for changes and improvements in the book’s coverage?

Nothing more than what's covered in my chapter-by-chapter review.

MARKET

Are there similar books or competing books available?

Only a small handful of ebooks, and nothing that I know of in print or at this length.

In your opinion, which is the strongest competition and why?

I'm not an ebook reader (I printed this book out and marked every page so I could come back to it when I wrote up my review), so I'm not sure I can comment on the existing backbone ebooks.

How does this manuscript compare to the strongest title in the field?

This will very likely be the strongest title in the field.

Can you estimate the size of the audience?

This is an interview question, right? I can only work with relative numbers here. I personally believe that there should be 1-to-1 ratio of people who bought any other JavaScript book and who will buy this book. I tried coming up with some estimate, but each time it gives away how little I know about the technical book market. I would be happy if I saw this book on somebody's shelf, so that means at least a few thousand are sold in the first year. My guesstimate is that at least 10k are needed to be sold in order to issue another edition.

Where in a bookstore would you expect this book to be shelved?

I'd say in the Computer Science section, but that's where the eBay for Dummies books are now shelved.

Would you recommend publication of this book? Why or why not?

I sure would. It's not just a book on a library, it's a book on building the structure of real-world apps using a popular and widely accepted JavaScript library.

Would you buy a copy for yourself or recommend it to a colleague?

Well, I'll be buying a copy no matter what, but to be honest if a colleague asked me I would point them to the DocumentCloud source tree and tell them to go through the ~30 JavaScript files that were the original inspiration for Backbone. It's beautiful code, mostly written by Jeremy Ashkenas, the author of Backbone, and makes for a great use case.

How would your company use such a book?

It would serve as a nice basis for all front-end developers to be well-versed in common JS terminology and practices like unit-testing and extending Backbone.

Chapter Reviews - Strengths & Weaknesses

Chapter 2, Fundamentals

This is a drier chapter than others, but one that will be appreciated by somebody who might be jumping into Backbone without having thought much about the background necessary for actually shipping a full single-page application. And while this chapter covers the most of any chapter about the server side, it would be helpful, just as part of the fundamentals or in its own chapter, to cover common overrides for Backbone.sync. Overriding Backbone.sync is a common use case, and I assume that because the number of various backends that could be used is high enough, it isn't worthwhile to cover in more detail.

Further in the chapter, under Implementation Specifics, it would be helpful to include specific enumeration methods to support the definition of Collections (select, reduce, filter). I just find that the best way to describe the purpose of Collections is to show off their Underscore-derived possibilities.

Because there is a chapter about internals (although the chapter is titled Basics) I figure you'll cover the source code deeply enough. But a good time to talk about reading the source code would be under Models > Initialization, where the Backbone.js source code makes it obvious that Model.initialize() is meant to be overridden. Backbone.js's source code is a clean document. It doesn't have to deal with tricks used by jQuery for cross-browser consistency. Because of it's straight-forward nature, reading the Backbone.js source code is both easy and useful for figuring out the order that Backbone sets up your models and views.

The fast facts section is particularly well done. I recommend extending the "Used by" section to include more of the examples at backbonejs.org/#examples. One of the best ways to defend Backbone in a MVC/framework showdown is to simply point to the growing number of examples of successful apps written with Backbone.

Chapter 3, Backbone Basics / Internals

Under Direct Access (when accessing a model's attributes), you may want to mention that setting values through the .attributes attribute on a model bypasses triggers bound to the model. Additionally you can use silent: true, but they can build up and then hit in unexpected ways later on.

In the example of el, it would be helpful to include more information about the purpose of this.setElement() and how overriding this.el needs to both change the DOM reference and re-bind events to the new element (and unbind from the old). Just a few lines of code in setElement, but it makes for a good explanation of how this.el operates.

In Understanding render(), one of the common conventions used is to return this at the end of render. This is shown elsewhere in the book, but it's a common enough task that it would make sense to consider it a basic building block of Backbone. It's useful for creating a list of elements without rendering and painting each of them individually, only to be drawn once the entire list is populated.

Similarly, in the events attribute section, it would be helpful to mention how you can bind methods yourself with _.bind(this.viewEvent, this), which is effectively what the value in each event's key-value pair is doing.

While talking about the client id (cid), it would be helpful to offer an example of why you would even use a client id.

Another handy tip is to use reset() with no arguments to clear out a collection. Handy when dynamically loading a new page of results and you want to blank out the current page of results.

Chapter 4, Exercise 1: Todos - Your First Backbone.js App

This is a classic example and I like the layout of the chapter. Start with the boilerplate and templates, show the model and its collection, and then dive deep into the views that handle all the glue. It would be helpful to be consistent with alternating between this.$el and this.input (which, for consistency's sake, is missing a $ sign).

When talking about the _.template method in the initialize method, it would be helpful to talk about the two ways to use the _.template method. The alternate method is to pre-compile the template if it will be used multiple times (only giving it a single argument, omitting the interpolation parameters argument).

Chapter 5, Exercise 2: Book Library - Your First RESTful Backbone.js App

Similarly to the first Exercise, the compiled _.template call could be moved to the prototype. It all depends on how the view will be used, but it's a useful practice to know. I also think it would be helpful to show how to populate the books collection by using a reset call on the collection during page load, to speed up initial load time.

I think the paragraph about a self-rendering view is particularly strong in this chapter. The downside is, of course, that a self-rendering view will cause a repaint immediately, but it also results in less code needed to have to draw in the view. This is useful when drawing in many views at once.

Chapter 6, Backbone Boilerplate And Grunt BBB + Extensions

I don't have much experience with these boilerplate tools, preferring my existing build systems, but I would like to see a bit more background on the types of problems these tools help solve. Specifically "Boilerplate module code" still has me fuzzy on why I would use this tool as opposed to the few lines of code needed to get Backbone talking to both my existing app and the many component parts of my app.

In other words, "Numerous other Backbone.js snippets for making your life easier" would be awesome if enumerated with some specifics about what those snippets are.

However fuzzy I am with the purpose of these boilerplate tools, the RequireJS config was helpful. I always go to the config.js (or settings.py or config.rb) file first when looking at a new project. It serves as entrypoint for both me and for the application.

The first place that I could grasp the helpfulness of Backbone Boilerplate tools was in main.js where the boilerplate code for initializing the router was specified. This is also shown in the Marionette ItemView, which crunches down the few lines of initialization. But I'm of the opinion that the boilerplate in Backbone code is helpful to new developers looking at the code, as there are fewer assumptions being made and more control over the differences in how different views are instantiated and rendered.

I found the ZombieView example confusing because of the name reuse. Since zombieView is effectively instantiated twice, I didn't see the purpose of instantiating it the first time with the same model being instantiated the second time. However, talking about manually removing event handlers is critical, as this is quite possibly the biggest source of memory leaks (leaving event handlers dangling) in most Backbone.js code.

There was also a section on Thorax, but it made me think that using one of these third-party extensions was necessary to the completion of a large-scale web app, which may not be the intention. By placing the Extensions chapter before Common Problems, it's a signal that these extensions should be the first answer to your common problems rather than working with just Backbone.js and staying simple.

I think something that may be helpful to readers is to callout these extensions at specific points throughout the book in relation to a specific problem that these extensions could solve. I see this done in the next chapter in reference of Super, but I think that model could be extended even further. If the reader sees a problem and then the code used to work around it, then the extension which neatly solves the issue (which unfortunately seems to be confined to boilerplate and easy instantiation of multiple children) would be a great addition.

Chapter 7, Common Problems and Solutions

This is my favorite chapter so far. Learning the basics is one thing, but dealing with real-world limitations is ripe for discussion. In particular, showing the wrong/naive way to write some feature with Backbone before showing how to correct it reminds me of the classic Refactoring book by Martin Fowler.

I want to point out that the use of cids (client ids) here is useful, as it illustrates the idea of separating a model and its views by having the views referenced by their instances and not their attributes. It's very common to ask for all views that satisfy an attribute on their models. But if you have recursive subviews or repeated views (a common enough occurance) then you can't simply ask for views by attribute unless you specify additional attributes that separate duplicates. Using cids solves that problem by allowing for direct references to views.

I did find that the examples which were abstract, relying on variables called viewA, viewB, modelB, and modelC, were harder to follow than concrete examples. You do use a "Panel" later on in the chapter, as well as a "Note" and its subclass "OldFashionedNote", which provide enough color to enrich the abstracted explanations for subview behavior. But picking something more concrete, in essence following the Backbone.js docs and using examples like Artists, Meal (appetizer, entree, dessert), and book chapters, would go a long way towards explaining the why to go along with the how.

Also, I wrote a lengthy blog post about this very subject: http://www.ofbrooklyn.com/2012/11/13/backbonification-migrating-javascript-to-backbone/. It includes more than a dozen common problems and solutions and may be useful in finding more hangups that cause stress while developing real-world apps.

Chapter 9, Modular Development

This is the biggest chapter yet, but I found it to share the least with the other chapters. Dependency management is a complicated task, and every web development framework has it's own preferred and accepted ways of handling static media. At DocumentCloud we used our home-built asset packager called Jammit. To provide dependencies, you simply wrote out an assets.yml file that either listed dependencies in order, or used a combination of free capture directories (for example: //.js, templates/.js, and specific files). Very, very few projects get to the point where loading in dependencies piecemeal and on request that can justify the added expense of switching to use AMD. This is my opinion only, but most projects can easily afford to load the entire app. While there are performance gains to be had by wrestling with per-module dependency graphs, it's a tough battle and I haven't seen enough real-world use cases where it would cut down load time.

However, that being said, I think this is a strong chapter that deals with the intricacies of introducing dependency management through AMD. It's just one choice among several in modular development of a Backbone app. I think more coverage of simpler methods, like using Jammit to automatically templatize .jst files (wrapping them in a window.JST['templateName'] = _.template("<div></div>")) for both development and production. I think simplicity goes a long way in the race against load time.

Chapter 10, Mobile Applications

This chapter is all about successful integration with jQuery Mobile, the UI and widget factory. It's useful for hinting at the main pain point, which is dealing with Backbone's router and jQuery's hash changes and page loading. It would be helpful to also include an example showing how to use the router to call jQuery Mobile and sync their pages on reload.

The difficulty is in loading up a navigation stack when reloading into the middle of the stack. If you're in a deep detail page and need to back out into a list and overview parent, that needs to be setup by the router. That sort of example would be welcome here, especially as breadcrumbs and navigation structure is the hardest part about developing for mobile.

Chapter 11, Unit Testing

My experience with JavaScript unit testing only extends to QUnit, which is what the Backbone.js unit testing suite is written with. But this chapter has one of the strongest introductions of any in the book because it lays out the background and history of Jasmine (and its predecessors) along with the implementation details. Handy, concise, and relevant.

The section about spies (mocking requests and responses) was a bit confusing, in that the Jasmine-specific methods like andCallFake and toHaveBeenCalled are not obvious. The Jasmine functions like waitsFor and runs are more functional than procedural, and for most Backbone.js developers, functional programming concepts are not yet in wide use. I'm not saying that one way is better than the other, just that depending on the audience for the book, it may make sense to explain more of these foreign concepts in a bit more detail. Maybe I'm just bitter that Jasmine uses beforeEach and afterEach instead of setUp and tearDown.

In the Shared Scope section, I think it would be beneficial to include a short code sample that illustrates how the scope really is shared, by having just two tests that modify a model and rely on shared state. It's a powerful idea and one that unfortunately bites some newcomers to unit testing. But the code sample could be simple enough that it shows modifying the model in one test causes it to change in the second. This comes from some humbling experience.

I found the koans to be extraordinarily useful. There were some differences between the koans in the js/ directory and in the book's description, which made me think that the koans were somehow separate from the book, like a bonus CD.

One minor niggle: perhaps using the NAUGHTY_WORDS variable is a bit distracting. If you want to stick with the text sanitization example, maybe use some story centered around classified documents and the retraction of names (Mr. Jones becomes Mr. ------).

Apart from the basics covered in the model section, perhaps it would be helpful to add in a test that covers models that depend on each other. In other words, figure out a race condition and make the models perform actions in order. This is something that is trivially solved with promises, but it would make for a great read and is something that has an immediate use in many projects.

Additionally, the collections section could use a similar example with nested collections. I covered this specific example in my blog post I referenced earlier, but for a directory listing, where sub-folders can contain files and additional sub-folders, the rendering of children should be completed before the rendering of parents, and that would make for a great example.

One last comment on testing, and this comes from experience in other languages, but a short mention of how to work with mocking Dates and relative times would be super helpful. It's not the easiest system to work with, but it would fit in this chapter pretty well. All I mean is to have some items sorted by date (a common enough feature) and loaded from a fixture, and then insert new models with dates that correspond to the other models. It's trivial, but you'd be surprised (actually, you probably wouldn't) at how hard some people find working with dates in JavaScript can be, especially when mocked in unit tests and in fixtures.

Chapter 12, Unit Testing Backbone Applications with QUnit and SinonJS

After reading this chapter, I have to ask why isn't this chapter the first unit testing chapter, going before Jasmine? You briefly covered your thoughts regarding the importance of showing both frameworks. QUnit first would make sense, as it's Backbone's test suite of choice.

I prefer this chapter's layout of showing the possible assertions in a list, and then showing examples of each assertion type. It's iterative and I think it's a very strong way to showcase QUnit. It's effectively a table of contents for the framework, and spells out what you have to work with. Think of it as the table of contents on Backbone's documentation page. This layout would be quite helpful if also applied to Jasmine, since there are many more methods in Jasmine than QUnit.

I didn't quite understand the point of using the $.fn.enumerate method. It looks like it is only used for the purpose of generating a fixture, but only as a convenience method. Wouldn't it be easier to either write out the fixture by hand, or use a simpler generator for a fixture that can be following inline?

In the Asynchronous section, I see the point in stopping execution of the test only to be resumed later, but for a purpose of creating a unit test, would a mock data structure (instead of an ajax call) be a better indicator of code quality? It would demonstrate how the code works with data coming back from the server, and can also show what the response is expected to look like.

Chapter 15, Appendix

This chapter is wonderful, in that it feels like a room in a house that has no door but you discover after 10 years of living in it. This chapter explains a lot about the MVC pattern and I think it's unfortunate that it gets relegated to the Appendix. Unsurprisingly, this chapter's setup of cranium.js looks a whole lot like the beginnings of Backbone. Views are dumb, so they get very little boilerplate and setup. Models are responsible for their attributes and announcing changes to those models. I think this structure could be very useful for describing Backbone to somebody uninitiated in the MVC design pattern and I wish it was given a bit more light than stuffed into an Appendix that will unfortunately get an order of magnitude less love than the rest of the book.

One small note, when comparing MVC and MVP, Backbone.Router is mentioned as being covered later in the book. It's true that it's covered further in the Appendix, which is operating in a dictionary mode at points. So shouldn't it either say later in the chapter, or refer to the earlier chapter where the Router is defined and used?

On the topic of namespacing, perhaps it would be helpful to show how the original DocumentCloud workspace uses namespacing in a necessary way, as documents (and annotations and document lists) are embedded on third-party news sites. Even just linking to the DocumentCloud workspace would be helpful: https://github.com/documentcloud/documentcloud/blob/master/public/javascripts/application.js

Overall, this is a fantastic read and my hope and honest belief is that it will age well.

@addyosmani
Copy link
Owner Author

@dcmaf I was particularly interested in the comment "This chapter is wonderful, in that it feels like a room in a house that has no door but you discover after 10 years of living in it. This chapter explains a lot about the MVC pattern and I think it's unfortunate that it gets relegated to the Appendix. Unsurprisingly, this chapter's setup of cranium.js looks a whole lot like the beginnings of Backbone. Views are dumb, so they get very little boilerplate and setup. Models are responsible for their attributes and announcing changes to those models. I think this structure could be very useful for describing Backbone to somebody uninitiated in the MVC design pattern and I wish it was given a bit more light than stuffed into an Appendix that will unfortunately get an order of magnitude less love than the rest of the book." - should we consider this comment? Sam worked on the first version of Backbone with Jeremy.

@dcmaf
Copy link
Collaborator

dcmaf commented Mar 5, 2013

Yes, I read Samuel's review this morning and noticed that as well. I think our difference of opinions on this is due to us being members of different target audiences.

I think I am representative of the first audience that Samuel identifies: "novice JavaScript developers who know jQuery". From my perspective, I'm looking for practical knowledge I can apply to build my application. I think one of the most appealing characteristics of Backbone is its simplicity - you don't need to learn a large, complicated framework in order to do something simple. To me, diving into how to implement such a framework up front was confusing and not relevant to what I was looking for. In fact, I started wondering if I was the target audience.

This difference is also evident in his preference for calling what is now "Backbone Basics" by its original "Internals" name. To me, "Internals" is a deep dive into how something works, which is not at all what I am interested in at that point in the book. Thus, "Backbone Basics" which sounds much more like an introduction to the key concepts I need to learn in order to use Backbone.

It might make sense to have an Internals chapter towards the back of the book which pulls together the material that relates to implementation. Also a "How to Use This Book" section could provide guidance to different audiences on what to read depending on their goals and perspective.

@addyosmani
Copy link
Owner Author

@dcmaf I've been addressing much of Samuel's feedback today. One thing I'm wondering about is his comment about moving the QUnit/Sinon work before the section on Jasmine. What are your thoughts here? In my experience, I've seen more developers in the wild using Jasmine for their Backbone app unit testing but he does make a fair point that QUnit is the Backbone solution of choice for this. Does it make sense to have it appear earlier or leave as is?

@dcmaf
Copy link
Collaborator

dcmaf commented Mar 18, 2013

@addyosmani From my perspective, QUnit seemed more straight-forward since the discussion is not intertwined with BDD concepts, thus it might make sense to present it first. However, I think it might be a little tricky to move QUnit/SinonJS in front of Jasmine at this point since I think the SinonJS chapter uses examples based on code presented in the Jasmine chapter and there may be other references between the sections which would need to be adjusted.

@addyosmani
Copy link
Owner Author

I appreciate your input, @dcmaf. I think that this move might make sense for the second edition of the book but I agree that for now it might make more sense to keep the organization of sections as is.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants