Feedback Driven Development

I give credit for this idea to my co-worker Ash Etemadieh who first told me about this concept and is something that I've been thinking about lately.

As the name suggests, Feedback Driven Development (FDD for short) is a play on the popular concept of Test Driven Development (TDD). Instead of always relying on writing tests firsts, FDD is a broader approach that says you as the developer should use whichever method will give you feedback the fastest. This idea that we should go beyond strictly adhering TDD has been brewing for some time, particularly by David Heinemeier Hansson (DHH), the creator of Rails.*

* For those interested, DHH had a very thorough conversation with Kent Beck (the originator of TDD) and Martin Fowler around this idea of "Is TDD dead?" While Kent and Martin view the benefits of TDD easily outweighing its cost, the three of them agreed a lot more on the general ideas of automated testing that the title would suggest.

Vojta Jina, the creator of Karma, the popular Javascript test runner, also said that he uses TDD when he's creating something like a command-line app because unit tests provides the fastest form of feedback, however if he's making something that's highly visual like a user interface he might just refresh the browser and look as the fastest form of feedback.

In short, while it may seem really simple, sometimes just loading the web application after incremental changes is the best way of getting feedback.

Below, I've listed a few practical ways that you can practice FDD.

  • Unit testing - Because there are so many articles on TDD today, I won't delve into too much details but to briefly recap the steps of TDD: 1) write a failing test, 2) write just enough application code to pass the failing test, 3) refactor the code to keep the same functionality but improve long-term maintainability and repeat. Fowler & co have called this the red-green refactoring cycle
  • Running the web application - This seems like the most naive approach but is sometimes the best approach as you are actually examining the application as the user. The short-term downside of this approach is that it may take each time to manually do a scenario. For example, if you have to login and then click on several buttons before you can get to the actual screen / interface you are developing with, this might be an inefficient method. To remedy this, I've come up with a few sub-ideas below. The long-term downside of this approach is that it's easy to get lazy and neglect unit testing. The problem is that in order to create a maintainable large-scale code base, you have to have a comprehensive automated test suite (ideally at the unit, functional, and e2e level).
    • Respect the URL - If every distinctive screen on your application has a unique URL, it is much easier than to just refresh the page rather than having to hop through multiple boilerplate screens just to get to the one you're interested in. This is based on how you do your routing.
    • Automatically refresh the browser - Using a tool like BrowserSync automagically refreshes the browser page for you whenever you change the source code.
  • Static analysis - Javascript in the last few years has seen static analysis tools become increasingly popular. The involvement and assistance provided by these tools run the gamut:
    • Language / syntax-based tools - Microsoft's Typescript and Facebook's Flow open source projects are the most popular and extensive static analysis tools available for Javascript right now. Typescript itself is a language that combines ideas from C# and implements them as a language that is a superset of javascript. Flow is pitched as a tool but it has its own syntax (which seem similar to Typescript) and these two are essentially competing in the same space. The real benefit of these tools is that it provides feedbackbefore runtime which should save you time. In practice, I've seen and read that they do emit quite a bit of errors so there is some amount of investment required by the developer.
    • IDE - Using an IDE like WebStorm or a text editor with intellisense like Microsoft's new Visual Studio Code will give you hints about code that don't seem correct. Whether it's a missing comma or a misspelled variable name, I find this to be some of the fastest feedback.
    • Linting - This idea was popularized by Douglas Crockford with his tool JSLint that checked for commonly-made mistakes in Javascript. Especially in the early days when Javascript wasn't taken seriously as a language by many people, this tool was very valuable. As the Javascript community has evolved, JSHint began to get traction as a community-based linting tool which is more flexible than JSLint. Taking it even further is ESLint which is probably the most powerful linting tool for Javascript as of right now and is designed to be easily "pluggable" so you can dd your own linting rules. People have created some powerful linting rules, such as best practices for the Angular framework.
  • Automated testing cloud - Sometimes you really want to get feedback on a page for multiple devices / languages / etc. This is especially relevant for those creating user interfaces that have to work for desktop web and mobile web. Using an automated testing service provider such as Sauce Labs may help you improve your workflow rather than manually opening up the page in Chrome, Firefox, IE, and Safari.
  • Visual diffing - Along the lines of automated testing, visual diffing is a particular technique where you do take screenshots of the key interfaces of an application and then compare them with a basline (basically a set of screenshots that you have manually approved as correct). Huxley is an interesting visual diffing tool however it's no longer maintained by Facebook.

Workflow productivity tips

Recap of workflow productivity tips and tricks that I've implemented:

  • Fast file-navigation using Z jump
  • Use git alias for common commands
  • Use SCM Breeze to easily reference specific files
  • Use Hub as a wrapper around Git to do pull-request from CLI
  • Webstorm: "preview compiled coffeescript file"
  • Write down notes on notebook (when I want diagrams) and workflowy (better for to-do lists)
  • Pre alias checks for unwanted test focusing functions (e.g. ddescribe)

Productivity ideas that I've thought about but haven't done:

  1. Backup dotfiles using Google Drive & sym link
  2. Better windows management using Slate: https://github.com/jigish/slate
  3. Automatically open four shell tabs (1 on client dir, 1 on server dir, 1 on root project dir, 1 on protractor)
  4. Create a git alias to create a tag and push to origin & upstream
  5. Automatically refresh Browserify process after hitting an error OR make a sound when you hit an error (as of now, just make sure you are always looking at the client tab)
  6. Automatically exclude npm_modules and bower_components from webstorm index
  7. git difftool -t meld --cached (Install meld!)
  8. Troubleshoot Wallaby.js (doesn't seem to accurately run tests all the time)

Ideas that don't seem like worth the juice right now:

  • Git pre-commit hook to run unit & e2e tests for next branch

More thoughts on improving workflow

  • Diff git commits better
    • git difftool -t vimdiff --cached
    • Use Kaleidoscope app OR webstorm's diff
  • Pseudo-code more often - much faster than writing code wrong and debugging it mentally
  • Right-click to preview coffeescript compiled file
  • Get Wallaby.js running properly
  • Study coffeescript