{"id":12,"date":"2014-10-01T16:22:00","date_gmt":"2014-10-01T16:22:00","guid":{"rendered":"https:\/\/redbooth.com\/engineering\/?p=12"},"modified":"2014-10-10T13:39:47","modified_gmt":"2014-10-10T13:39:47","slug":"the-coordinator-pattern","status":"publish","type":"post","link":"https:\/\/redbooth.com\/engineering\/javascript\/the-coordinator-pattern","title":{"rendered":"The Coordinator pattern"},"content":{"rendered":"<p>I wanted to share a pattern that we&#8217;ve been using lately in our<br \/>\nBackbone\/Marionette application. It&#8217;s a pattern that we strongly<br \/>\nrecommend for separating monolithic applications into components.<\/p>\n<h3>UI-heavy applications and components<\/h3>\n<p>With the rise of reactive programming and frameworks like Facebook&#8217;s<br \/>\nReact its becoming more apparent that state should never be kept on<br \/>\nthe View layer. The programs we write should only deal with state<br \/>\nand when this changes it should update the views <em>reactively<\/em>.<\/p>\n<p>We&#8217;ve experienced how much easier it is to maintain\/test the programs<br \/>\nwritten with this approach. That being said, most architecture sins are<br \/>\ncommitted on writing UI-heavy applications. Those have a lot of working<br \/>\nparts that have to talk to each other. Its easy to fall into the trap<br \/>\nand have all these parts being coupled with each other. To avoid this<br \/>\nscenario, those apps would be better implemented with components.<\/p>\n<blockquote><p>A component is a <em>reusable<\/em>\u00a0view that <em>has a state<\/em>, can be <em>interacted<\/em>\u00a0with<br \/>\nand <em>can be composed<\/em>.<\/p><\/blockquote>\n<p>Separating a problem into components is not an easy task, and we soon began to ask ourselves the following questions:<\/p>\n<ul>\n<li>Where do I keep the component state?<\/li>\n<li>How do I make two components speak to each other?<\/li>\n<li>How can a component request the state of another component?<\/li>\n<li>How do I achieve all of the above without them knowing each other?<\/li>\n<\/ul>\n<p>You can answer all this questions with the Coordinator pattern.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/s3.amazonaws.com\/wordpress-production\/wp-content\/uploads\/sites\/7\/2014\/10\/coordinator.png\" alt=\"Coordinator\" \/><\/p>\n<h3>What is a Coordinator?<\/h3>\n<p>A Coordinator is an event aggregator that can hold state. I like to describe<br \/>\nthem like &#8220;little sticks&#8221; that are used to tie components together. They hold<br \/>\ncomponent&#8217;s shared state and serve as a localized bus of events.<\/p>\n<p>Components can use that bus to communicate with each other.<\/p>\n<p>Imagine we have a UI with 3 components:<\/p>\n<ul>\n<li>Country selector<\/li>\n<li>State selector<\/li>\n<li>Map<\/li>\n<\/ul>\n<p>The map reacts to country\/state changes. The state selector updates itself<br \/>\non selecting a country. We won&#8217;t store any state on the views, but we will use a shared Coordinator that will allow them to communicate without knowing each other.<\/p>\n<p>Let&#8217;s represent this with a dummy Marionette application:<\/p>\n<pre>\r\nCountrySelector = Backbone.Marionette.ItemView.extend({\r\n  events: { 'change': 'onChange' }\r\n, onChange: function () {\r\n    this.model.set('country', this.$el.val());\r\n  }\r\n, serializeData: function () {\r\n    return {country: this.model.get('country')};\r\n  }\r\n});\r\n\r\nStateSelector = Backbone.Marionette.ItemView.extend({\r\n  events: { 'change': 'onChange' }\r\n, onChange: function () {\r\n    this.model.set('state', this.$el.val());\r\n  }\r\n, serializeData: function () {\r\n    return {state: this.model.get('state')};\r\n  }\r\n});\r\n\r\nMap = Backbone.Marionette.ItemView.extend({\r\n  serializeData: function () {\r\n    return {\r\n      state: this.model.get('state')\r\n    , country: this.model.get('country')\r\n    };\r\n  }\r\n});\r\n\r\nMainApplication = Backbone.View.extend({\r\n  initialize: function () {\r\n    var coordinator = new Backbone.Model()\r\n      , options = {model: coordinator};\r\n\r\n    this.map = new Map(options)\r\n    this.state_sel = new StateSelector(options)\r\n    this.country_sel = new CountrySelector(options);\r\n\r\n    this.listenTo(coordinator, 'change:country', this.state_sel.render);\r\n    this.listenTo(coordinator, 'change', this.map.render);\r\n  }\r\n});\r\n\r\n<\/pre>\n<h3>Benefits of the Coordinator pattern<\/h3>\n<p>We&#8217;ve seen that this problem is not only bound to Views and UI-heavy<br \/>\napplications. Any kind of monolithic application benefits from being<br \/>\nsplit into smaller self-contained components.<br \/>\nThese components need a way to interact. Coordinators are an awesome solution!<\/p>\n<p>One of the best things about this pattern is that most of the<br \/>\nenvironments \/ frameworks have the necessary tools out of the box:<br \/>\nWe are using them in Rails and soon in our mobile<br \/>\napps too. Give them a try!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wanted to share a pattern that we&#8217;ve been using lately in our Backbone\/Marionette application. It&#8217;s a pattern that we strongly recommend for separating monolithic applications into components. UI-heavy applications and components With the rise of reactive programming and frameworks like Facebook&#8217;s React its becoming more apparent that state should never be kept on the <a class=\"read-more\" href=\"https:\/\/redbooth.com\/engineering\/javascript\/the-coordinator-pattern\">&hellip;&nbsp;<span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":37,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[47,5,6],"class_list":["post-12","post","type-post","status-publish","format-standard","hentry","category-javascript","tag-backbone","tag-javascript-2","tag-marionette"],"_links":{"self":[{"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/posts\/12","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/users\/37"}],"replies":[{"embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/comments?post=12"}],"version-history":[{"count":0,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/posts\/12\/revisions"}],"wp:attachment":[{"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/media?parent=12"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/categories?post=12"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/redbooth.com\/engineering\/wp-json\/wp\/v2\/tags?post=12"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}