The jQuery Divide

62
The jQuery Divide Rebecca Murphey • JSConf.eu • 25.09.2010 @rmurphey • rebeccamurphey.com Wednesday, September 29, 2010

description

jQuery is drawing newcomers to JavaSCript in droves. As a community, we have an obligation -- and it is in our interest -- to help these newcomers understand where jQuery ends and JavaScript begins.

Transcript of The jQuery Divide

Page 1: The jQuery Divide

The jQuery DivideRebecca Murphey • JSConf.eu • 25.09.2010@rmurphey • rebeccamurphey.com

Wednesday, September 29, 2010

Page 2: The jQuery Divide

Wednesday, September 29, 2010

Page 3: The jQuery Divide

what this presentation covers

how jQuery’s popularity means newcomers learn bad things

why I think this is worth talking about at JSConf

what I think the larger JavaScript community needs to do about it

Wednesday, September 29, 2010

Page 4: The jQuery Divide

We need you to help us organize our jQuery-based application. It’s a steaming pile of unmaintainable crap.

Wednesday, September 29, 2010

Page 5: The jQuery Divide

But we want to keep using jQuery. It’s just so easy! And popular!

Wednesday, September 29, 2010

Page 6: The jQuery Divide

It’s almost guaranteed that the client will point to jQuery’s popularity as a reason to keep using it. It’s also a pretty fair bet what their code will look like.

Wednesday, September 29, 2010

Page 7: The jQuery Divide

var toggleHistItems = function (selTabId) { console.log('Selected Tab ID: ' + selTabId); var curEl = $('#' + selTabId); var bSLTabSelected = $('#slhis').is('[class=left selected]'); $('#divNoRecordMsg').hide(); switch (selTabId) { case 'slhis': $('tr[class^=fk]').show(); $('.cPriceRent').html('Foo/Bar'); rentalRateIsVisible(true); $('#historySortButton').show(); //curEl.addClass('left'); if ($('#historySort1').is(':visible')) { if ($('#fooLeaseHistory > tbody > tr[class^=fk]').length === 0) { if (!$('#divAction1').is(':visible') && !$('#divRSAction1').is(':visible')) { $('#divNoRecordMsg').html('There is no history at this time').show(); } $('#historySortButton').hide(); $('#fooLeaseHistory').slideUp(); } else { $('#fooLeaseHistory').slideDown(); } } else { if ($('#listingDisplay > tbody > tr[class^=fk]').length === 0) { if (!$('#divAction1').is(':visible') && !$('#divRSAction1').is(':visible')) { $('#divNoRecordMsg').html('There is no history at this time').show(); } $('#historySortButton').hide(); $('#listingDisplay').slideUp(); } else { $('#listingDisplay').slideDown(); } } break; case 'shis': rentalRateIsVisible(false); $('#historySortButton').show(); if (bSLTabSelected) { $('.fkSale').fadeIn(); $('.Thinger').fadeOut(); } else { $('.fkSale').show(); $('.Thinger').hide(); } $('.cPriceRent').html('Price'); if ($('#historySort1').is(':visible')) { if ($('#fooLeaseHistory > tbody > .fkSale').length === 0) { if (!$('#divAction1').is(':visible') && !$('#divRSAction1').is(':visible')) { $('#divNoRecordMsg').html('There is no Sale History at this time').show(); } $('#historySortButton').hide(); $('#fooLeaseHistory').slideUp(); } else { $('#fooLeaseHistory').slideDown(); } } else { if ($('#listingDisplay > tbody > .fkSale').length === 0) { if (!$('#divAction1').is(':visible') && !$('#divRSAction1').is(':visible')) { $('#divNoRecordMsg').html('There is no history at this time').show(); } $('#historySortButton').hide(); $('#listingDisplay').slideUp(); } else { $('#listingDisplay').slideDown(); } } break; case 'lhis': rentalRateIsVisible(true); $('#historySortButton').show(); if (bSLTabSelected) { $('.fkSale').fadeOut(); $('.Thinger').fadeIn(); } else { $('.fkSale').hide(); $('.Thinger').show(); } $('.cPriceRent').html('Rent'); if ($('#historySort1').is(':visible')) { if ($('#fooLeaseHistory > tbody > .Thinger').length === 0) { if (!$('#divAction1').is(':visible')) { $('#divNoRecordMsg').html('There is no other history at this time').show(); } $('#historySortButton').hide(); $('#fooLeaseHistory').slideUp(); } else { $('#fooLeaseHistory').slideDown(); } } else { if ($('#listingDisplay > tbody > .Thinger').length === 0) { if (!$('#divAction1').is(':visible')) { $('#divNoRecordMsg').html('There is no other history at this time').show(); } $('#historySortButton').hide(); $('#listingDisplay').slideUp(); } else { $('#listingDisplay').slideDown(); } } break; } //set current tab curEl.addClass('selected'); $('h3[class=history] a').each(function () { if ($(this).attr('id') !== curEl.attr('id')) { $(this).removeClass('selected'); } });};

Wednesday, September 29, 2010

Page 8: The jQuery Divide

Plus that way our database guy can still help us out with the front end.

Wednesday, September 29, 2010

Page 9: The jQuery Divide

*headdesk*

Wednesday, September 29, 2010

Page 10: The jQuery Divide

“... it turns out that if you have absolutely no idea what you’re doing in the language you can still generally make things work.”

Douglas Crockford, Yahoo!

http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-2

Wednesday, September 29, 2010

Page 11: The jQuery Divide

the morals of the story

perceived popularity & perceived ease of use factor into library choice (duh)

people who don’t know JS write non-trivial JS apps whether we like it or not

there’s a demand for answers to app org questions

the people seeking these answers aren’t necessarily dumb, just untrained in JS

Wednesday, September 29, 2010

Page 12: The jQuery Divide

jQuery meant we didn’t have to understand this ...

Wednesday, September 29, 2010

Page 13: The jQuery Divide

var xmlhttp;

if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safarixmlhttp=new XMLHttpRequest();} else {// code for IE6, IE5xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");}xmlhttp.open("POST","ajax_test.asp",true);xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");xmlhttp.send("fname=Henry&lname=Ford");

xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { document.getElementById("myDiv").innerHTML = xmlhttp.responseText; }};

Wednesday, September 29, 2010

Page 14: The jQuery Divide

we could just write this ...

Wednesday, September 29, 2010

Page 15: The jQuery Divide

$.post( 'ajax_test.php', { fname : 'Henry', lname : 'Ford' }, function(resp) { $('#myDiv').html(resp); });

Wednesday, September 29, 2010

Page 16: The jQuery Divide

jQuery offers a really clear answer when we need to build this ...

Wednesday, September 29, 2010

Page 17: The jQuery Divide

Wednesday, September 29, 2010

Page 18: The jQuery Divide

$(document).ready(function() { $('#searchForm').submit(function(e) { e.preventDefault(); var myVal = $(this).find('input:first').val(); $.ajax({ url : 'search.php', data : { term : myVal }, dataType : 'json', success : function(resp) { var tpl = '<li><h2>%title</h2><p>%desc</p></li>'; $('#results').html( $.map(resp.results, function(r) { return tpl.replace('%title', r.title).replace('%desc', r.desc); }).join(''); ); } }); });});

Wednesday, September 29, 2010

Page 19: The jQuery Divide

... which is why we see this ...

Wednesday, September 29, 2010

Page 20: The jQuery Divide

Wednesday, September 29, 2010

Page 21: The jQuery Divide

Wednesday, September 29, 2010

Page 22: The jQuery Divide

But when it comes time to create this ...

Wednesday, September 29, 2010

Page 23: The jQuery Divide

Wednesday, September 29, 2010

Page 24: The jQuery Divide

... it can be hard for the average jQuery developer to see how they might get from the #rst version to the second without creating a whole lot of spaghetti code.

Wednesday, September 29, 2010

Page 25: The jQuery Divide

It turns out jQuery’s DOM-centric patterns are a fairly terrible way to think about applications.

Wednesday, September 29, 2010

Page 26: The jQuery Divide

Applications require thinking in terms of loosely coupled, DRYed out units of functionality, designed to work with each other without depending on each other.

Wednesday, September 29, 2010

Page 27: The jQuery Divide

require.def('views/Results', [], function() { return Class.extend({ itemTemplate : '<li><h2>%title</h2><p>%desc</p></li>',

init : function(el) { this.el = el; $.subscribe('/search/results', $.proxy(this, '_showResults')); },

_showResults : function(results) { var tpl = this.itemTemplate, html = $.map(results, function(r) { return tpl .replace('%title', r.title) .replace('%desc', r.desc); }).join('');

this.el.append(html); } });});

Wednesday, September 29, 2010

Page 28: The jQuery Divide

require.def('views/Results', [], function() { return Class.extend({ itemTemplate : '<li><h2>%title</h2><p>%desc</p></li>',

init : function(el) { this.el = el; $.subscribe('/search/results', $.proxy(this, '_showResults')); },

_showResults : function(results) { var tpl = this.itemTemplate, html = $.map(results, function(r) { return tpl .replace('%title', r.title) .replace('%desc', r.desc); }).join('');

this.el.append(html); } });});

omg wtf is this???

Wednesday, September 29, 2010

Page 29: The jQuery Divide

We shouldn’t scold; cartoon client man — and the developers lured to JavaScript by jQuery — don’t know what they don’t know.

Wednesday, September 29, 2010

Page 30: The jQuery Divide

Some people i’ve talked to think we or the market should discourage these people from writing code, but that ship has already sailed.

Wednesday, September 29, 2010

Page 31: The jQuery Divide

ey’re writing code whether we like it or not, and it’s not good code.

Wednesday, September 29, 2010

Page 32: The jQuery Divide

is has actual effects on the perception of JavaScript, and on our ability to do interesting things with it.

Wednesday, September 29, 2010

Page 33: The jQuery Divide

In a nutshell, this is what these developers need to learn:

Wednesday, September 29, 2010

Page 34: The jQuery Divide

jQuery

JavaScript

Wednesday, September 29, 2010

Page 35: The jQuery Divide

Companies need developers, and if bad ones are all that’s available, they’ll hire them anyway.

Wednesday, September 29, 2010

Page 36: The jQuery Divide

Wednesday, September 29, 2010

Page 37: The jQuery Divide

Aaron Newton from Cloudera wrote a post a while back about how hard it is to #nd “badass” JavaScript developers.

Wednesday, September 29, 2010

Page 38: The jQuery Divide

e productive reaction to a post like that isn’t to feel superior because you’re a badass JavaScript developer.

Wednesday, September 29, 2010

Page 39: The jQuery Divide

e productive reaction is to #gure out how to #x it.

Wednesday, September 29, 2010

Page 40: The jQuery Divide

jQuery’s ease has brought us legions of developers who think of an application like this: disparate pieces with few organizing principles; components that are fun but aren’t made to work together.

Wednesday, September 29, 2010

Page 41: The jQuery Divide

We need to turn them into developers who think of applications like this.

Wednesday, September 29, 2010

Page 42: The jQuery Divide

five things to think about

Wednesday, September 29, 2010

Page 43: The jQuery Divide

popularity contests are stupid

#1

Wednesday, September 29, 2010

Page 44: The jQuery Divide

Making decisions based on this graph ...

Wednesday, September 29, 2010

Page 45: The jQuery Divide

Wednesday, September 29, 2010

Page 46: The jQuery Divide

... makes as much sense as making decisions based on this graph ...

Wednesday, September 29, 2010

Page 47: The jQuery Divide

Wednesday, September 29, 2010

Page 48: The jQuery Divide

We have to be intellectually honest when we discuss library pros & cons — and vigorous in correcting those who are not.

http://xpandapopx.deviantart.com/art/The-Prideful-Hypocrite-68848153

Wednesday, September 29, 2010

Page 49: The jQuery Divide

#2choose tools, not APIs

Wednesday, September 29, 2010

Page 50: The jQuery Divide

// YUI3var parent = Y.Node.create('<div/>'), child = Y.Node.create('<p>foo</p>'); child.on('click', fn);parent.appendChild(child);

// Dojovar parent = dojo.create('div'), child = dojo.create('p', { innerHTML : 'foo' }); dojo.connect(child, 'click', fn);dojo.place(child, parent);

// jQueryvar parent = $('<div/>');$('<p>foo</p>') .click(fn) .appendTo(parent);

Wednesday, September 29, 2010

Page 51: The jQuery Divide

$(document).ready(function() { $('#searchForm').submit(function(e) { e.preventDefault(); var myVal = $(this).find('input:first').val(); $.ajax({ url : 'search.php', data : { term : myVal }, dataType : 'json', success : function(resp) { var tpl = '<li><h2>%title</h2><p>%desc</p></li>'; $('#results').html( $.map(resp.results, function(r) { return tpl.replace('%title', r.title).replace('%desc', r.desc); }).join(''); ); } }); });});

Wednesday, September 29, 2010

Page 52: The jQuery Divide

(function(d, $) {d.ready(function() { d.connect('searchForm', 'submit', function(e) { e.preventDefault(); var myVal = $('input', this)[0].value; d.xhrGet({ url : 'search.php', content : { term : myVal }, handleAs : 'json', load : function(resp) { var tpl = '<li><h2>%title</h2><p>%desc</p></li>'; d.byId('results').innerHTML = d.map(resp.results, function(r) { return tpl.replace('%title', r.title).replace('%desc', r.desc); }).join(''); } }) });});})(dojo, dojo.query);

Wednesday, September 29, 2010

Page 53: The jQuery Divide

understanding the problem is key to determining the solution

#3

Wednesday, September 29, 2010

Page 54: The jQuery Divide

Decision-makers need help to make actual decisions ... and understand their consequences.

Wednesday, September 29, 2010

Page 55: The jQuery Divide

understand the project

application vs. website?

team skills: dedicated F2E?

team size & turnover?

project lifecycle: long-term, evolving product?

service-oriented back-end?

Wednesday, September 29, 2010

Page 56: The jQuery Divide

assess the application’s needs

code & #le organization?

dependency management & build tools?

templating & templated widgets?

data abstractions & binding?

a11y, i18n & l10n?

Wednesday, September 29, 2010

Page 57: The jQuery Divide

then and only then, choose your tools

features that address the application’s needs?

active development?

active community?

documentation & resources?

institutional backing?

Wednesday, September 29, 2010

Page 58: The jQuery Divide

RTFM can’t be our go-to answer

#4

Wednesday, September 29, 2010

Page 59: The jQuery Divide

“[It’s] a difficult time to learn to be a JavaScript ninja, or even a JavaScript street beggar. Good resources for getting beyond the very basics are hard to !nd, documentation is sparse or wrong, and a snippet of code that may have been viable last year is now an anti-pattern.”

http://www.clientcide.com/deep-thoughts/why-its-a-good-idea-to-be-a-javascript-developer-and-what-it-takes-to-be-one/#comment-32703

Wednesday, September 29, 2010

Page 60: The jQuery Divide

sharing what we knowis as important as

making new things

#5

Wednesday, September 29, 2010

Page 61: The jQuery Divide

Wednesday, September 29, 2010

Page 62: The jQuery Divide

rebeccamurphey.com • blog.rebeccamurphey.com • @rmurphey

anks, in guilt-free alphabetical order, to: Tim Caswell, John Hann, Peter Higgins, Tom Hughes-Croucher, Paul Irish, Brian LeRoux, Roger Raymond, Alex Sexton, Colin Snover, Adam Sontag, Chris Williams, and to everyone who listened to me formulate my thoughts.

Wednesday, September 29, 2010