<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><description>I post about mobile and web development.  Also other things.</description><title>Todd Way</title><generator>Tumblr (3.0; @toddway)</generator><link>https://toddway.com/</link><item><title>Share artifacts with an orphan branch</title><description>&lt;p&gt;Over the last several years I&amp;rsquo;ve worked with a variety of great hosted services for team code integration:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;For build automation - Jenkins, Bitrise, CircleCi, BuddyBuild, TeamCity.&lt;/li&gt;
&lt;li&gt;For code analysis - SonarQube, Codacy, Code Climate, Veracode.&lt;/li&gt;
&lt;li&gt;For peer review - Github, Bitbucket, GitLab, Gerrit.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;When everything works in harmony (checking out files, compiling, running tests, analyzing code structure, assembling artifacts, posting clear results) the whole team sees steady feedback, early in the development cycle, that helps prevent defects, educate new team members, and nudge us all to better design habits.&lt;/p&gt;

&lt;p&gt;But for various reasons we can&amp;rsquo;t always set up the perfect recipe of hosted services for every project. If information that we&amp;rsquo;ve counted on in the past is missing, unreliable, or hard to access, the impact quickly fades. In the worst cases, the &lt;a href="https://youtu.be/ddPQAJSm2cQ"&gt;lack of feedback makes us falsely confident&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are fancy ways to connect build automation services and code analysis services to deployment services and code review services. If these options are available, if you can quickly troubleshoot interruptions, and if your whole team can access the results, then do this.  If not, here is a relatively independent alternative:&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;p&gt;Most software platforms have standalone tools for code analysis (test execution, test coverage, linting, docgen, etc.) that can generate standalone reports (probably HTML). If you get familiar with how to generate these, you can port them to future projects without relying on an external hosted service or special IDE features. Make a one-step script that generates all of these artifacts.&lt;/p&gt;

&lt;p&gt;Make another one-step script that does this: check out an &lt;a href="https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt---orphanltnewbranchgt"&gt;orphan branch&lt;/a&gt; from your code repository into a temporary folder. Remove existing files. Copy in the generated files from your previous script. Commit and push. Print a download link for the commit.&lt;/p&gt;

&lt;p&gt;Finally copy/paste the download link into your pull request description.  Your team can use this link to easily download and browse results.  One additional file I include is a root index.html with short descriptions and relative links for each report.  This helps everyone know why each report is there and gives a single entry point for everything in the download.&lt;/p&gt;

&lt;p&gt;For reference, I&amp;rsquo;ve set this up on one of my small, public Github projects.  You can see an example &lt;a href="https://github.com/toddway/Shelf/pull/6"&gt;pull request&lt;/a&gt; that includes a direct link to &lt;a href="https://github.com/toddway/Shelf/archive/07e990cb8840e83782d28f9135a25cf75e040ad3.zip"&gt;download reports&lt;/a&gt;.  You can also see the &lt;a href="https://github.com/toddway/Shelf/blob/multiplatform/shelf/push-artifacts.sh"&gt;shell script for pushing artifacts&lt;/a&gt; and the &lt;a href="https://github.com/toddway/Shelf/blob/multiplatform/shelf/push-artifacts-init.sh"&gt;shell script for initializing the branch with an index.html&lt;/a&gt;.  The goal for these scripts is to be relatively generic and portable so they can quickly be applied to future projects.  The same goal applies to scripts that generate report artifacts, but this is inherently more platform-dependent.  In this example, &lt;a href="https://github.com/toddway/Shelf/blob/multiplatform/shelf/checks.gradle"&gt;the script to generate artifacts is Gradle-based&lt;/a&gt; and the code analysis tools include JaCoCo, CPD, Detekt, BuildChecks, and JUnit.&lt;/p&gt;</description><link>https://toddway.com/post/615761714966872064</link><guid>https://toddway.com/post/615761714966872064</guid><pubDate>Sat, 18 Apr 2020 13:55:32 -0500</pubDate></item><item><title>Checklist yourself</title><description>&lt;p&gt;In 1935, Boeing introduced a heavy bomber that outperformed any other aircraft of it&amp;rsquo;s kind. It crashed tragically in exhibition because a routine step was missed by the well-trained and experienced flight crew.  As a result, pilots everywhere began to adopt preflight checklists and failures decreased significantly.&lt;/p&gt;

&lt;p&gt;Today, checklists for complex responsibilities are used in many professions. A surgeon named Adul Gawande wrote an entire book called &lt;a href="http://atulgawande.com/book/the-checklist-manifesto/"&gt;The Checklist Manifesto&lt;/a&gt;.   I think one reason the idea has spread so successfully is because a checklist is an incredibly easy tool to make and to use. 
&lt;!-- more --&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve written previously about how we do &lt;a href="http://toddway.com/post/175477173505/put-a-motor-on-your-code-cycle"&gt;continuous&lt;/a&gt; &lt;a href="http://toddway.com/post/165735557485/continuous-integration-for-firebase-cloud-code"&gt;integration&lt;/a&gt;, which is essentially an automated checklist verified by a machine. CI provides a level of safety, consistency, and efficiency that&amp;rsquo;s hard to match in any other way.  The problem is some details are prohibitively hard to automate and too important to ignore.  Our current solution for this is to manually review all code before it &amp;ldquo;takes flight&amp;rdquo;.  We use pull requests for this.  What we&amp;rsquo;ve been missing, tho, is a preflight checklist.&lt;/p&gt;

&lt;p&gt;Gawande sees ineptitude (not making use of what we already know) as a greater problem than ignorance (what we don&amp;rsquo;t know).  So our development group did a retrospective on code reviews.  We made a list of &lt;em&gt;what we already know&lt;/em&gt; we&amp;rsquo;re looking for when reviewing code.  The things we don&amp;rsquo;t want to forget about in the future.   Based on input from that discussion and this handy &lt;a href="http://www.projectcheck.org/uploads/1/0/9/0/1090835/checklist_for_checklists_final_10.3.pdf"&gt;checklist for creating checklists&lt;/a&gt;, I started one:&lt;/p&gt;

&lt;h2&gt;A checklist for reviewing code&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;Integration  
- [ ] Will merging this code create source conflicts?  
- [ ] Is there a clear and concise description of the changes?
- [ ] Did all automated checks (build, test, lint) run and pass?  
- [ ] Are there supporting metrics or reports (e.g. test coverage, fitness functions) that measure the impact?
- [ ] Are there obvious logic errors or incorrect behaviors that might break the software?

Readability
- [ ] Is the code self-documenting? Do we need secondary sources to understand it?  
- [ ] Do the names of folders, objects, functions, and variables intuitively represent their responsibilities?  
- [ ] Could comments be replaced by descriptive functions?  
- [ ] Is there an excessively long object, method, function, pull request, parameter list, or property list? Would decomposing make it better? .  

Anti-patterns
- [ ] Does the code introduce any of the following anti-patterns?
- [ ] Sequential coupling - a class that requires its methods to be called in order  
- [ ] Circular dependency - mutual dependencies between objects or software modules  
- [ ] Shotgun surgery - a change needs to be applied to multiple classes at the same time  
- [ ] Magic numbers - unexplained numbers in algorithms  
- [ ] Hard code - embedding assumptions about the environment in the implementation  
- [ ] Error hiding - catching an error and doing nothing or showing a meaningless message  
- [ ] Feature envy - a class that uses methods of another class excessively  
- [ ] Duplicate code - identical or very similar code exists in more than one location.  
- [ ] Boat anchor - retaining a part of a system that no longer has any use  
- [ ] Cyclomatic complexity - a function contains too many branches or loops 
- [ ] Famous volatility - a class or module that many others depend on and is likely to change 

Design principles
- [ ] Does the code align with the following principles?
- [ ] Single Responsibility - an object should have only one reason to change  
- [ ] Open/Closed - objects should be open for extension, closed for modification  
- [ ] Liskov Substitution - subtypes should not alter the correctness of code that depends on a supertype  
- [ ] Interface Segregation - many client specific interfaces are better than one general purpose interface  
- [ ] Dependency Inversion - dependencies should run in the direction of abstraction; high level policy should be immune to low level details

Last updated: 8/15/2018

Note: This is not a checklist for *approving* or *merging* code, it is a checklist for *reviewing* code.  It's a list of questions a reviewer should ask themselves as they review.
&lt;/code&gt;&lt;/pre&gt;</description><link>https://toddway.com/post/177036257990</link><guid>https://toddway.com/post/177036257990</guid><pubDate>Wed, 15 Aug 2018 16:46:27 -0500</pubDate><category>checklist</category></item><item><title>Put a motor on your code cycle</title><description>&lt;p&gt;There&amp;rsquo;s an old programmer joke:&lt;/p&gt;

&lt;p&gt;&amp;gt; Show me a line of code and I&amp;rsquo;ll tell you what&amp;rsquo;s wrong with it,
&amp;gt; Show me five hundred lines of code and I&amp;rsquo;ll say &amp;ldquo;looks ok to me&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Where I work, we use pair programming and pull requests in our development process.  No code is committed to the main branch without peer review.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m convinced the investment in extra eyes can pay off for a project of any size.  Human brains are uniquely capable of solving hard problems even when objectives are vaguely defined.  When we do this together it increases ownership, cohesion, velocity and resilience across the team.   This is magical.&lt;/p&gt;

&lt;p&gt;But even the collective brainpower of a long-lived, high-functioning team isn&amp;rsquo;t always reliable.  The complexities, pressures, and context-switching of a typical day can wear us down.  When we add the eye-glazing drudgery of a long pull request at 4pm in the afternoon, we&amp;rsquo;re in trouble.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s how we&amp;rsquo;re using automation to optimize our review process:&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;h2&gt;Build checks&lt;/h2&gt;

&lt;p&gt;Before anyone reviews source code, a machine should do it first.  It won&amp;rsquo;t catch everything a human could see, but it&amp;rsquo;s more consistent and much faster.  Source control systems (e.g. Github, Bitbucket) usually have an API so build results can be tracked for each code commit.  These are commonly called &amp;ldquo;status checks&amp;rdquo; or &amp;ldquo;build checks&amp;rdquo;.  As shown below, a green icon indicates a check posted from a build server was successful.&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="137" data-orig-width="856" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/passing-check.png"&gt;&lt;img src="https://64.media.tumblr.com/3af19c4b589c74f4825c2f263c8bd66e/tumblr_inline_pk09lmqzym1r4ik0y_540.png" data-orig-height="137" data-orig-width="856" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/passing-check.png"/&gt;&lt;/figure&gt;&lt;p&gt;Reviewers see a green or red icon immediately and can avoid wasting time reading code with known problems.  Even better, we can make these checks required for merging any code into our main code branch. Now the entire team, whether they review code or not, has confidence that the main branch is &lt;em&gt;always&lt;/em&gt; protected.&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="702" data-orig-width="894" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/protect-branch.png"&gt;&lt;img src="https://64.media.tumblr.com/743da068a6066528fc1f0fa7a7925fc6/tumblr_inline_pk09lnuJZB1r4ik0y_540.png" data-orig-height="702" data-orig-width="894" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/protect-branch.png"/&gt;&lt;/figure&gt;&lt;p&gt;We currently use 3 build checks: build, test, and lint. These can work for almost any project.&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="235" data-orig-width="472" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/build-checks.png"&gt;&lt;img src="https://64.media.tumblr.com/9e92e39acb0f9bf617fb103499168990/tumblr_inline_pk09loz9uw1r4ik0y_540.png" data-orig-height="235" data-orig-width="472" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/build-checks.png"/&gt;&lt;/figure&gt;&lt;p&gt;To process and post the checks, we use a Gradle plugin called &lt;a href="https://github.com/toddway/BuildChecks"&gt;BuildChecks&lt;/a&gt;.  We use Gradle because it&amp;rsquo;s free, fast, configurable, testable, well-supported, and portable.  From one project to the next, we don&amp;rsquo;t aways get to use the same development languages, source control system, or build servers, but we want to preserve key processes.  BuildChecks can work across multiple languages and source control systems.  It can run anywhere Java 7+ is installed.  In situations where we aren&amp;rsquo;t able to use a dedicated build server, it can be run from a developer&amp;rsquo;s workstation.  We can have the same automated integration protection even on shoestring budgets and timelines.&lt;/p&gt;

&lt;h2&gt;Build&lt;/h2&gt;

&lt;p&gt;The &amp;ldquo;build&amp;rdquo; check tells us if a build finished successfully and how long it took.  The process may be different for each project but is typically some variation of: compile source code, assemble artifacts, run tests, run lint, and deploy artifacts.  Having this feedback alone for a pull request review will save considerable time and effort.&lt;/p&gt;

&lt;h2&gt;Test&lt;/h2&gt;

&lt;p&gt;The &amp;ldquo;test&amp;rdquo; check show us the percentage of code that is covered by tests.  BuildChecks parses output from coverage tools like JaCoCo, Cobertura, Istanbul, Slather, and OpenCover. A minimum threshold for coverage can be set that will cause the check to fail.  This is optional.  Even without a threshold, the check clarifies that tests are running and if they&amp;rsquo;ve changed between commits.&lt;/p&gt;

&lt;h2&gt;Lint&lt;/h2&gt;

&lt;p&gt;The &amp;ldquo;lint&amp;rdquo; check tells us if the code violates any predefined standards.  BuildChecks parses output from linters like ESLint, TSLint, Detekt, Checkstyle, PMD, SwiftLint, and Android Lint.  Each linter has different rule sets that span categories like correctness, security, performance, accessibility, formatting style, internationalization, etc.  The lists can be overwhelming at first.  Many are language or platform-specific, but one category that has some pretty universal rules is maintainability.  If you don&amp;rsquo;t know where to start, this is a good place.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s list of maintainability rules from a multi-language code analysis platform called &lt;a href="https://docs.codeclimate.com/docs/maintainability"&gt;CodeClimate&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Argument count - Methods or functions defined with a high number of arguments&lt;/li&gt;
&lt;li&gt;Complex logic - Boolean logic that may be hard to understand&lt;/li&gt;
&lt;li&gt;Method complexity - Functions or methods that may be hard to understand&lt;/li&gt;
&lt;li&gt;File length - Excessive lines of code within a single file&lt;/li&gt;
&lt;li&gt;Method count - Classes defined with a high number of functions or methods&lt;/li&gt;
&lt;li&gt;Method length - Excessive lines of code within a single function or method&lt;/li&gt;
&lt;li&gt;Nested control flow - Deeply nested control structures like if or case&lt;/li&gt;
&lt;li&gt;Return statements - Functions or methods with a high number of return statements&lt;/li&gt;
&lt;li&gt;Similar blocks of code - Duplicate code which is not identical but shares the same structure&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Enable any of these that your lint tool supports.  Then use pull request conversations to discuss and identify additional patterns you want to add.  If the pattern isn&amp;rsquo;t already available, you can write your own custom rule.&lt;/p&gt;

&lt;h2&gt;Details&lt;/h2&gt;

&lt;figure class="tmblr-full" data-orig-height="235" data-orig-width="472" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/build-checks.png"&gt;&lt;img src="https://64.media.tumblr.com/9e92e39acb0f9bf617fb103499168990/tumblr_inline_pk09loz9uw1r4ik0y_540.png" data-orig-height="235" data-orig-width="472" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/build-checks.png"/&gt;&lt;/figure&gt;&lt;p&gt;In the image above, each check has a hyperlink labelled &amp;ldquo;Details&amp;rdquo;.  This links back to detail on the build server.  It&amp;rsquo;s a great way to give reviewers access to the full generated reports from lint and coverage tools as well as build logs and other artifacts.  The more context we can provide, the easier it will be for others to give real feedback.&lt;/p&gt;

&lt;h2&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;Automated checks help code reviews scale with consistency. Getting started is as easy as enabling the requirement in your source control system and using a tool like BuildChecks to report it.  If you&amp;rsquo;re not already, this puts you on a path to a several important development practices: automated builds, unit tests, frequent integration, maintainability standards, and protected branches.  Don&amp;rsquo;t worry if you start with low test coverage and high lint violations.  You will immediately have a better understanding of your current situation and a way track your progress.&lt;/p&gt;

&lt;p&gt;What automation tricks have you found for improving code review and integration?&lt;/p&gt;</description><link>https://toddway.com/post/175477173505</link><guid>https://toddway.com/post/175477173505</guid><pubDate>Mon, 02 Jul 2018 12:19:28 -0500</pubDate></item><item><title>Continuous integration for Firebase cloud code</title><description>&lt;p&gt;In a &lt;a href="http://toddway.com/post/165619029205/types-and-tests-for-firebase-cloud-code"&gt;previous post&lt;/a&gt; I showed how to add type-checking and unit tests to Firebase cloud code (cloud functions &lt;em&gt;and&lt;/em&gt; database rules).  Those tests are independent from any Firebase environment and independent from each other.   We should be able to run them all quickly and consistently in a clean Node.js environment with a single command.  We should also be able to chain that command with others so that we can build, test, and deploy each code commit directly into a live Firebase environment.&lt;/p&gt;

&lt;h4&gt;Here are the steps we want to automate:&lt;/h4&gt;

&lt;ol&gt;&lt;li&gt;Download project source&lt;/li&gt;
&lt;li&gt;Download project dependencies&lt;/li&gt;
&lt;li&gt;Compile project&lt;/li&gt;
&lt;li&gt;Run all tests&lt;/li&gt;
&lt;li&gt;Stop if any test fails, otherwise continue&lt;/li&gt;
&lt;li&gt;Deploy (cloud functions and database rules) to a Firebase environment&lt;/li&gt;
&lt;li&gt;Write a deployment summary to our Firebase environment (Git info, date, test results)&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll assume we have a machine with Node.js and Git installed.  This could be a developer machine or a dedicated continuous integration server (I try to make the execution identical for either if I can).  The first three steps are pretty straightforward from the command line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone git@github.com:whatever folder-name
npm install
tsc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that we have a compiled project environment, we can use Typescript/Javascript to handle the rest of our steps.  From the command line, node can execute a function from a local file like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;node -e 'require("./build.js").runAllTests()'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let&amp;rsquo;s implement a function to run all our tests:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export async function runAllTests() : Promise&amp;lt;TestResultsEntity&amp;gt; {
    const Mocha = require('mocha');
    const mocha = new Mocha();
    mocha.addFile('./test/tests.functions.js');
    mocha.addFile('./test/tests.database.js');
    const results = new TestResultsEntity();
    return await new Promise&amp;lt;TestResultsEntity&amp;gt;((resolve, reject) =&amp;gt; {
        mocha.run()
            .on('pass', (test) =&amp;gt; { results.passed++; })
            .on('fail', (test, err) =&amp;gt; { results.failed++; })
            .on('end',  () =&amp;gt; { resolve(results) });
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here I&amp;rsquo;m use the Mocha API to point to our test files, run them, and keep track of how many pass and fail.  Let&amp;rsquo;s write a deploy function that grabs the test results and handles our last three steps:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export async function deploy()  {
    const testResults = await runAllTests();
    const gitSummary = await getGitSummary();
    const summary = `${testResults.getSummary()} on ${getDateSummary()} from ${gitSummary}`;

    if (testResults.hasFailures()) {
        console.log('Deploy failed');
    } else {
        await asyncCommand(`firebase deploy --only functions,database`);
        await asyncCommand(`firebase database:set /lastDeploy -d '"${summary}"' -y`);
        console.log('Deploy succeeded');
    }

    console.log(summary);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the else clause above we run two &lt;a href="https://firebase.google.com/docs/cli/"&gt;Firebase CLI&lt;/a&gt; commands.  The first command deploys our code to the currently configured Firebase environment.  The second command writes a record to the database of that environment with a summary of our deployment.  This makes it easy for anyone on the team to see:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;what code is deployed,&lt;/li&gt;
&lt;li&gt;when it happened,&lt;/li&gt;
&lt;li&gt;and the results of the tests.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;To pull all of this together into a single command, we&amp;rsquo;ll use the package.json file to set up an npm script:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;"scripts": {
   "deploy": "npm install &amp;amp;&amp;amp; tsc &amp;amp;&amp;amp; node -e 'require(\"./build.js\").deploy()'"
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can run all steps with these two commands:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone git@github.com:whatever folder-name
npm run deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, here&amp;rsquo;s the ancillary code referenced by the deploy() and runAllTests() functions above:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export async function getGitSummary() : Promise&amp;lt;string&amp;gt; {
    const gitSha = await asyncCommand("git rev-parse --short HEAD");
    const gitBranch = await asyncCommand("git rev-parse --abbrev-ref HEAD");
    return Promise.resolve(`${gitSha.trim()}-${gitBranch.trim()}`);
}

function getDateSummary() : string {
    return new Date().toLocaleString("en-US", { timeZone: 'America/Chicago' }).trim();
}


const exec = require('child_process').exec;
function asyncCommand(command : string) : Promise&amp;lt;string&amp;gt; {
    return new Promise&amp;lt;string&amp;gt;((resolve, reject) =&amp;gt; {
        exec(command, function(error, stdout, stderr){ resolve(stdout); });
    })
}

export class TestResultsEntity {
    passed : number = 0;
    failed : number = 0;

    getSummary() : string {
        return `${this.passed}/${this.failed+this.passed} tests passed`
    }

    hasFailures() : boolean { return this.failed != 0 }
}
&lt;/code&gt;&lt;/pre&gt;</description><link>https://toddway.com/post/165735557485</link><guid>https://toddway.com/post/165735557485</guid><pubDate>Mon, 25 Sep 2017 15:28:42 -0500</pubDate><category>firebase</category><category>continuous integration</category><category>typescript</category><category>node</category></item><item><title>Types and tests for Firebase cloud code</title><description>&lt;p&gt;Firebase makes it cheap and easy to code custom functions and database access rules that run in the cloud along with their standard services.  This is great because you can try things out very quickly in a real, shared environment that performs at scale.  This simplicity make it tempting just to verify each change manually in the cloud environment.  I think static type-checking and independent unit tests are an even more appealing way to verify our code with confidence.  Here&amp;rsquo;s a recipe for eliminating dependencies on Firebase so we can run fast, automated tests before deploying code to the cloud.&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;h2&gt;Typescript + IDE&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/"&gt;Typescript&lt;/a&gt; is a superset of Javascript that compiles to plain Javascript.  It adds many useful language features like type annotations, interfaces, classes, and generics to Javascript.  All features are optional, so you can always ignore types and interop with plain Javascript when you want.&lt;/p&gt;

&lt;p&gt;Image we want have an app where we want to archive posts if they&amp;rsquo;ve been flagged too many times.  Let&amp;rsquo;s use a Typescript interface to decouple the Firebase dependency from as much of our code as we can.&lt;/p&gt;

&lt;p&gt;Say we have a PostEntity class like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class PostEntity {
    id : string;
    flags : number;
    maxFlags = 5;

    hasTooManyFlags() : boolean {
        return this.flags &amp;gt;= this.maxFlags
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;hellip;and a function that fetches a post by id, determines if it has too many flags, and archives it if so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function archiveIfTooManyFlags(postId : string, datasource : PostDatasource) : Promise&amp;lt;void&amp;gt; {
    return datasource.getPost(postId)
        .then(post =&amp;gt; {
            if (post.hasTooManyFlags())
                return datasource.archivePost(post.id);
            else
                return Promise.resolve();
        })
}

interface PostDatasource {
    getPost(postId : string) : Promise&amp;lt;postentity&amp;gt;
    archivePost(postId : string) : Promise&amp;lt;void&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that we defined a PostDatasource &lt;em&gt;interface&lt;/em&gt; with methods getPost and archivePost.  We can write an implementation of that interface that uses Firebase as our datasource or we could write an implementation that uses something completely different.  All of the code we&amp;rsquo;ve written so far is independent of that implementation.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s what that implementation might look like using Firebase:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class PostDatasourceFb implements PostDatasource {
    db = require('firebase-admin').database();

    getPost(postId: string) : Promise&amp;lt;postentity&amp;gt; {
        return this.db.ref(`/posts/${postId}`).once('value')
            .then(snap =&amp;gt; snap.val());
    }

    archivePost(postId: string): Promise&amp;lt;void&amp;gt; {
        return this.db.ref(`/posts/${postId}/isArchived`).set(true);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To execute this as a cloud function when a post is flagged in our Firebase Database we do this :&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;exports.onFlaged = functions.database.ref('/posts/{postId}/flags')
    .onWrite(event =&amp;gt; {
        return archiveIfTooManyFlags(
            event.params.postId, 
            new PostDatasourceFb()
        );
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In addition you can use a Typescript-aware IDE to make discovering the properties of your objects, language features and other javascript dependencies automatic as you write code.  If you&amp;rsquo;ve used any other OO language with a good IDE you&amp;rsquo;ll know what this means.  &lt;a href="https://www.jetbrains.com/webstorm/"&gt;WebStorm&lt;/a&gt; is my choice because I&amp;rsquo;m already familiar with the shortcuts and organization of JetBrains tools, but there are &lt;a href="https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support"&gt;many others&lt;/a&gt;.   They all support features like: instant type checking, code assist, inline refactoring, breakpoint debugging, object navigation, source control tracking, etc.&lt;/p&gt;

&lt;h2&gt;Mocha + Chai + Sinon&lt;/h2&gt;

&lt;p&gt;Now that we have the language tools to decouple our application code from dependencies, we can set up unit tests that run locally outside of the Firebase cloud environment.  Our test libraries are:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;a href="https://mochajs.org/"&gt;Mocha&lt;/a&gt; -  lets you describe and execute a set of unit tests.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://chaijs.com/"&gt;Chai&lt;/a&gt; - lets you make assertions within each of those tests.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sinonjs.org/"&gt;Sinon&lt;/a&gt; - lets you create spies, stubs, and mocks for your test dependencies.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Here&amp;rsquo;s what a test for our archiveIfTooManyFlags function might look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe('archiveIfTooManyFlags', () =&amp;gt; {
    it('should call archivePost when there are too many flags', async () =&amp;gt; {
        const sinon = require('sinon');
        const post = new PostEntity();
        post.flags = 7;
        const postDatasource = &amp;lt;postdatasource&amp;gt;{};
        postDatasource.getPost = sinon.stub().resolves(post);
        postDatasource.archivePost = sinon.stub().resolves(null);

        await archiveIfTooManyFlags("123", postDatasource);

        sinon.assert.calledWith(&amp;lt;sinonstub&amp;gt;postDatasource.archivePost, post.id);
        sinon.assert.calledWith(&amp;lt;sinonstub&amp;gt;postDatasource.getPost, "123");
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First we set up Sinon, and declare a PostDatasource and a PostEntity.  Since PostDatasource is an interface, we have to implement at least the methods we plan to use in our test.  We don&amp;rsquo;t want to use the PostDatasourceFb class from earlier, because it requires a Firebase environment.  We could write a second implementation from scratch that returns some mock values and keeps track of method calls, or we could let Sinon do most of that work for us.  Creating our PostDatasource as {} means it exists, but none of the methods have been implemented yet.  We use sinon.stub() to stub the behavior of the methods we plan to use: getPost and archivePost.  Finally we call archiveIfTooManyFlags and verify that getPost and archivePost were called with the expected arguments.&lt;/p&gt;

&lt;p&gt;Now we can run this test and others like it locally without connecting to Firebase.  This covers our cloud functions, but what about our database rules?&lt;/p&gt;

&lt;h2&gt;Targaryen&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/goldibex/targaryen"&gt;Targaryen&lt;/a&gt; lets us write the same kind of Mocha-based unit tests for our Firebase database rules.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a rule for reading &amp;amp; writing to a post:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  "rules": {
    ".read": "false",
    ".write": "false",
    "posts" :  {
      ".read": "true",
      "$post" : {
        ".read" : "true",
        ".write": "auth != null &amp;amp;&amp;amp; (data.child('userID').val() == auth.uid || root.child('users/' + auth.uid + '/isAdmin').val() == true)",
        "views":{
          ".write":"true"
        }
      }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Only admins and authors should be able to write to (edit) a post.  Targaryen lets us test this rule locally like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;describe('posts/aPostId', () =&amp;gt; {
    it(`can write if admin or author`, () =&amp;gt; {
        targaryen.setFirebaseData({
            users: {
                adminUser: {
                    isAdmin:true
                }
            },
            posts: {
                aPostId: {
                    userID:"authorUser"
                }
            }
        });

        expect({uid: 'adminUser'}).can.write.path('posts/aPostId');
        expect({uid: 'authorUser'}).can.write.path('posts/aPostId');
        expect({uid: 'randomUser'}).cannot.write.path('posts/aPostId');
        expect(null).cannot.write.path('posts/aPostId');
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can cover all our cloud functions and all our database rules with fast, automated tests! Wouldn&amp;rsquo;t it be great if we had a single command that could confirm all our tests are passing, then deploy the code and results to our Firebase environment? I&amp;rsquo;ll write up my solution to this in a future post. &lt;/p&gt;</description><link>https://toddway.com/post/165619029205</link><guid>https://toddway.com/post/165619029205</guid><pubDate>Fri, 22 Sep 2017 10:13:24 -0500</pubDate><category>firebase</category><category>typescript</category><category>nodejs</category></item><item><title>API Acceptance Tests with Cucumber and Rest-assured</title><description>&lt;p&gt;On projects where multiple systems undergo development at the same time, it&amp;rsquo;s crucial to maintain a clear picture of how they should interact.  We commonly have a backend system providing a REST API to multiple frontends (browsers, mobile apps, chatbots, IoT, etc.).  Because it will likely change over time, keeping the API picture clear and up to date can be a significant challenge.  How can we efficiently describe the currently expected behavior and know if it&amp;rsquo;s working as expected so teams don&amp;rsquo;t spin their wheels due to miscommunication?&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;h2&gt;Cucumber&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://cucumber.io"&gt;Cucumber&lt;/a&gt; helps us write readable requirements upfront that can be tied directly to executable tests.  Here&amp;rsquo;s an example for a guestbook REST API:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Scenario: Read a list of guestbook entries

  Given I'm using the staging API environment
  And the guestbook has at least "2" entries
  When I make a GET request to "/guestbook/entries"
  Then I get a response code of "200"
  And I get a response with at least "2" entries
  And each entry has a "name"
  And each entry has a "date" formatted as a Unix timestamp
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each line in the scenario above represents a discrete Cucumber step.  A developer can now write a short block of code to fulfill each step.&lt;/p&gt;

&lt;p&gt;There are options in various languages for fulfilling Cucumber step definitions (e.g. Ruby, Javascript, Python, .NET, Java).  I chose the Java implementation, &lt;a href="https://github.com/cucumber/cucumber-jvm"&gt;Cucumber-JVM&lt;/a&gt;, for these reasons:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Works with many out-of-the-box &lt;strong&gt;reporting and automation tools&lt;/strong&gt; - because it&amp;rsquo;s JUnit-based&lt;/li&gt;
&lt;li&gt;Intuitive &lt;strong&gt;IDE support&lt;/strong&gt; for code assist, breakpoints, debugging, output formatting, etc. (Intellij and Eclipse)&lt;/li&gt;
&lt;li&gt;Easy-to-build &lt;strong&gt;HTTP request and response assertions&lt;/strong&gt; using the &lt;a href="http://rest-assured.io/"&gt;Rest-assured&lt;/a&gt; library&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Cucumber on Java&lt;/h2&gt;

&lt;p&gt;Using Cucumber-JVM and the Intellij IDE, I get automatically generated step definitions like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public GuestbookStepDefinitions() {
    Given("^I'm using the staging API environment$", () -&amp;amp;gt; {
        //short block of code goes here
    });

    When("^I make a GET request to \"([^\"]*)\"$", (String path) -&amp;amp;gt; {
        //another block here
    });

    Then("^I get a response code of \"([^\"]*)\"$", (Integer code) -&amp;amp;gt; {
        //and another
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next we fill in the implementations using Rest-assured&amp;hellip;&lt;/p&gt;

&lt;h2&gt;Rest-assured&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;public GuestbookStepDefinitions() {

    private RequestSpecification request;
    private ValidatableResponse response;

    @Before
    public void before(Scenario scenario) {
        request = RestAssured.with();
    }

    Given("^I'm using the staging API environment$", () -&amp;amp;gt; {
        request.given()
            .contentType(ContentType.JSON)
            .baseUri("https://staging.mycompany.com");
    });

    When("^I make a GET request to \"([^\"]*)\"$", (String path) -&amp;amp;gt; {
        response = request.get(path + ".json").then();
    });

    Then("^I get a response code of \"([^\"]*)\"$", (Integer code) -&amp;amp;gt; {
        response.statusCode(code);
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;Given&lt;/code&gt; and &lt;code&gt;When&lt;/code&gt; steps are building a request with details for our REST API.  The &lt;code&gt;Then&lt;/code&gt; step calls &lt;code&gt;response.statusCode(...)&lt;/code&gt; which is an assertion of the status code returned by the REST API.  If any step fails we get targeted feedback like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;java.lang.AssertionError: 1 expectation failed.
Expected status code  but was .


...
io.restassured.internal.ValidatableResponseOptionsImpl.statusCode(ValidatableResponseOptionsImpl.java:117)
    at GuestbookStepDefinitions.lambda$new$8(GuestbookStepDefinitions.java:66)
    at &amp;amp;#10045;.Then I get a response code of "100"(guestbook-entries-read.feature:12)

Failed scenarios:
guestbook-entries-read.feature:9 # Scenario: Read a list of guestbook entries

1 Scenarios (1 failed)
3 Steps (1 failed, 2 passed)
0m1.370s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This output is a bit verbose (we&amp;rsquo;ll worry about report formatting later), but contains important information about the failure.&lt;/p&gt;

&lt;p&gt;The step: we see that the &amp;ldquo;Then I get a response code of 100&amp;rdquo; step of our &amp;ldquo;Read a list of guestbook entries&amp;rdquo; scenario is where we&amp;rsquo;re failing.  That means the previous two steps passed successfully.&lt;/p&gt;

&lt;p&gt;The expectation:  we see that we got a  response code but expected a  response code.  If we change the expected status code back to 200, we should get a passing test:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Scenario: Read all guestbook entries          # guestbook-entries-read.feature:9
  Given I'm using the staging API environment # GuestbookStepDefinitions.java:89
  When I make a GET request to "/guestbook"   # GuestbookStepDefinitions.java:59
  Then I get a response code of "200"         # GuestbookStepDefinitions.java:65

1 Scenarios (1 passed)
3 Steps (3 passed)
0m1.937s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since we&amp;rsquo;re making HTTP calls it&amp;rsquo;d be nice to see the request and response details too.  We can tell Rest-assured to print those along with our test results:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Request method: GET
Request URI:    &lt;a href="https://staging.mycompany.com/guestbook/entries.json"&gt;https://staging.mycompany.com/guestbook/entries.json&lt;/a&gt;
Proxy:          &amp;lt;none&amp;gt;
Request params: &amp;lt;none&amp;gt;
Query params:   &amp;lt;none&amp;gt;
Form params:    &amp;lt;none&amp;gt;
Path params:    &amp;lt;none&amp;gt;
Multiparts:     &amp;lt;none&amp;gt;
Headers:        Accept=*/*
                Content-Type=application/json; charset=UTF-8
Cookies:        &amp;lt;none&amp;gt;
Body:           &amp;lt;none&amp;gt;
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 10 Apr 2017 19:09:16 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 4830
Connection: keep-alive
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Strict-Transport-Security: max-age=31556926; includeSubDomains; preload
{
    "-KgBbHUcv2NWn2M6tzGp": {
        "comment": "Hello Guestbook",
        "name": "Test User",
        "timestamp": 1490565277672
    },
    "-KgBbzZE2WtRD9wz1t-D": {
        "comment": "Hello Guestbook",
        "name": "Test User",
        "timestamp": 1490565462287
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Reporting&lt;/h2&gt;

&lt;p&gt;Now when we run this test we immediately know three things:
1. &lt;strong&gt;What we expect to happen&lt;/strong&gt; (the Given-When-Then statement)
2. &lt;strong&gt;How to make it happen&lt;/strong&gt; (the printed request and response)
3. &lt;strong&gt;Is it currently working as expected&lt;/strong&gt; (Pass or Fail)&lt;/p&gt;

&lt;p&gt;Having this feedback continuously throughout development mitigates communication issues early before teams waste time heading in different directions.  The easy-to-read Cucumber steps that everyone can read tie directly to the gritty HTTP definitions that developers need and we can drop it on a CI server to generate formatted reports visible to the whole team.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s an example of formatted results from the Intellij IDE:&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="728" data-orig-width="1188" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/ide-cucumber-output.png"&gt;&lt;img src="https://64.media.tumblr.com/2b9505cb00c137a2246a8f353a981c3d/tumblr_inline_pjzq05TyS81r4ik0y_540.png" width="600px" data-orig-height="728" data-orig-width="1188" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/ide-cucumber-output.png"/&gt;&lt;/figure&gt;&lt;p&gt;On the left we have a collapsible, colored outline of our features, scenarios, and steps.  We can select anything in the tree and see corresponding details on the right.&lt;/p&gt;

&lt;p&gt;And here&amp;rsquo;s a standalone HTML report:&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="1410" data-orig-width="1896" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/web-cucumber-output.png"&gt;&lt;img src="https://64.media.tumblr.com/116c8b133d374021376065b667d1341d/tumblr_inline_pjzq06uSaT1r4ik0y_540.png" width="600px" data-orig-height="1410" data-orig-width="1896" data-orig-src="https://sandbox-9221c.firebaseapp.com/blog/web-cucumber-output.png"/&gt;&lt;/figure&gt;&lt;p&gt;Again we have a collapsible, colored outline that documents the expected behavior and HTTP details.&lt;/p&gt;

&lt;h2&gt;Process&lt;/h2&gt;

&lt;p&gt;This approach is designed drive collaboration early in the process so it&amp;rsquo;s a great chance to work in pairs.  Pairing a frontend developer and a backend developer can help start the conversation about how systems should interact.  Getting other roles like analysts, designers, and testers involved can level-set everyone&amp;rsquo;s understanding of how the product is supposed to work.   As soon as we have requirements for our first feature, we can start writing tests.  The code required to fulfill step definitions should be easy enough for any developer to pick up quickly regardless of language choice.  I prefer to put API acceptance tests in a separate repository apart from any other production code.   This limits external dependencies from affecting our ability to write and run the tests.&lt;/p&gt;</description><link>https://toddway.com/post/159457015220</link><guid>https://toddway.com/post/159457015220</guid><pubDate>Tue, 11 Apr 2017 11:40:58 -0500</pubDate><category>acceptance-tests</category><category>api</category><category>bdd</category></item><item><title>Serverless apps with Firebase</title><description>&lt;p&gt;&lt;a href="http://firebase.google.com"&gt;Firebase&lt;/a&gt; is a set of backend platform services (owned by Google and closely integrated with the Google Cloud Platform) for building web and mobile apps.  They have SDKs for Android, iOS, web, C++, Unity, Node.js, and Java.  Their generous free tier makes it easy to launch fully functional apps to a modest user base without cost.&lt;/p&gt;

&lt;p&gt;Free and unlimited features include: 
Authentication, Analytics, App Indexing, Cloud Messaging, Crash Reporting, Dynamic Links, Notifications, Remote Config&lt;/p&gt;

&lt;p&gt;Free features with usage limits: 
Realtime Database, Cloud Functions, Hosting, Storage, Test Lab&lt;/p&gt;

&lt;p&gt;There is way too much to cover here.  If you want all the details, their &lt;a href="https://firebase.google.com/docs/database/"&gt;website docs&lt;/a&gt; are some of the best I&amp;rsquo;ve encountered.  You can also demo many features right from the &lt;a href="https://console.firebase.google.com/"&gt;web console&lt;/a&gt;.  Here are a few of the highlights that I think can considerably reduce effort and improve quality for app development.&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;h2&gt;Sign in/up simply&lt;/h2&gt;

&lt;p&gt;Firebase Authentication provides email, social, anonymous, and custom sign in methods out of the box.  Accounts can be managed and each method enabled or disabled from the Firebase web console.   Access tokens are based on the JWT feature of OpenID Connect which encrypts portable authorization data in each token.  This means multi-system architectures can share tokens and without the expense of server-to-server callbacks on client requests.&lt;/p&gt;

&lt;h2&gt;Realtime apps are no longer a luxury&lt;/h2&gt;

&lt;p&gt;The Realtime Database is a NoSQL cloud database with REST and SDK (websocket) support.  Data is synced across all clients in realtime, and remains available even when offline.   Network calls, cache updates, device resources, and intermittent connectivity are managed automatically by the SDK.  Clients simply listen for data changes and react with UI updates.&lt;/p&gt;

&lt;h2&gt;Free backend - if needed&lt;/h2&gt;

&lt;p&gt;For the most part Firebase requires no server-side code, but if you want something to be handled in a trusted backend environment (e.g. push notification logic), there are two relatively simple and free-tier options: Cloud Functions and App Engine.  Cloud Functions is a hosted, private, and scalable Node.js environment where you can run JavaScript code and interact with Firebase.   App Engine is a hosted, private, and scalable environment that supports Java, Python, PHP, and Go.  If you&amp;rsquo;re building an Android app, App Engine is a convenient option because your Java code and IDE tools can be shared between the two.&lt;/p&gt;

&lt;h2&gt;Deep links that survive installs&lt;/h2&gt;

&lt;p&gt;A Dynamic Link is a deep link that can survive the optional app installation step (on Android and iOS) or fall back to a web link if the user is on a desktop machine.  Firebase will generate short links that contain all the details required.  This works great for letting users invite their friends to an app or tracking referral codes.&lt;/p&gt;

&lt;h2&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;Serverless isn&amp;rsquo;t the right approach for every situation, but the potential for reduced effort, early feedback, and tighter operational management is compelling - especially in the early life stages of an app.  Firebase is one of the most complete Backend-as-a-Service platforms, but the field is still fairly new.  The competition will evolve and so will your app.  Design principles like &lt;a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle"&gt;dependency inversion&lt;/a&gt; can help minimize these future risks.&lt;/p&gt;

&lt;h2&gt;Further Reading&lt;/h2&gt;

&lt;ul&gt;&lt;li&gt;&lt;a href="https://scotch.io/bar-talk/a-look-at-the-new-firebase-a-powerful-google-platform"&gt;https://scotch.io/bar-talk/a-look-at-the-new-firebase-a-powerful-google-platform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://firebase.google.com/docs/"&gt;https://firebase.google.com/docs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/articles/serverless.html"&gt;https://martinfowler.com/articles/serverless.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><link>https://toddway.com/post/158363350435</link><guid>https://toddway.com/post/158363350435</guid><pubDate>Mon, 13 Mar 2017 14:53:05 -0500</pubDate></item><item><title>Reuse Android code without remote dependencies</title><description>&lt;p&gt;You&amp;rsquo;re starting to write similar code project after project and think it would be useful to establish some base components that can be reused across multiple projects.  First you create a library module to isolate your code.  Then you need to figure out how you&amp;rsquo;re going to include it in each project.&lt;/p&gt;

&lt;p&gt;If it&amp;rsquo;s open source, hosting it in a public maven repository like JCenter/Maven Central is a good solution.  If the code can&amp;rsquo;t be shared publicly, the simplest way I&amp;rsquo;ve found is this:&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;h2&gt;Step 1&lt;/h2&gt;

&lt;p&gt;Copy the packaged library file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;MyReusableLibrary/build/outputs/aar/MyReusableLibrary-release.aar
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and paste it into the &lt;code&gt;app/libs&lt;/code&gt; directory of each project you want to use it in.&lt;/p&gt;

&lt;h2&gt;Step 2&lt;/h2&gt;

&lt;p&gt;Add the following to the &lt;code&gt;app/build.gradle&lt;/code&gt; of each project&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;repositories {
    ...
    flatDir {
        dirs 'libs'
    }
}

dependencies {
    ...
    compile ':MyReusableLibrary-release.aar
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;What I like about it&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s self-contained for library consumers.  If a developer tries to download and build a project that uses this library, there are no additional commands to run and no extra credentials to track down.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s low maintenance for library providers.  You can host the aar files directly in your source repository or wherever else makes sense.  You don&amp;rsquo;t need to worry about maintaining a private maven server.&lt;/p&gt;

&lt;h2&gt;What I don&amp;rsquo;t like about it&lt;/h2&gt;

&lt;p&gt;It doesn&amp;rsquo;t include transitive dependencies automatically.  Since there is no associated pom file, you need to describe them along with your library.  If the example library above depended on the Android Support Library, the project dependencies would need to include both:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dependencies {
    ...
    compile ':MyReusableLibrary-release.aar
    compile 'com.android.support:appcompat-v7:24.2.0'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Additional tips&lt;/h2&gt;

&lt;p&gt;Add the following to the &lt;code&gt;build.gradle&lt;/code&gt; of your library module to store versioned aar files:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;android {
    defaultConfig {
        versionName "1.0"
    }
    buildTypes {
        release {
            archivesBaseName = "${project.name}-${android.defaultConfig.versionName}"
        }
    }
}

task copyAar(type: Copy) {
    from('build/outputs/aar')
    into('../app/libs')
    include(archivesBaseName + '-release.aar')
}
copyAar.dependsOn assemble
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Running &lt;code&gt;./gradlew copyAar&lt;/code&gt; assembles the file &lt;code&gt;MyResuableLibrary-1.0-release.aar&lt;/code&gt; and copies it to the libs folder.&lt;/p&gt;

&lt;p&gt;Have a sample app module in your library project so you can test your library before using it in other projects.  See the &lt;a href="https://github.com/square/picasso"&gt;Picasso library&lt;/a&gt; from Square (or many of the other Android library projecst on Github) as an example.  The /picasso directory is the library and /picasso-sample directory is the sample app.  You can also use this sample app module to test the flatDir dependency approach described above.&lt;/p&gt;</description><link>https://toddway.com/post/153051723150</link><guid>https://toddway.com/post/153051723150</guid><pubDate>Fri, 11 Nov 2016 15:04:32 -0600</pubDate><category>android</category><category>gradle</category><category>aar</category></item><item><title>Observable cache policies with Shelf</title><description>&lt;p&gt;Mobile apps often depend on network data that needs to be stored locally, restructured, and periodically refreshed.  You&amp;rsquo;ll find plenty of implementation options for http calls, serialization, disk storage, encryption, etc.  You&amp;rsquo;ll also find plenty of changing requirements that make you want to replace the choices you made a month ago.&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Wouldn&amp;rsquo;t it be nice to minimize the dependencies your application code has on these persistence details?&lt;/li&gt;
&lt;li&gt;Wouldn&amp;rsquo;t it be extra nice to defer complex and highly optimized implementations you may never need?&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve applied these ideas to a storage library I wrote called &lt;a href="https://github.com/toddway/Shelf"&gt;Shelf&lt;/a&gt;.  Shelf aims to be a simple but extendable interface for local storage in Java.  Out of the box it uses &lt;a href="https://github.com/google/gson"&gt;Gson&lt;/a&gt; for serialization, flat files for storage, and &lt;a href="https://github.com/ReactiveX/RxJava"&gt;RxJava&lt;/a&gt; for observable cache policies.  Rx is great for asynchronous data operations.  It helps separate &lt;em&gt;what you want to do with data from how and when it becomes available&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Over and over I found myself writing code to do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Get cached data if available, 
then get new data if the cache is too old.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I also frequently repeated this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Get cached data if available and not too old, 
else get new data.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Shelf wraps these policies (and others) into Rx Observables and Transformers:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;cacheThenNew&lt;/li&gt;
&lt;li&gt;cacheOrNew&lt;/li&gt;
&lt;li&gt;newOnly&lt;/li&gt;
&lt;li&gt;pollNew&lt;/li&gt;
&lt;li&gt;cacheThenPollNew&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;A simple example&lt;/h2&gt;

&lt;p&gt;To demonstrate, here&amp;rsquo;s a contrived example of printed strings.  We start with a cached string value that&amp;rsquo;s &lt;em&gt;good&lt;/em&gt; for 1 millisecond and an observable to fetch a new value (imagine the new value call is slow, e.g. relies on the network):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;shelf.defaultLifetime(1, MILLISECOND);
shelf.item("myString").put("cached value");
Observable&amp;lt;String&amp;gt; myObservable = Observable.fromCallable(() -&amp;gt; return "new value");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we use the &lt;em&gt;cacheThenNew&lt;/em&gt; policy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;//Prints "cached value" then prints "new value".
myObservable
    .compose(shelf.item("myString").cacheThenNew(String.class))
    .subscribe(s -&amp;gt; System.out.println(s));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using the &lt;em&gt;cacheOrNew&lt;/em&gt; policy looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;//Prints "new value" if the cache is older than 1 millisecond, 
//otherwise it prints "cached value".
myObservable
    .compose(shelf.item("myString").cacheOrNew(String.class))
    .subscribe(s -&amp;gt; System.out.println(s));  
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Network data example&lt;/h2&gt;

&lt;p&gt;Imagine we want to display a list of blog articles.  We have an basic Article object like this,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Article {
    String title;
    String url;
    String category;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And a &lt;a href="http://square.github.io/retrofit/"&gt;Retrofit&lt;/a&gt; service to fetch a list of articles from the web,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public interface ArticleService {
    @GET("/articles")
    Observable&amp;lt;Article[]&amp;gt; getArticles();
}

ArticleService service = retrofit.create(ArticleService.class);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And a view interface to display the articles once they&amp;rsquo;re available,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public interface ArticlesView {
    void displayArticles(Article[] articles);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now all we need to populate the view with articles is this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;service
    .getArticles()
    .compose(shelf.item("articles").cacheThenNew(Article[].class))
    .subscribe(articles -&amp;gt; view.displayArticles(articles));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Whether we have old cache, new cache, or no cache, Shelf has built-in policies that will react appropriately, update the cache, and emit results to the view.  Best of all our view, cache, and network implementations are independent.  RxJava makes it easy to replace any part of the equation in isolation.&lt;/p&gt;

&lt;p&gt;Finally, let&amp;rsquo;s imagine that our articles service actually returns thousands of articles from dozens of categories and we only want the ones about baseball.  Assuming we have a &lt;code&gt;filterBy(category)&lt;/code&gt; function like this,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public Func1&amp;lt;Article[], Article[]&amp;gt; filterBy(final String category) {
    return (articles) -&amp;gt;
         List&amp;lt;String&amp;gt; filteredArticles = new ArrayList&amp;lt;&amp;gt;();
         for (int i = 0; i &amp;lt; articles.length; i++) {
             if (articles[i].category.equals(category)) {
                 filteredArticles.add(articles[i]);
             }
         }
         return (String[]) filteredArticles.toArray();
    };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then our chain from above would look like this,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;service
    .getArticles()
    .map(filterBy("baseball"))
    .compose(shelf.item("articles").cacheThenNew(Article[].class))
    .subscribe(articles -&amp;gt; view.displayArticles(articles));
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;Additional info&lt;/h4&gt;

&lt;p&gt;If you&amp;rsquo;re interested in using the caching policies described above, but don&amp;rsquo;t want to use Shelf, take a look at the &lt;code&gt;RxCacheable&lt;/code&gt; class in the Shelf library.  It should work for most caching implementations and only depends on RxJava.&lt;/p&gt;

&lt;p&gt;If you want to learn the basics of RxJava, specifically for Android, Dan Lew has some &lt;a href="http://blog.danlew.net/tag/rxjava/"&gt;great posts&lt;/a&gt;.  In one particular article he talks about using it to manage data from multiple sources (memory, disk, and network) which was the inspiration for Shelf&amp;rsquo;s cache policies.&lt;/p&gt;</description><link>https://toddway.com/post/142852279395</link><guid>https://toddway.com/post/142852279395</guid><pubDate>Fri, 15 Apr 2016 12:19:20 -0500</pubDate><category>android</category><category>rxjava</category></item><item><title>3 ways to reach Android users beyond your app</title><description>&lt;p&gt;If you have an app in the Google Play store and are looking for better ways to connect with users, there are some powerful Android utilities you should know about.  Users don&amp;rsquo;t need to have your app open or even installed to reap the benefits.  Here are 3 tools for reaching Android users beyond your app.&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;h2&gt;Deep links from Google search results&lt;/h2&gt;

&lt;p&gt;By implementing &lt;a href="https://developers.google.com/app-indexing/webmasters/"&gt;Google&amp;rsquo;s App Indexing API&lt;/a&gt;, users will see Google search results and autocomplete suggestions that take them directly to specific sections in your app.  Even when the app isn&amp;rsquo;t installed, users will see results in relevant searches and can walk through a few steps to install and land in your app.&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="700" data-orig-width="497" data-orig-src="http://1.bp.blogspot.com/-df1m_CWPToA/VS_lnw2IF-I/AAAAAAAAAz4/diTZCpVY1AI/s1600/App%2Binstalls%2Bthrough%2Bapp%2Bindexing.gif"&gt;&lt;img src="https://64.media.tumblr.com/5fe2cff93258663d466d120745aa19df/tumblr_inline_psdchlrAjD1r4ik0y_540.gif" width="300" style="width:300px" alt="App installs through indexing" data-orig-height="700" data-orig-width="497" data-orig-src="http://1.bp.blogspot.com/-df1m_CWPToA/VS_lnw2IF-I/AAAAAAAAAz4/diTZCpVY1AI/s1600/App%2Binstalls%2Bthrough%2Bapp%2Bindexing.gif"/&gt;&lt;/figure&gt;&lt;p&gt;Just as URLs are used to index pages of your website, &lt;em&gt;deep links&lt;/em&gt; must be defined to index the sections of your app.  Although not required, deep links should align with &lt;a href="https://developers.google.com/app-indexing/webmasters/server"&gt;corresponding webpages&lt;/a&gt; when they exist.  This will streamline traffic flows across web and app experiences.  For example, when an Android user selects your content link a search result (or marketing email, or device notification) the system can decide whether the link should direct them into the installed app or fallback to the website.&lt;/p&gt;

&lt;h2&gt;App installs without leaving your website&lt;/h2&gt;

&lt;p&gt;If you offer &amp;ldquo;Sign in with Google&amp;rdquo; on your website, users can not only skip a lengthy registration process, they&amp;rsquo;ll have the option to install your Android app on their device instantly without leaving your website.  This can significantly reduce barriers to user activation.  Google reports that developers see a &lt;a href="http://techcrunch.com/2013/05/14/google-40-of-android-users-accept-google-sign-ins-over-the-air-install-prompts/"&gt;40% acceptance rate from the app install prompt&lt;/a&gt;.  Here&amp;rsquo;s what the process looks like:&lt;/p&gt;

&lt;h4&gt;1. Website Sign in&lt;/h4&gt;

&lt;figure class="tmblr-full" data-orig-height="1142" data-orig-width="1314" data-orig-src="https://google-developers.appspot.com/+/features/images/features-ota-fitbit-03.jpg"&gt;&lt;img width="300" src="https://64.media.tumblr.com/f3bbe7cfb75c5db4a4ace34f1cb5c01f/tumblr_inline_psdchnRQSU1r4ik0y_540.jpg" data-orig-height="1142" data-orig-width="1314" data-orig-src="https://google-developers.appspot.com/+/features/images/features-ota-fitbit-03.jpg"/&gt;&lt;/figure&gt;&lt;h4&gt;2. Choose devices&lt;/h4&gt;

&lt;figure class="tmblr-full" data-orig-height="1142" data-orig-width="1314" data-orig-src="https://google-developers.appspot.com/+/features/images/features-ota-fitbit-04.jpg"&gt;&lt;img width="300" src="https://64.media.tumblr.com/617488fd8ad356ab8e286713c1518ea5/tumblr_inline_psdchoZVTf1r4ik0y_540.jpg" data-orig-height="1142" data-orig-width="1314" data-orig-src="https://google-developers.appspot.com/+/features/images/features-ota-fitbit-04.jpg"/&gt;&lt;/figure&gt;&lt;h4&gt;3. App installed&lt;/h4&gt;

&lt;figure class="tmblr-full" data-orig-height="1142" data-orig-width="1314" data-orig-src="https://google-developers.appspot.com/+/features/images/features-ota-fitbit-05.jpg"&gt;&lt;img width="300" src="https://64.media.tumblr.com/7e25f1b31dbe6a6d0627444e3935a601/tumblr_inline_psdchphDQf1r4ik0y_540.jpg" data-orig-height="1142" data-orig-width="1314" data-orig-src="https://google-developers.appspot.com/+/features/images/features-ota-fitbit-05.jpg"/&gt;&lt;/figure&gt;&lt;p&gt;Note: this install prompt appears only if: 1) The user signs in with a Google+ account tied to an Android device. 2) The app is in the Google Play store. 3) The app is free. 4) The app has a minimum of 10 ratings, with a minimum rating of three stars.&lt;/p&gt;

&lt;h2&gt;Interactive notifications&lt;/h2&gt;

&lt;p&gt;Android provides some special notification features that don&amp;rsquo;t exist yet for iOS.  This includes embedding images, controlling media playback, expandable details, continuous display updates, categorization, prioritization and more.  Apps can leverage these features to create quick and easy user interactions without ever launching an app.  Here are a few examples.&lt;/p&gt;

&lt;p&gt;Expandable notifications allow a user to see more detail and perform convenient actions without leaving the the notification list.&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="533" data-orig-width="620" data-orig-src="http://core0.staticworld.net/images/article/2014/11/05-android-50-lock-screen-100530533-large.idge.jpg"&gt;&lt;img width="400" src="https://64.media.tumblr.com/01b571aad85ac412a4f649cf45e53a74/tumblr_inline_psdchqtMRN1r4ik0y_540.jpg" data-orig-height="533" data-orig-width="620" data-orig-src="http://core0.staticworld.net/images/article/2014/11/05-android-50-lock-screen-100530533-large.idge.jpg"/&gt;&lt;/figure&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;The Big Picture style is a special type of expandable notification that can contain images.&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="604" data-orig-width="800" data-orig-src="http://www.androidcentral.com/sites/androidcentral.com/files/styles/large_wm_brw/public/article_images/2015/03/htc-one-m9-screenshot-notification.jpg?itok=VWRTR2bc"&gt;&lt;img width="400" src="https://64.media.tumblr.com/71abd28b7659af339f1ff576aad0e4c1/tumblr_inline_psdchqCAee1r4ik0y_540.jpg" data-orig-height="604" data-orig-width="800" data-orig-src="http://www.androidcentral.com/sites/androidcentral.com/files/styles/large_wm_brw/public/article_images/2015/03/htc-one-m9-screenshot-notification.jpg?itok=VWRTR2bc"/&gt;&lt;/figure&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;Notification display updates allow an app to provide immediate feedback in the notification when something changes.  In the example below the &amp;ldquo;Check-in&amp;rdquo; button changes to a disabled &amp;ldquo;Checked-in&amp;rdquo; button when selected by the user.&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="793" data-orig-width="900" data-orig-src="http://drive.google.com/uc?export=view&amp;amp;id=0ByKzOmVNsVO1cVoxT3Y4RktvU3c"&gt;&lt;img width="400" src="https://64.media.tumblr.com/df3ffffe52f305aca357a6fdda9e42ad/tumblr_inline_psdchswjIa1r4ik0y_540.png" data-orig-height="793" data-orig-width="900" data-orig-src="http://drive.google.com/uc?export=view&amp;amp;id=0ByKzOmVNsVO1cVoxT3Y4RktvU3c"/&gt;&lt;/figure&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;h2&gt;Honorable mention - Google Now integration&lt;/h2&gt;

&lt;p&gt;This one doesn&amp;rsquo;t technically have anything to do with &lt;em&gt;your&lt;/em&gt; app and isn&amp;rsquo;t exclusive to Android, but since many Android users interact with Google Now on a daily basis I&amp;rsquo;m giving it an honorable mention.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.androidcentral.com/google-now-gets-integration-70-more-third-party-apps"&gt;Full third-party integration is being slowly rolled out&lt;/a&gt; which will ultimately allow things like custom Now Cards and voice activated deep links into your app. Until then you can get limited integration for your products and services by &lt;a href="https://developers.google.com/schemas/now/cards"&gt;adding markup to your user email notifications&lt;/a&gt;.  Users who connect Google Now to their Gmail account will see Now Cards for the email notifications you send to users.&lt;/p&gt;

&lt;h2&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;The tools above will help extend the reach and discoverability of your products and services on the Android platform.  The features they enable are already familiar to users.  They&amp;rsquo;re expecting them and will welcome the enhancements and conveniences they provide.&lt;/p&gt;</description><link>https://toddway.com/post/120641206880</link><guid>https://toddway.com/post/120641206880</guid><pubDate>Wed, 03 Jun 2015 16:49:52 -0500</pubDate><category>android</category></item><item><title>Android Material Transitions</title><description>&lt;p&gt;&lt;a href="https://github.com/toddway/MaterialTransitions"&gt;This Android project&lt;/a&gt; samples some Material Design-ish transitions for list items and floating action buttons.  It uses the
&lt;a href="https://developer.android.com/training/material/animations.html"&gt;the shared element concept introduced in Android 5.0&lt;/a&gt;.  I tried to pull it off with pure fragment transitions and ran into a few stags (see below)
so my current solution uses an activity transition for each step.&lt;/p&gt;

&lt;figure data-orig-height="344" data-orig-width="210" data-orig-src="https://raw.githubusercontent.com/toddway/MaterialTransitions/master/img/activity-transitions.gif"&gt;&lt;img src="https://64.media.tumblr.com/a7e6a5bebae8c3ba24f8236e89d521bf/tumblr_inline_pjzom1fSPF1r4ik0y_540.gif" style="width:210px;border:1px solid #eeeeee" data-orig-height="344" data-orig-width="210" data-orig-src="https://raw.githubusercontent.com/toddway/MaterialTransitions/master/img/activity-transitions.gif"/&gt;&lt;/figure&gt;&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;h2&gt;Activity Transition tricks:&lt;/h2&gt;

&lt;ul&gt;&lt;li&gt;Generate a background bitmap immediately before the transition and pass it to the called activity&lt;/li&gt;
&lt;li&gt;Suppress the view overaly (used by default for activity transitions) to keep shared elements behind the toolbar &amp;amp; system bars&lt;/li&gt;
&lt;li&gt;Fall back to fade and scale activity transitions when&lt;/li&gt;
&lt;/ul&gt;</description><link>https://toddway.com/post/117743994705</link><guid>https://toddway.com/post/117743994705</guid><pubDate>Wed, 29 Apr 2015 22:23:18 -0500</pubDate><category>android</category><category>ui</category></item><item><title>Mocking backend features in an Android app</title><description>&lt;p&gt;Many of the apps we build rely on backend web services.  During development these systems are often still in flux.  Test environments go on and offline.  Web services change.  Data from the servier is inconsistent or incomplete.  This article outlines a few techniques to mock external network dependencies so development and user testing can keep moving.&lt;/p&gt;

&lt;h2&gt;Dev settings&lt;/h2&gt;

&lt;p&gt;Android&amp;rsquo;s &lt;a href="http://developer.android.com/guide/topics/ui/settings.html"&gt;Setting/Preference API&lt;/a&gt; is a handy way for developers and testers to configure mock features directly in your app.&lt;/p&gt;

&lt;p&gt;&lt;img style="width:360px" src="https://dl.dropboxusercontent.com/u/862951/md/dev-settings.png"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;p&gt;&lt;img style="width:360px" src="https://dl.dropboxusercontent.com/u/862951/md/backend-dialog.png"/&gt;&lt;/p&gt;

&lt;p&gt;Jake Wharton&amp;rsquo;s &lt;a href="https://github.com/JakeWharton/u2020"&gt;u2020 project&lt;/a&gt; wraps settings like these in a clever &amp;ldquo;Debug Drawer&amp;rdquo; that&amp;rsquo;s completely hidden until the user swipes the app from the right bezel. You don&amp;rsquo;t have to get this fancy, but the goal is to make them easily accessible from anywhere in the app without altering your interface layouts.&lt;/p&gt;

&lt;h2&gt;Local Web Service Stubs&lt;/h2&gt;

&lt;p&gt;The first mock setting shown in the image above selects a backend environment.  Typical choices are: Dev environment, Test environment, and Prod environment which each point to a different set of external web services by changing a base URL.  In addition to external environments like these, it&amp;rsquo;s quite useful to have mock environment options that rely only on locally stored stub files.  This isolates your app from flaky servers while still exercising most of the http and serialization logic used for real network requests. See Matt Swanson&amp;rsquo;s article outlining &lt;a href="http://www.mdswanson.com/blog/2014/02/24/integration-testing-rest-apis-for-android.html"&gt;this and 3 alternative approaches for mock data integration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First we copy HTTP responses from real web service calls and paste them into files in the res/raw directory of our app:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;MyAndroidProject
|_app
    |_src
        |_main
            |_res
                |_raw
                    |_ get_some_web_service.stub
                    |_ get_another_web_service.stub
                    |_ empty_get_some_web_service.stub
                    |_ empty_get_another_web_service.stub
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The example above shows local stub files for two web service endpoints - /some/web/service, /another/web/service) and two scenarios -  empty and default (where default stubs have no prefix and empty stubs are prefixed by &amp;ldquo;empty_&amp;rdquo;).  The contents of these files is typically JSON.&lt;/p&gt;

&lt;p&gt;Next we write a custom HTTP client to fetch from these local files instead of the network.  The following example implements the &lt;code&gt;Client&lt;/code&gt; object from Square&amp;rsquo;s &lt;a href="http://square.github.io/retrofit/"&gt;Retrofit library&lt;/a&gt;.  If you&amp;rsquo;re not familiar with Retrofit, the default Client implementation is OkClient.  It makes a standard HTTP network request.  We&amp;rsquo;re writing a custom client to fake a network request and get the response data from a local file instead of a network server.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class LocalStubClient implements Client {
    private Context context;
    private String scenario;

    public LocalStubClient(Context context, String scenario) {
        this.context = context;
        this.scenario = scenario;
    }

    public LocalStubClient(Context context) {
        this.context = context;
    }

    public void setScenario(String scenario) {
        this.scenario = scenario;
    }

    @Override
    public Response execute(Request request) throws IOException {
        //get resource id for local file
        String fileName = createFilename(request, scenario);
        int resourceId = getResourceId(fileName);
        if (resourceId == 0) { //fallback to default filename
            fileName = createFilename(request, null);
            resourceId = getResourceId(fileName);
            if (resourceId == 0) {
                throw new IOException("Could not find res/raw/" + fileName + ".stub");
            }
        }

        //get input stream &amp;amp; mime for local file
        InputStream inputStream = context.getResources().openRawResource(resourceId);
        String mimeType = URLConnection.guessContentTypeFromStream(inputStream);

        //wrap local stream in retrofit objects
        TypedInput body = new TypedInputStream(mimeType, inputStream.available(), inputStream);
        Response response = new Response(request.getUrl(), 200, "Stub from res/raw/" + fileName, new ArrayList&amp;lt;Header&amp;gt;(), body);
        return response;
    }

    private String createFilename(Request request, String scenario) throws IOException {
        URL requestedUrl = new URL(request.getUrl());
        String requestedMethod = request.getMethod();
        String prefix = scenario == null ?  "" : scenario + "_";
        String filename = prefix + requestedMethod + requestedUrl.getPath();
        filename = filename.replace("/", "_").replace("-", "_").toLowerCase();
        return filename;
    }

    private int getResourceId(String filename) {
        return context.getResources().getIdentifier(filename, "raw", context.getPackageName());
    }

    private static class TypedInputStream implements TypedInput {
        private final String mimeType;
        private final long length;
        private final InputStream stream;

        private TypedInputStream(String mimeType, long length, InputStream stream) {
            this.mimeType = mimeType;
            this.length = length;
            this.stream = stream;
        }

        @Override
        public String mimeType() {
            return mimeType;
        }

        @Override
        public long length() {
            return length;
        }

        @Override
        public InputStream in() throws IOException {
            return stream;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally we check our &amp;ldquo;Backend Environment&amp;rdquo; setting to determine if we should use our &lt;code&gt;LocalStubClient&lt;/code&gt; or the default &lt;code&gt;OkClient&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;RestAdapter.Builder builder = new RestAdapter.Builder();

String selectedBackend = getSharedPreference(R.string.pref_backend, "");
switch (Integer.parseInt(selectedBackend)) {
    case R.string.test_server:
    case default:
        builder.setClient(new OkClient());
        builder.setEndpoint("http://test.api.mydomain.com");
        break;
    case R.string.demo_server:
        builder.setClient(new OkClient());
        builder.setEndpoint("http://demo.api.mydomain.com");
        break;
    case R.string.default_local_stubs:
        builder.setClient(new LocalStubClient(app));
        break;
    case R.string.empty_local_stubs:
        builder.setClient(new LocalStubClient(app, "empty"));
        break;
}

RestAdapter adapter = builder.build();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice we have two local stub options.  One is &amp;ldquo;default&amp;rdquo; and one is &amp;ldquo;empty&amp;rdquo;.  This way we can quickly check how our app handles empty scenarios and then go right back to &amp;ldquo;default&amp;rdquo; responses.&lt;/p&gt;

&lt;h2&gt;Simulate network delays and failures&lt;/h2&gt;

&lt;p&gt;Retrofit also allows us to simulate network delays, variance, and failures.  Here&amp;rsquo;s code to enable/disable a mock network adapter based on our second Dev setting:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;RestAdapter.Builder builder = new RestAdapter.Builder();

//...

RestAdapter adapter = builder.build();

if (getSharedPreference(R.string.pref_mock_network, false)) {
    MockRestAdapter mockRestAdapter = MockRestAdapter.from(adapter);
    mockRestAdapter.setDelay(1000);
    mockRestAdapter.setVariancePercentage(50);
    mockRestAdapter.setErrorPercentage(10);
    return mockRestAdapter.create(serviceType, adapter.create(serviceType));
} 
return adapter.create(serviceType)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;re continuing to improve our techniques for mocking backend features but have found these to be useful and easy to apply (if you&amp;rsquo;re using Retrofit).  The extra work to build quick settings access into your app will pay for itself as your backend systems undergo varying levels of reliability and consistency.  Anyone else have tips or techniques like these for managing app backends?&lt;/p&gt;</description><link>https://toddway.com/post/115767491695</link><guid>https://toddway.com/post/115767491695</guid><pubDate>Tue, 07 Apr 2015 10:46:10 -0500</pubDate><category>android</category><category>retrofit</category></item><item><title>Automatically boot and unlock an Android emulator </title><description>&lt;p&gt;For all you DRY-conscious developers out there who want to eliminate some repetitive manual steps when testing against an Android emulator, here&amp;rsquo;s a simple bash script.   It boots the emulator if it&amp;rsquo;s not already running, waits for the full boot, and then unlocks the lock screen.  It&amp;rsquo;s pretty handy automated tests against an emulator with something like &lt;a href="http://calaba.sh"&gt;Calabash&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/bash

# init variables
DEVICE_ID="@nexus5"
EMULATOR_CHECK_STATUS="adb shell getprop init.svc.bootanim"
EMULATOR_IS_BOOTED="stopped"

# see if emulator needs to be booted
OUT=$($EMULATOR_CHECK_STATUS)
if [[ ${OUT:0:7} == $EMULATOR_IS_BOOTED ]]
then # do nothing if already booted
    echo "Emulator already booted."
else # Start the emulator in the background
    emulator $DEVICE_ID &amp;amp; # for Android SDK emulator
    # /Applications/Genymotion.app/Contents/MacOS/player --vm-name "$DEVICE_ID" &amp;amp; # for genymotion emulator

    # wait for full emulator boot
    OUT=$($EMULATOR_CHECK_STATUS)
    while [[ ${OUT:0:7}  != $EMULATOR_IS_BOOTED ]]; do
            OUT=$($EMULATOR_CHECK_STATUS)
            echo "Waiting for emulator to fully boot..."
            sleep 3
    done

    echo "Emulator booted!"

    adb shell input keyevent 82 # unlock lock screen
fi
&lt;/code&gt;&lt;/pre&gt;</description><link>https://toddway.com/post/101024820980</link><guid>https://toddway.com/post/101024820980</guid><pubDate>Sun, 26 Oct 2014 15:48:20 -0500</pubDate><category>android</category><category>continuous integration</category></item><item><title>Browse some of the best Android library demos with DevAppsDirect</title><description>&lt;a href="https://play.google.com/store/apps/details?id=com.inappsquared.devappsdirect"&gt;Browse some of the best Android library demos with DevAppsDirect&lt;/a&gt;: &lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.inappsquared.devappsdirect"&gt;DevAppsDirect&lt;/a&gt; is a great tool for Android designers and developers.  Install it on any Android device and get quick access to demo UI patterns, custom views, widgets, game engines, and other libraries.&lt;/p&gt;</description><link>https://toddway.com/post/82410563497</link><guid>https://toddway.com/post/82410563497</guid><pubDate>Fri, 11 Apr 2014 15:18:50 -0500</pubDate><category>android</category><category>ux</category></item><item><title>Easy local stack management with Vagrant</title><description>&lt;p&gt;I’m using &lt;a href="http://www.vagrantup.com"&gt;Vagrant&lt;/a&gt; to hand-off complete copies of my local development environment to other members of my team.  This is a great way to lower setup time, isolate dependencies and eliminate inconsistencies.  Frontend developers are able to work against a full local environment without wasting time on backend configuration.  The following describes how Vagrant can make this possible without any additional &lt;a href="http://docs.vagrantup.com/v2/provisioning/"&gt;provisioning tools&lt;/a&gt;.  Those tools are powerful and offer even more efficiencies, but we’re leaving them out in the interest of simplicity.&lt;/p&gt;

&lt;p&gt;&lt;!-- more --&gt;&lt;/p&gt;

&lt;h2&gt;A sample environment&lt;/h2&gt;

&lt;p&gt;On my MacBook Pro, I built a VM that runs the entire technology stack for a web application I’m currently working on called Jude.  It’s a &lt;a href="http://virtualbox.org"&gt;VirtualBox&lt;/a&gt; VM with things like Linux, Apache Web Server, MySQL, PHP, Memcache, APC, Drush, and Apache Solr installed and configured to work together.  The codebase is checked out from a remote SVN code repository to a local directory on my Mac that’s also shared to the VM.  I can use my regular Mac text editor (&lt;a href="http://netbeans.org"&gt;NetBeans&lt;/a&gt;) to edit code locally, and the changes are immediately available in the running VM.  I can also use the command line (SSH), a database explorer (&lt;a href="http://www.sequelpro.com"&gt;Sequel Pro&lt;/a&gt;), and a breakpoint debugger (NetBeans) to inspect the running web app.&lt;/p&gt;

&lt;figure class="tmblr-full" data-orig-height="585" data-orig-width="723" data-orig-src="https://docs.google.com/drawings/d/1PVaPLsQnPE50MaMChk1ceFVk9xsUNMBSd5eGhi4LAiw/pub?w=724&amp;amp;h=585"&gt;&lt;img src="https://64.media.tumblr.com/6bb9d9c7181c4a7427c086468d425f43/tumblr_inline_pjzp0qRwjm1r4ik0y_540.png" data-orig-height="585" data-orig-width="723" data-orig-src="https://docs.google.com/drawings/d/1PVaPLsQnPE50MaMChk1ceFVk9xsUNMBSd5eGhi4LAiw/pub?w=724&amp;amp;h=585"/&gt;&lt;/figure&gt;&lt;p&gt;Vagrant, &lt;a href="http://www.opscode.com/chef/"&gt;Chef&lt;/a&gt;, and the &lt;a href="https://drupal.org/project/vagrant"&gt;Drupal Vagrant&lt;/a&gt; project made most of this configuration automatic, but manual configuration would have worked just as well.  The point being it doesn&amp;rsquo;t matter how the initial VM gets created or what the technology stack is.  It just matters that we set it up once and we want an easy way to copy it to another machine.&lt;/p&gt;

&lt;h2&gt;Sample workflow for spinning up a new VM copy&lt;/h2&gt;

&lt;h3&gt;Step 1: Package the source VM&lt;/h3&gt;

&lt;p&gt;First we need to package up the initial VM from the source machine and make it available for download.  The following command packs up the VirtualBox VM called vagrant_1374870184 and creates a file on the source machine called jude.box.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant package --base vagrant_1374870184 --output jude.box --vagrantfile box.Vagrantfile
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The box file then needs to be copied to the target machine or uploaded to a publicly accessible URL.&lt;/p&gt;

&lt;h3&gt;Step 2: Install the target VM&lt;/h3&gt;

&lt;p&gt;On the target machine we need to install &lt;a href="https://www.virtualbox.org/wiki/Downloads"&gt;VirtualBox&lt;/a&gt; and &lt;a href="http://downloads.vagrantup.com/"&gt;Vagrant&lt;/a&gt;, then open up a terminal window and run the following commands.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkdir &amp;lt;project-directory&amp;gt;
cd &amp;lt;project-directory&amp;gt;
svn co https://path/to/repo/trunk/htdocs public/dev-site.vbox.local/www/
echo -e '33.33.33.10\tdev-site.vbox.local' | sudo tee -a /etc/hosts
vagrant init jude https://path/to/file/jude.box
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first three lines create the project directory and checkout the codebase from a remote SVN repository.  The &lt;code&gt;public&lt;/code&gt; directory in the checkout location is the directory that will be mounted to the VM via NFS.  The &lt;code&gt;dev-site.vbox.local/www&lt;/code&gt; directory represents the web root of an Apache vhost on our VM.&lt;/p&gt;

&lt;p&gt;Line four adds the site’s domain alias to our local hosts file.  &lt;code&gt;33.33.33.10&lt;/code&gt; is the IP address we defined in the Vagrantfile on our source VM and &lt;code&gt;dev-site.vbox.local&lt;/code&gt; is the vhost we defined in the source VM&amp;rsquo;s Apache conf.&lt;/p&gt;

&lt;p&gt;Line five uses the source box file we packaged in the first step to initialize the target VM configuration.  We now have a file called &lt;code&gt;Vagrantfile&lt;/code&gt; in our project directory where we could override environment settings if we needed.&lt;/p&gt;

&lt;h3&gt;Step 3: Start the target VM&lt;/h3&gt;

&lt;p&gt;Now we&amp;rsquo;re ready to start up the new VM by running:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first start up may take a few minutes, especially if the box file is remote and has not been downloaded yet. Start ups in the future will be much faster.  Once this is complete we can access our new local copy of Jude at  &lt;a href="http://"&gt;http://dev-site.vbox.local&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Further possibilities&lt;/h2&gt;

&lt;p&gt;At my company, we use a similar technology stack across many of our projects.  Vagrant can be used to manage reusable VM components across all these projects.  In addition to developer workstation installations, these could be used to spin up identical development, testing and production environments.  Say goodbye to &amp;ldquo;works on my machine&amp;rdquo; bugs.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re interested in using this approach on your next project and you&amp;rsquo;re using Drupal, be sure to check out &lt;a href="https://drupal.org/project/vagrant"&gt;Drupal Vagrant&lt;/a&gt;.  It made the setup of my initial VM really simple.  The only piece that needed to be manually configured was Apache Solr.&lt;/p&gt;</description><link>https://toddway.com/post/58794129376</link><guid>https://toddway.com/post/58794129376</guid><pubDate>Tue, 20 Aug 2013 10:50:00 -0500</pubDate><category>Drupal Planet</category><category>code</category></item><item><title>A clean, lightweight, pure JS alternative for anchoring file fields to Drupal WYSIWYGs</title><description>&lt;p&gt;&lt;img src="https://dl.dropbox.com/u/862951/md/modal-links.png" style="border:1px solid #ccc;width:100%" alt="image"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/toddway/jquery.modalize"&gt;jquery.modalize.js&lt;/a&gt; is a lightweight, pure-javascript approach to automatically turn part of any web page into a modal overlay.&lt;/p&gt;

&lt;p&gt;I originally wrote it as a simple alternative for associating file upload fields to WYSIWYGs in Drupal, but can be used to modalize any chunk of HTML and significantly clean up overloaded pages (Drupal or non-Drupal).&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2&gt;The original dilemma&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve never loved any of the solutions for associating image and file uploads to WYSIWYGs in Drupal and yet I&amp;rsquo;ve had to do it on almost every project I&amp;rsquo;ve worked on.  The &lt;a href="http://drupal.org/project/media"&gt;Media module&lt;/a&gt; and the &lt;a href="http://drupal.org/project/wysiwyg_fields"&gt;Wysiwyg Fields module&lt;/a&gt; are both ambitious projects that attempt this feature (and other things as well).  Unfortunately I&amp;rsquo;ve run into issues with both.  Being complex modules they are difficult to troubleshoot and hard to move away from if they don&amp;rsquo;t work out.&lt;/p&gt;

&lt;h2&gt;My usual solution&lt;/h2&gt;

&lt;p&gt;I normally end up sticking a multi-value image field and a multi-value file field underneath the WYSIWYG and then using the excellent &lt;a href="http://drupal.org/project/insert"&gt;Insert module&lt;/a&gt; to allow content editors to &amp;ldquo;send&amp;rdquo; HTML for the uploaded files to the WYSIWYG.&lt;/p&gt;

&lt;p&gt;&lt;img src="https://dl.dropbox.com/u/862951/md/no-modal.png" style="border:1px solid #ccc;width:400px" alt="image"/&gt;&lt;/p&gt;

&lt;p&gt;This is reliable and works nicely, but has a few drawbacks:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;It takes up lot of screen real estate - especially if you upload many files&lt;/li&gt;
&lt;li&gt;The WYSIWYG associations aren&amp;rsquo;t immediately intuitive to users - sometimes they have to scroll to see the whole picture&lt;/li&gt;
&lt;li&gt;If you have more than one WYSIWYG on a page it&amp;rsquo;s even harder to infer the associations.&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;The new modally-powered solution&lt;/h2&gt;

&lt;p&gt;With jquery.modalize.js, I start with my usual solution (as described above), add a single line of jQuery to turn my file fields into modals, and attach them to every WYSIWYG on the page.&lt;/p&gt;

&lt;p&gt;&lt;img src="https://dl.dropbox.com/u/862951/md/modal-links.png" style="border:1px solid #ccc;width:400px" alt="image"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="https://dl.dropbox.com/u/862951/md/opened-modal.png" style="border:1px solid #ccc;width:400px" alt="image"/&gt;&lt;/p&gt;

&lt;p&gt;To use it you just need JQuery, jquery.modalize.js, and a line of code like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.modalize('#edit-field-image-attachments', '+ Attach images', '.field-type-text-with-summary');
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This turns the &lt;code&gt;#edit-field-image-attachments&lt;/code&gt; element into a hidden modal, replaces it with a link labeled &lt;em&gt;+ Attach images&lt;/em&gt; and prepends the link to all elements with the &lt;code&gt;.field-type-text-with-summary&lt;/code&gt; class (covers WYSIWYG fields in Drupal).  Clicking on the link will open the modal as a page overlay.  The third argument is optional and if not provided, the modal link will be attached in the original element&amp;rsquo;s DOM location.&lt;/p&gt;

&lt;p&gt;As a bonus, Modalize is Insert module aware, so clicking the Insert button will automatically close the modal and show the user the WYSIWYG it was inserted into.&lt;/p&gt;</description><link>https://toddway.com/post/47163125679</link><guid>https://toddway.com/post/47163125679</guid><pubDate>Thu, 04 Apr 2013 22:03:00 -0500</pubDate><category>code</category><category>ui</category><category>js</category><category>drupal planet</category></item><item><title>Single Page Interface with Drupal</title><description>&lt;p&gt;&lt;img src="https://dl.dropbox.com/u/862951/md/custom-drupal-overaly.png" style="width:100%" alt="image"/&gt;&lt;/p&gt;

&lt;p&gt;We recently built a community app in Drupal.  It has:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;a fully abstracted (no Drupal), single page (no reloads) frontend&lt;/li&gt;
&lt;li&gt;a web service enabled Drupal backend&lt;/li&gt;
&lt;li&gt;an integrated Drupal overlay for edit and admin pages&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Here’s how we did it:&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2&gt;Setting up Drupal web services&lt;/h2&gt;

&lt;p&gt;The Drupal &lt;a href="http://drupal.org/projects/services"&gt;Services module&lt;/a&gt; provides a standard framework for defining web services.  This was our foundation for making Drupal data available to an external application.  Out of the box it supports multiple interfaces like REST, XMLRPC, JSON, JSON-RPC, SOAP, AMF and provides functional CRUD services for core Drupal entities like nodes, users, and taxonomy terms.  The response data is structured much like the Drupal entity objects you’re used to seeing in PHP and provides all the same data.  We added our own group of “UI” services to clean up these objects and strip out some of the data that isn’t relevant to the UI layer (lots of [‘und’] arrays).  I’m hoping to make this into a contrib module sometime soon.&lt;/p&gt;

&lt;p&gt;A response to the standard Services resource &lt;code&gt;/rest/user/&amp;lt;uid&amp;gt;.json&lt;/code&gt; looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  uid: "222",
  name: "tway",
  field_first_name: {
    und: [
      {
        value: "Todd",
        format: null,
        safe_value: "Todd"
      }
    ]
  },
  field_last_name: {
    und: [
      {
        value: "Way",
        format: null,
        safe_value: "Way"
      }
    ]
  },
  field_location: {
    und: [
      {
        tid: "604"
      }
    ]
  },
  field_department: {
    und: [
      {
        tid: "614"
      }
    ]
  },
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And a response to our UI resource &lt;code&gt;/rest/user/&amp;lt;uid&amp;gt;/ui.json&lt;/code&gt; looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  uid: "222",
  name: "tway",
  field_first_name: {
    label: "Todd"
  },
  field_last_name: {
    label: "Way"
  },
  field_location: {
    id: "604",
    label: "KC-Airport",
    type: "taxonomy_term"
  },
  field_department: {
    id: "614",
    label: "Technology",
    type: "taxonomy_term"
  },
  edit_link: "user/222/edit",
  display_name: "Todd Way",
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Making authenticated web service requests from your frontend app&lt;/h2&gt;

&lt;p&gt;The Services module comes with support for session-based authentication.  This was essential for our app because we did not want any of our content or user data to be publicly available.  Each request had to be associated with an authorized user.  So basically, if a valid session key is set (as a request header cookie) on a service request, Drupal will load the user associated with that session key - just like any  standard Drupal page request.  There are two ways to accomplish this with an external frontend.&lt;/p&gt;

&lt;h3&gt;Option 1: Run your app on the same domain as Drupal&lt;/h3&gt;

&lt;p&gt;If your app can run on the same web domain as the Drupal services backend, you can use the built-in Drupal login form to handle authentication for you.  It will automatically set the session key cookie and pass it on any service requests from the browser on that domain.  So for example if your Drupal site is at &lt;strong&gt;&lt;a href="http://mysite.com"&gt;http://mysite.com&lt;/a&gt;&lt;/strong&gt; and your Drupal login is at &lt;strong&gt;&lt;a href="http://mysite.com/user"&gt;http://mysite.com/user&lt;/a&gt;&lt;/strong&gt;, your UI app will be at something like &lt;strong&gt;&lt;a href="http://mysite.com/my-ui-path"&gt;http://mysite.com/my-ui-path&lt;/a&gt;&lt;/strong&gt; (more on how to set this up later).&lt;/p&gt;

&lt;p&gt;To make a jQuery-based service request for a user object you would simply need to do this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(function ($) {
    $.getJSON('/rest/user/1.json', function(data) {
      console.log(data);
    });    
})(jQuery);  
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The response data, if the request was properly authenticated, would be:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
 "uid":"1",
 "name":"admin",
 "mail":"admin@mysite.com",
 "created":"1354058561",
 "access":"1363899033",
 "login":"1363725854",
 "status":"1",
 "timezone":"America/Chicago",
 "roles":[
    2
 ],
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and if unauthenticated would be:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[
  "Access denied for user anonymous"
]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Option 2: Run your app on a separate domain&lt;/h3&gt;

&lt;p&gt;If your app will be on a separate domain it will need it’s own server (e.g. node.js, etc.) to proxy all authenticated service requests.  One reason for this is that web browsers do not allow the Cookie header to be set on XMLHttpRequest from the browser (see the &lt;a href="http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method"&gt;W3C Spec&lt;/a&gt;).  You can get around this on GET requests with JSONP if you do something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$.ajax({
     type: 'GET',
     url: 'http://mysite.com/rest/uiglobals.jsonp?callback=jsonpCallback',
     async: false,
     jsonpCallback: 'jsonpCallback',
     contentType: "application/json",
     dataType: 'jsonp',
     success: function(json) { console.log(json); },
     error: function(e) { console.log(e.message); }
 });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However JSONP does not allow POST requests, so this is not a complete solution.  For more details, check out &lt;a href="http://chroder.com/posts/archive-cross-domain-ajax"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your proxy server will need to call an initial login service request (already part of the services module) on behalf of the client browser that takes a username and password and, if valid, returns a session key.  The server then needs to pass the session key in the Cookie header on all service requests.  If you were using a second Drupal site for your proxy, the PHP would look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php
function example_service_request() {
  $server = 'http://example.com/rest/';

  //login request - we need to make an initial authentication request before requesting protected data
  $username = 'username';
  $password = 'password';
  $url = $server . 'user/login.json';
  $options = array(
    'method' =&amp;gt; 'POST',
    'headers' =&amp;gt; array('Content-Type' =&amp;gt; 'application/json'),
    'data' =&amp;gt; json_encode(array(
      'username' =&amp;gt; $username,
      'password' =&amp;gt; $password,
    )),
  );  

  $result = drupal_http_request($url, $options['headers'], $options['method'], $options['data']);  //d6 
  //$result = drupal_http_request($url, $options); //d7

  if ($result-&amp;gt;code != 200) {
    drupal_set_message(t('Authentication error: ') . $result-&amp;gt;status_message, 'error');
  }
  $login_data = json_decode($result-&amp;gt;data);

  //build the session cookie from our login repsonse so we can pass it on subsequent requests
  $cookie = $login_data-&amp;gt;session_name . "=" . $login_data-&amp;gt;sessid . ";"; 

  //user search request
  //$url = $server . 'search/user_index/ui.json';
  $url = $server . 'search/user_index/ui.json?keys=joe&amp;amp;sort=field_anniversary:DESC'; 

  $options = array(
    'method' =&amp;gt; 'GET',
    'headers' =&amp;gt; array(
      'Content-Type' =&amp;gt; 'application/json',
      'Cookie' =&amp;gt; $cookie, //add our auth cookie to the header
    ),
  );
  $result = drupal_http_request($url, $options['headers'], $options['method'], $options['data']);  //d6 
  //$result = drupal_http_request($url, $options); //d7
  dpm(json_decode($result-&amp;gt;data), 'result data');

  //Log out request, since we are done now.
  $url = $server . 'user/logout.json';
  $options = array(
    'method' =&amp;gt; 'POST',
    'headers' =&amp;gt; array('Cookie' =&amp;gt; $cookie),
  );
  $result = drupal_http_request($url, $options['headers'], $options['method'], $options['data']);  //d6     
  //$result = drupal_http_request($url, $options); //d7
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We didn&amp;rsquo;t use this code for our UI app, but it came in handy for testing and we eventually used it to interact with data from another backend system.&lt;/p&gt;

&lt;p&gt;For our UI app, we used option 1 for two main reasons:&lt;br/&gt;
1. No need for a separate frontend server or custom authentication handling.&lt;br/&gt;
2. Better integration with the Drupal overlay (more on this later).&lt;/p&gt;

&lt;h2&gt;Hosting the frontend app for local development&lt;/h2&gt;

&lt;p&gt;We didn’t want our frontend developers to need any Drupal knowledge or even a local Drupal install in order to develop the app.  We set up a web proxy on our shared Drupal development environment so frontend developers could build locally against it while appearing to be on the same domain (to maintain the cookie-based authentication).  We used a simplified version of &lt;a href="https://github.com/cowboy/php-simple-proxy"&gt;PHP Simple Proxy&lt;/a&gt; for this and added it to the Drupal webroot, but Apache can be configured to handle this as well.  I wouldn&amp;rsquo;t recommend using a Drupal-based proxy since each request would perform unnecessary database calls during the Drupal bootstrap.&lt;/p&gt;

&lt;p&gt;Our frontend developers used &lt;a href="http://node.js"&gt;node.js&lt;/a&gt; and &lt;a href="http://progrium.com/localtunnel"&gt;localtunnel&lt;/a&gt;, but other local dev tools could be used for this.  As long as the Drupal development server can make requests to the frontend developer’s machine, the web proxy will work.  Using this setup, the URL for frontend development looks something like this&amp;hellip;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;a href="http://mysite.devserver.com/proxy.php?url=myfrontend.localtunnel.com"&gt;http://mysite.devserver.com/proxy.php?url=myfrontend.localtunnel.com&lt;/a&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;hellip;where &lt;code&gt;mysite.devserver.com&lt;/code&gt; is the domain alias of the dev server, &lt;code&gt;proxy.php&lt;/code&gt; is the name of the PHP proxy script, and &lt;code&gt;myfrontend.localtunnel.com&lt;/code&gt; is the domain alias for a frontend developer’s machine.&lt;/p&gt;

&lt;h2&gt;Hosting the frontend app in Drupal&lt;/h2&gt;

&lt;p&gt;To make the frontend app easy to deploy along with the Drupal backend, we set up a simple custom Drupal module to host it.  Since the app is just a single HTML page (and some JS and CSS files), we define one custom menu item and point it to a custom TPL.&lt;/p&gt;

&lt;p&gt;Here are the essential pieces for our judeui.module file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php
/**
 * implements hook_menu
 */
function judeui_menu() {
  //define our empty ui menu item
  $items['ui'] = array(
    'page callback' =&amp;gt; 'trim', //shortcut for empty menu callback
    'page arguments' =&amp;gt; array(''),
    'access callback' =&amp;gt; TRUE,
  );
  return $items;
}

/**
 * implements hook_theme
 */
function judeui_theme() {
  //point to our custom UI TPL for the 'ui' menu item
  return array(
    'html__ui' =&amp;gt; array(
      'render element' =&amp;gt; 'page',
      'template' =&amp;gt; 'html__ui',
    ),
  );
}

/**
 * implements hook_preprocess_html
 * @param type $vars
 */
function judeui_preprocess_html(&amp;amp;$vars) {
  //if we're serving the ui page, add some extra ui variables for the tpl to use
  $item = menu_get_item();
  if ($item['path'] == 'ui') {        
    $vars['judeui_path'] = url(drupal_get_path('module', 'judeui'));
    $vars['site_name'] = variable_get('site_name', '');

    //add js to a custom scope (judeui_scripts) so we can inject global settings into the UI TPL
    drupal_add_js(
      "var uiglobals = " . drupal_json_encode(_get_uiglobals()), 
      array('type' =&amp;gt; 'inline', 'scope' =&amp;gt; 'judeui_scripts')
    );
    $vars['judeui_scripts'] = drupal_get_js('judeui_scripts');
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The hook_menu function defines our ui page, the hook_theme function points it at our custom TPL, and the hook_preprocess_html lets us add a few custom variables to the TPL.  We use the &lt;strong&gt;judeui_scripts&lt;/strong&gt; variable to get global settings from Drupal into the page - much like the Drupal.settings variable on a standard Drupal page. We also have a web service that the ui app could use for this, but adding this directly to the page saves an extra request when intially building the page.  More on ui globals in the next section.&lt;/p&gt;

&lt;p&gt;And here is our custom html_ui.tpl.php file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;&amp;lt;?php echo $site_name ?&amp;gt;&amp;lt;/title&amp;gt;
        &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"&amp;gt;
        &amp;lt;?php echo $judeui_scripts ?&amp;gt;
        &amp;lt;script src="&amp;lt;?php echo $judeui_path ?&amp;gt;/app.js"&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;link href="&amp;lt;?php echo $judeui_path ?&amp;gt;/app.css" rel="stylesheet"/&amp;gt;      
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It contains the few very basic PHP variables that we set in hook_preprocess_html and a small amount of HTML to set the page up.  Frontend developers can build and deploy app updates simply by committing new app.js and app.css files to the module folder.  Drupal serves the page at &lt;code&gt;&lt;a href="http://mysite.com/ui"&gt;http://mysite.com/ui&lt;/a&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Global settings for the UI&lt;/h2&gt;

&lt;p&gt;We added a custom web service to pass global settings to the UI app.  The frontend app can call &lt;code&gt;&lt;a href="http://mysite.com/rest/uiglobals.json"&gt;http://mysite.com/rest/uiglobals.json&lt;/a&gt;&lt;/code&gt; to load this or use the &lt;code&gt;uiglobals&lt;/code&gt; variable we added to the UI TPL in the section above.  Both of these methods use a function that returns an array of settings that are useful to the UI app.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php
function _get_uiglobals() { 
  return array(    
    'basePath' =&amp;gt; base_path(), 
    'site-name' =&amp;gt; variable_get('site_name', ''),
    'site-slogan' =&amp;gt; variable_get('site_slogan',''),
    'publicFilePath' =&amp;gt; file_stream_wrapper_get_instance_by_uri('public://')-&amp;gt;getDirectoryPath(),
    'privateFilePath' =&amp;gt; 'system',
    'main-menu' =&amp;gt; _get_uimenu('main-menu'),
    'user-menu' =&amp;gt; _get_uimenu('user-menu'),  
    'image-styles' =&amp;gt; array_keys(image_styles()),
    'user' =&amp;gt; $GLOBALS['user']-&amp;gt;uid,
    'messages' =&amp;gt; drupal_get_messages(NULL, TRUE),
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see it contains global data like base path, site name, currently logged in user, public file path, image styles, messages, etc.  This is a handy way for the frontend to access data that shoudn&amp;rsquo;t change during the browser session.&lt;/p&gt;

&lt;h2&gt;Integrating standard Drupal pages/URLs&lt;/h2&gt;

&lt;p&gt;In the early stages of frontend development it was quite useful to model the pages in a standard Drupal theme.  For a while we thought we might still want some parts of the site to just be standard Drupal pages.  Handling this incremently was fairly simple.&lt;/p&gt;

&lt;p&gt;We established some conventions for URL aliases patterns in both Drupal and the frontend app. For example, one of our content types is &lt;strong&gt;post&lt;/strong&gt;.  The URL alias pattern for posts is &lt;strong&gt;post/[node:nid]&lt;/strong&gt;.  So we had a Drupal-themed URL for the post at &lt;strong&gt;&lt;a href="http://mysite.com/post/123"&gt;http://mysite.com/post/123&lt;/a&gt;&lt;/strong&gt; and a frontend URL at &lt;strong&gt;&lt;a href="http://mysite.com/ui#post/123"&gt;http://mysite.com/ui#post/123&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once the frontend app was ready to start handling posts, we used &lt;strong&gt;hook_url_inbound_alter&lt;/strong&gt; to redirect &lt;strong&gt;&lt;a href="http://mysite.com/post/123"&gt;http://mysite.com/post/123&lt;/a&gt;&lt;/strong&gt; to &lt;strong&gt;&lt;a href="http://mysite.com/ui#post/123"&gt;http://mysite.com/ui#post/123&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php
/**
 * implements hook_url_inbound_alter
 */
function judeui_url_inbound_alter(&amp;amp;$path, $original_path, $path_language) {
  //dpm($path, $original_path);
  if (variable_get('site_frontpage', 'node') == 'ui') {
    $oargs = explode('/', $original_path);
    if (in_array($oargs[0], array('post', 'user', 'group', 'tool')) 
        &amp;amp;&amp;amp; !isset($oargs[2]) &amp;amp;&amp;amp; isset($oargs[1]) &amp;amp;&amp;amp; is_numeric($oargs[1])) {
      drupal_goto('ui/' . $original_path);
    }
    if (strpos($original_path, 'user/edit') === 0) {
      $frag = 'modal/' . str_replace('user/edit', 'user/' . $GLOBALS['user']-&amp;gt;uid . '/edit', $original_path);
      drupal_goto('ui/' . $frag);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is incredibly handy for redirecting preconfigured links in Drupal views or email notifications to our abstracted UI URLs.  And &lt;strong&gt;hook_url_inbound_alter&lt;/strong&gt; can be expanded as more of the app moves to the abstracted UI.&lt;/p&gt;

&lt;h2&gt;Integrating the Drupal overlay&lt;/h2&gt;

&lt;p&gt;We wanted to use the standard content editing and admin pages that Drupal provides and have those pages open in an overlay just like any other Drupal 7+ site.  To make it appear like part of the abstracted frontend, links to Drupal-rendered pages open in an iframe with 100% height and 100% width (just like the &lt;a href="http://drupal.org/documentation/modules/overlay"&gt;Drupal 7 admin overlay&lt;/a&gt;), and we made some minor CSS tweaks to the Drupal theme so that the page appears to be a modal window in front of the abstracted UI.  Now &lt;strong&gt;edit&lt;/strong&gt; and &lt;strong&gt;create&lt;/strong&gt; links throughout our abstracted frontend can open the iframe overlay and display pure Drupal admin pages.&lt;/p&gt;

&lt;p&gt;&lt;img src="https://dl.dropbox.com/u/862951/md/custom-drupal-overaly.png" style="width:100%" alt="image"/&gt;&lt;/p&gt;

&lt;p&gt;In addition we needed to facilitate closing the modal when appropriate.  Setting up a close link in the top right corner of the modal was a pretty straightforward javascript exercise, but we also wanted to close it automatically when a user completed a task in the modal (For example, when a user clicks save after editing a content item, we want the modal to close on it’s own).  Drupal already has a way to handle a redirect after a task (usually a form submit) is complete - the destination query string parameter.  So in our frontend app, we add a destination query parameter to all of the &lt;strong&gt;edit&lt;/strong&gt; and &lt;strong&gt;create&lt;/strong&gt; links.  The frontend app listens to the onload event of the iframe, and if it redirects to a non-modal page (e.g. /ui ), it closes the modal.&lt;/p&gt;

&lt;p&gt;Finally, we want to pass Drupal messages back to the abstracted UI so the user can still see them even if the modal closes.  Since the modal is redirecting to the ui callback when it closes, the &lt;strong&gt;messages&lt;/strong&gt; variable of the uiglobals array will contain any related messages that should be displayed to the user.&lt;/p&gt;

&lt;h2&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;This was our first attempt using this kind of site architecture with Drupal.  Although there were new development challenges inherent to any single page web application (and best saved for another post), the integration with Drupal as a backend and as an adminstrative frontend was suprisingly smooth.  Our community site incorporates other contrib modules like &lt;a href="http://"&gt;Organic Groups&lt;/a&gt;, &lt;a href="http://"&gt;Search API Solr&lt;/a&gt;, &lt;a href="http://"&gt;Message Notify&lt;/a&gt;, and &lt;a href="http://"&gt;CAS&lt;/a&gt; without issue.  Here are some additional benefits we discovered:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Full suite of reusable UI web services for other client apps (Android, iOS, etc).&lt;/li&gt;
&lt;li&gt;Free to use a frontend development team with no Drupal knowledge.&lt;/li&gt;
&lt;li&gt;Avoided many of the usual Drupal theming struggles and limitations.&lt;/li&gt;
&lt;li&gt;Relatively seamless integration of Drupal UI and abstracted UI.&lt;/li&gt;
&lt;li&gt;Progressive integration (You don&amp;rsquo;t have to build the entire UI outside of Drupal - convert it later, if desired)&lt;/li&gt;
&lt;/ol&gt;</description><link>https://toddway.com/post/46638775215</link><guid>https://toddway.com/post/46638775215</guid><pubDate>Fri, 29 Mar 2013 21:57:00 -0500</pubDate><category>code</category><category>ui</category><category>js</category><category>drupal planet</category></item><item><title>Feed Enlarger (Full Text RSS Feed Generator)</title><description>&lt;a href="http://feedenlarger.com"&gt;Feed Enlarger (Full Text RSS Feed Generator)&lt;/a&gt;: &lt;p&gt;Regain control of your feeds and get the full text of every article, blog post and story.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;fast&lt;/li&gt;
&lt;li&gt;free&lt;/li&gt;
&lt;li&gt;full text of truncated feeds&lt;/li&gt;
&lt;li&gt;works with your reader&lt;/li&gt;
&lt;li&gt;can strop out links from original feed&lt;/li&gt;
&lt;/ul&gt;</description><link>https://toddway.com/post/45945320266</link><guid>https://toddway.com/post/45945320266</guid><pubDate>Thu, 21 Mar 2013 17:59:00 -0500</pubDate><category>code</category><category>Tech</category><category>software</category></item><item><title>Strict 404 handling for Drupal sites</title><description>&lt;p&gt;By default, a Drupal site allows undefined arguments on any system path instead of returning 404 Not Found (e.g. &lt;a href="http://drupal.org/node/1/asdlfkjadlfkdjaflakjsldkfa"&gt;http://drupal.org/node/1/asdlfkjadlfkdjaflakjsldkfa&lt;/a&gt;).  I created the &lt;a href="http://drupal.org/project/strict404" target="_blank"&gt;Strict 404 module&lt;/a&gt; to override this behavior and enforce 404 responses for paths that are not actually defined in the menu system.&lt;/p&gt;



&lt;p&gt;Some contrib modules rely on the undefined argument behavior (e.g. for admin pages) so you may want to enable Strict 404 only for certain path patterns (usually vistor-facing pages).  The module provides an admin page for selectively enabling Strict 404 responses. &lt;/p&gt;</description><link>https://toddway.com/post/45784153610</link><guid>https://toddway.com/post/45784153610</guid><pubDate>Tue, 19 Mar 2013 16:58:00 -0500</pubDate><category>modules</category><category>code</category><category>drupal planet</category></item><item><title>Kansas City’s Boulevard and Roasterie brew up a coffee ale</title><description>&lt;a href="http://www.kansascity.com/2013/02/11/4061080/kansas-citys-boulevard-and-roasterie.html"&gt;Kansas City’s Boulevard and Roasterie brew up a coffee ale&lt;/a&gt;: &lt;p&gt;Two Kansas City companies - Boulevard Brewing Co. and The Roasterie – have teamed up on a new beer, Coffee Ale, which will be on store shelves in early March. The businesses – neighbors on the city’s west side - began testing samples in late September and the final limited-edition beer was put in kegs and in 750 ml bottles in late January.&lt;/p&gt;</description><link>https://toddway.com/post/44396266326</link><guid>https://toddway.com/post/44396266326</guid><pubDate>Sat, 02 Mar 2013 14:55:00 -0600</pubDate><category>beer</category></item></channel></rss>
