Slide 1

Slide 1 text

Monday, April 15, 13

Slide 2

Slide 2 text

“In con guration-driven development, developers make all modi cations primarily in XML les.” Monday, April 15, 13

Slide 3

Slide 3 text

Monday, April 15, 13

Slide 4

Slide 4 text

Monday, April 15, 13

Slide 5

Slide 5 text

Monday, April 15, 13

Slide 6

Slide 6 text

Monday, April 15, 13

Slide 7

Slide 7 text

Monday, April 15, 13

Slide 8

Slide 8 text

fire bird Monday, April 15, 13

Slide 9

Slide 9 text

Monday, April 15, 13

Slide 10

Slide 10 text

exibility support arbitrary combinations of components interactivity support arbitrary interactions between components speed individual apps shouldn’t contain anything they don’t need 3 key problems to solve Monday, April 15, 13

Slide 11

Slide 11 text

Monday, April 15, 13

Slide 12

Slide 12 text

Limin & her dog Monday, April 15, 13

Slide 13

Slide 13 text

Monday, April 15, 13

Slide 14

Slide 14 text

Monday, April 15, 13

Slide 15

Slide 15 text

Monday, April 15, 13

Slide 16

Slide 16 text

Monday, April 15, 13

Slide 17

Slide 17 text

Monday, April 15, 13

Slide 18

Slide 18 text

bootstrapper {""foo"":"{"…"}"} ui request handler customer ui request initialize components init "top model" w/component data init submodels request data init "top view" w/component data init subviews delegate events initialize "outlets" request batcher components initialized render components model data loaded $BV.ui('rr',  'show_reviews',  {  /*  ...  */  }); Monday, April 15, 13

Slide 19

Slide 19 text

Monday, April 15, 13

Slide 20

Slide 20 text

"reviewContentList1"  :  {    "features"  :  {        "self"  :  ["headToHead",  "contentFilter",  "contentItemColl        "contentItem"  :  ["has:stars",  "has:secondaryRatings",  "ha        "pagination"  :  ["ugcCount"],        "secondaryContentList"  :  ["secondaryContentItemCollection        "secondaryContentItem"  :  ["avatar",  "feedback"],        "contentFilter"  :  ["has:filterButton"]    },    //  ... }, Monday, April 15, 13

Slide 21

Slide 21 text

"reviewContentList1"  :  {    "features"  :  {        "self"  :  ["headToHead",  "contentFilter",  "contentItemColl        "contentItem"  :  ["has:stars",  "has:secondaryRatings",  "ha        "pagination"  :  ["ugcCount"],        "secondaryContentList"  :  ["secondaryContentItemCollection        "secondaryContentItem"  :  ["avatar",  "feedback"],        "contentFilter"  :  ["has:filterButton"]    },    //  ... }, Monday, April 15, 13

Slide 22

Slide 22 text

"contentItem"  :  [    "has:stars",      "has:secondaryRatings",      "has:tags",      "feedback",      "secondaryContentList",      "has:secondaryContentBtn" ], Monday, April 15, 13

Slide 23

Slide 23 text

   
       {{>  responseFrom  .}}        {{#ifHasFeature  "stars"}}            {{>  contentStars  }}        {{/ifHasFeature}}        {{>  contentMeta  }}    
   
       {{>  contentTitle  }}    
{{{mountView  "secondaryContentList"  .}}}
Monday, April 15, 13

Slide 24

Slide 24 text

Monday, April 15, 13

Slide 25

Slide 25 text

"contentSearch1"  :  {    //  ...    "outlets"  :  {        "showreviews"  :  [{              "component"  :  "reviewContentList1",              "event"  :  "scrolltocontent"          }],        "showquestions"  :  [{              "component"  :"questionContentList1",              "event"  :  "scrolltocontent"          }]    } }, Monday, April 15, 13

Slide 26

Slide 26 text

_(outlets).each(function  (targets,  key)  {    _(targets).each(function  (target)  {        model.on(key,  createEventHandler(target));    }); }); function  createEventHandler  (target)  {    return  function  ()  {        var  targetComponent  =  components.find(target.component);        if  (!targetComponent)  {  return;  }        var  scope  =  targetComponent.getScope(targetComponent.contentType);        var  args  =  [                    scope  +  ':'  +  target.event                ].concat(  [].slice.call(arguments)  );        ENV.trigger.apply(ENV,  args);        return;    }; } Monday, April 15, 13

Slide 27

Slide 27 text

//  events  on  a  contentItem  view events  :  {    'click  .bv-­‐rating-­‐stars-­‐container'  :  'clickStars',    'click  .bv-­‐content-­‐secondary-­‐btn'  :  'showSecondarySubmission',    'click  .bv-­‐media-­‐item':  'showMedia',    'click  .bv-­‐secondary-­‐content-­‐link'  :  'preventDefault',    'click  .bv-­‐content-­‐item-­‐close'  :  'closeQuestion',    'click  .bv-­‐fullprofile-­‐popup-­‐target'  :  'launchProfile',    "click  .bv-­‐show-­‐more-­‐link"  :  "showFullContent" }, Monday, April 15, 13

Slide 28

Slide 28 text

_(subview.events).each(function  (methodName,  signature)  {    var  match  =  signature.match(eventSplitter);    var  eventName  =  match[1]  +  '.delegated'  +  subview.id;    var  selector    =  match[2];    var  method  =  subview[methodName];    this.$el.delegate(          selector,  eventName,  makeResponder(signature,  method)      ); },  this); Monday, April 15, 13

Slide 29

Slide 29 text

" init submodels request data init subviews delegate events s" request batcher components initialized render components model data loaded " init submodels request data init subviews delegate events s" request batcher components initialized render components model data loaded Monday, April 15, 13

Slide 30

Slide 30 text

Monday, April 15, 13

Slide 31

Slide 31 text

what’s great self-serve app creation preview any customer’s app economies of scale writing new features is more fun than implementation, amirite? Monday, April 15, 13

Slide 32

Slide 32 text

huge initial investment, ramp-up time it helps to have a legacy app no one-size- ts-all framework automated tests become imperative document all the things what’s challenging Monday, April 15, 13

Slide 33

Slide 33 text

is there a future where we can generalize this DSL? how does this work for apps with more dynamic data? what’s next Monday, April 15, 13

Slide 34

Slide 34 text

@rmurphey  •  rmurphey.com bazaarvoice.com pinboard.in/u:rmurphey/t:config-­‐driven-­‐apps/ Monday, April 15, 13