A few of things off the top of my head that we do on Tweetdeck, where we have just under 200 Flight components forming about a third of the codebase (I think, rough calculations there!). This is how I think of it, at least. Others may disagree slightly, but there are the patterns I see in our code:
Components
- There are two, maybe three, discernable types of components: UI, UI controller and data.
- All three use mixins, although the sets of mixins they use do not tend to overlap.
- UI components are initialised around a specific, small area of DOM to add or create functionality there.
- We extensively use mixins with UI components to add functionality as diverse as templating, lifecycle management or opening dropdowns and modals.
- UI controllers and data components sit usually at the document level, but sometimes elsewhere.
- Data components rarely use mixins.
- UI controllers either tie together the functionality of a number of UI components or manage global state that a single component could not; the latter are often paired with a mixin. For example, we have a (very lightweight) DragDropController, and mixin called withDragDrop. These combine to allow any component to react to drag/drop behaviour – the controller just manages the start and end events that the individual components could not. Another example is the FocusController and withFocus.
- We nest components (!) using a mixin called withTeardown, which we really should open source or get into Flight core. It's very useful, allowing a component to attach a 'child' component and couple their lifecyles. Parent tears down; child tears down (but not the other way). 'Child' components can nest their own children, and so teardown can form a kind of cascade. This is really important for TweetDeck as it's a single page app – we can't (ever) teardownAll! Almost every new component we create uses it, and it (IMO) makes for some very nice code.
Events
- Events are namespaced by the type of component they come from (ui or data)
- These will (mostly) then be namespaced again according to what bit or functionality they are associated with: uiDragStart, uiKeyEnter, dataAuthComplete.
- There is also uiRequestX, but I haven't seen any new examples recently.
- We sometimes use xNeedsY for request/response-type event pairings: uiNeedsTypeaheadSuggestions and dataTypeaheadSuggestions.
- We try to trigger and listen on the document as infrequently as possible, preferring rather to trigger on the component's node and allow the event to bubble. This way you can reuse components in multiple contexts, with parent components managing those events however they see fit. It really works too – we reuse our login forms like this way.
Hope that helps. I think
twitter.com have more sheer Flight code than us, but our lifecycle requirements are (afaik) completely different, so I'd imagine things are a bit different over there. Of course, this stuff is always evolving so I'd expect things to change.
Also, I'd be really interesting in comparing notes with others!