Tip:
Highlight text to annotate it
X
{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf510 {\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww28620\viewh19100\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
\f0\fs36 \cf0 Hello Again. This video continues to show how JavaScriptMVC\
breaks down the Srchr app into isolated, tested, and documented modules.\
\ Part 1 showed how we decided which modules
to build. This\ part, part 2, shows how we actually build,
test, and document them\ and then assemble them into the srchr application.\
\ So lets start building stuff ...\
\ SETUP\
\ After installing JavaScriptMVC, I should see
the following folders\ \
arrows\ \
- can - for CanJS, JavaScriptMVC's MVC utilities\ - documentjs - for documenting the app\
- funcunit - for testing\ - the jmvc folder contains generators for
creating boilerplate code.\ - jquerypp - contains a bunch of useful jQuery
extensions.\ - steal - provides dependency management and
production builds.\ \
The first thing I did was create an application skeleton with a generator. \
It created a srchr folder with index.html \
- which will be the app's page and srchr.js, which is\
the entry point for the application. \ \
The srchr folder should\ contain everything unique to the srchr application,
so\ I put my search, history, and results controllers
in there. I\ used the control generator to create a skeleton
for those modules.\ \
We put Modules that could be shared across applications in a\
ui folder. Often the folder is a git submodule that can be shared \
across several apps. I'll use the control generator\
to generate\ \
tabs\ placeholder\
and list\ \
Now we have a place to build each module.\ \
\ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
\cf0 PROCESS\ \
Lets take a look at how we make these modules. We'll focus on the \
process, not the code itself. This is because the process\
matters more than the actual code. \ \
Our process shares the same goals as Bitovi -\
we want to produce quality, tested, and documented apps in the shortest amount of time.\
\ Here's our process:\
\ 1. First, we create a demo page to experiment
with the module's HTML and JavaScript api.\ 2. Second, we document the module.\
3. Next we write tests for the module\ 4. and then write the actual module's code.\
5. Finally, we make sure everything passes.\ 6. and then move on to the next module.\
7. Once several modules are complete, we assemble them within higher order modules.\
\ -----\
\ To see this process in action, lets start
with the Tabs module.\ \
demo page.\ \
\ ## tabs\
\ Looking inside the generated tabs folder,
it contains everything we need to\ develop tabs as a micro application.\
\ It not only contains a JavaScript file for
the module's code and \ a LESS script for the module's styles, it
contains\ \
- a demo page that loads and creates the module, \
- a test script, and a\ - test page that runs the test script\
\ The tabs folder is it's own little universe
where we can build the tabs component\ in isolation from the rest of the modules
we will build.\ \
Now lets walk through the results of our process on the Tabs widget.\
\ ### Demo\
\ A demo page lets you experiment with a module's
JavaScript and HTML API\ by simulating how a user might use it. A good
API is powerful, flexible, and easy to use. \
\ For this tabs widget, I chose to make it work
like a "standard" tabs widget,\ with the ability to enable and disable tabs.\
\ By a "standard tabs widget", I mean the tabs
anchor element's href property points\ to the id of the tab content element to be
shown.\ \
After adding the HTML for the tabs widget, I setup Tabs in a\
script tag. \ \
I used steal to load the ui/tabs module and get the Tabs\
constructor function.\ \
The tabs widget needs some way to change which tabs are enabled or\
disabled. Instead of adding methods to enable or disable tabs,\
I'll had Tabs accept a can.compute of an array of enabled tab ids.\
\ By changing the enabled ids, Tabs will enable
and \ disable tab buttons. I demo this functionality
by adding a button that when clicked\ changes the ids in enabled.\
\ Now that we have a rough picture of the Tabs
module's API, we\ can fill out that picture by documenting the
module.\ \
### Docs\ \
Documentation makes you think about how your code is going to be\
used. =====\ \
If you can easily document a module's functionality, it's\
a good bet that you're designing \ a useful API. \
\ In tabs.js, I documented how to create a new
tabs widget within a multi-line comment. \ \
Later, we'll use DocumentJS to generate \ a documentation page from this comment. \
\ I also added the tabs demo page to the documentation
so people\ will be able to see the Tabs widget in action.\
\ Once I settled the API with a demo and documentation,
\ I moved on to writing tests.\
\ ### Testing\
\ Creating tests, like a demo page and documentation,
helps you explore\ and improve the API of the module you're writing.
But, it also\ adds an CRITICAL additional benefit: it can
verify the API is actually working.\ \
In tabs_test.js, I added tests for showing and hiding tabs,\
enabling and disabling tabs, and more.\ \
Once that was done, I started writing the tabs code.\
\ ### Code\
\ At this point, with a full picture of the
API, a demo page, and tests,\ it's quite easy to write the tabs module.\
\ In tabs.js, I implement Tabs with can.Control.\
\ ### Verify\
\ While writing the tabs code, I use the tests
and demo page\ to make sure the module is working.\
\ Once all tests passed ... I moved on to the
next module. =======\ \
### Repeat\ \
I repeated the previous 5 steps with the List module.\
\ DEMO - First, I created a demo page that uses
the List module.\ \
Second, I documented the List module. \ \
Next, I wrote tests for the List module.\ \
And then wrote the List modules code.\ \
Finally, I verified the tests passed and demo functioned properly.\
\ \
### Assemble\ \
Once these lower-level views were complete, I began assembling them into\
controllers. I combined Tabs and List\ into the Results controller following the
same process as before,\ starting with the results demo page.\
\ ## Results\
\ ### Demo\
\ The results controller is created on a simple
Div element. It's passed \ the observable from the first video that represents
the current search. \ \
### Docs\ \
Next, I added documentation.\ \
### TESTING\ \
And tested the results controller (which is mostly testing the integration between\
the tabs and list views).\ \
### Code\ \
The Results code is pretty straightforward. It needs to\
setup Tabs to show and hide a List view for \
each service.\ \
It starts by translating currentSearch into the enabled\
and params computes that Tabs and the Lists need.\
If current search changes, the value of params and\
enabled are automatically updated.\ \
Next Results renders a template that will create the HTML the tabs\
needs and create a List view for each model type. It creates\
the List view with the listFor helper.\ \
Finally, the tabs control is created.\ \
### Verify\ \
After verifying that the Results Controller's test and demo page works, \
\ ## Assemble App\
\ I repeated this process for the history and
search controllers. Now I will show you how\ how I assembled the controllers into the main
application. Of course,\ I will follow the same process as I've used
for everything else. But\ instead of a demo page, I'll setup the page
users will visit.\ \
In srchr.html, I added the elements we will create search, history, and results controllers
on.\ \
### Docs\ \
I'll add srchr's docs in srchr.md. These docs typically cover how to install, run, test,\
and build the app and generate the apps documentation.\ \
### Testb\ \
the srchr app's test script/ loads and run every module's tests and then provide some
tests\ of its own. It's own test, tests the integration
between the various controllers.\ \
### Code\ \
The code for the srchr app is pretty simple. It steals the controllers it needs,\
creates the shared observable currentSearch, and creates each controller.\
\ ### Verify\
\ Now I can actually use the app. And verify
the app works by running every modules tests.\ \
All the tests passed. Ah mazing!\ \
\ ## Build\
\ Right now, steal is loading the unminified
version of every JavaScript, LESS, CSS\ and template file.\
\ To make srchr load faster, I'll combine and
minify all the apps files into a single JS and\
CSS file using the app's build script.\ \
To make steal use the production files, I load the production version of steal in index.html.\
\ ## Document\
\ To generate the documentation, I run the apps
docs script. This creates docs.html.\ \
If we checkout tabs documentation page, we can see the working demo as well as a link
\ to its test page.\
\ ## Result\
\ We are done. Lets look at the result of what
we've accomplished!\ \
\ \
The result is that every module has it's own documentation with a working demo \'85 and\
every module is tested.\ \
We have low level view-widgets that could almost certainly be used in other \
projects. \ \
The complexity of assembling the low-level widgets is broken up by using\
the observer pattern. Everything is isolated.\ \
And steal's build (not to mention can.Control and can.View) help our app load fast.\
\ This is how you build a JavaScript application
regardless of\ what library or framework you use. However,
JavaScriptMVC makes it damn easy.\ }