Development Workflow08 Jun 2014
Making stuff is hard, right?
There are lots of ways to make things less hard, this is what works for me and it might work for you!
Step 1 is to clearly identify the problem that needs solving. Even if you are making something for fun or learning purposes, there is always a goal to be considered. Part of the consideration should be breaking the big problem into as many little problems as possible. And then breaking all of those problems into smaller problems. It’s problems all the way down. At some point you will hit a bedrock of solved problems to use as a foundation.
A (Contrived) Hypothetical
Let’s imagine you want to make a module that (for some reason!) takes a directory of files, parses all of the tarballs within it, finds any that contains a file with a certain name, and then posts the tarball filename to a web server.
A quick search tells us that this (surprisingly!) doesn’t exist yet. If it did and it worked, this would be a very short blog entry.
I prefer to work with streams, so for this example we will assume this app will be created as a stream pipeline.
In order to make this module, we will need:
- A module that streams filenames from a directory
- A module that will filter a stream (so we only see tarballs)
- A module that streams objects with tarball name and filenames within it
- A module that filters those objects by filename
- A module that posts data to a web server.
Luckily for us, the first 2 and the last one already exist. So at this point, I would begin work on a module that exposes a duplex stream reading tarball locations and writing out objects with tarball location and entry filename, once per entry.
# work begins! mkdir tar-entry-stream; cd tar-entry-stream # initialize a git repo git init # add a license, typically MIT cp ~/license.mit LICENSE # create a barebones readme echo 'tar-entry-stream\n====' > README.md # make a test dir mkdir test # create some placeholder files touch index.js test/index.js # copy in my travis config cp ~/travis.yml .travis.yml # create the package.json, my ~/.npmrc is filled out with my defaults npm init
I then create a repo on Github to host my source code on.
I write the minimum amount of code I can in
index.js to make my module do
what it needs to.
npm install --save-dev tape
Then I create a few tests to ensure that my module does what it should do.
npm test will do run those for me since I filled out my package.json
Once I am satisfied that everything is working order, I edit my README to contain:
- A super-brief description
- A code example
- Any note of gotchas or options
- An explicit callout to the included license (choose one you like here!)
# add my files git add index.js test/index.js package.json README.md .travis.yml LICENSE # add my github repo as a remote git remote add origin $github-url git push origin master
…wait for travis to verify build, and then:
npm publish. Tada! Now I can
begin work on my main app.
Let’s say I start working on it, but find a bug in my tar-entry-stream module. Wuh oh.
I inspect my code to see if I can quickly identify the cause, if I can I patch
it. Either way, I write a new test that exposes the bug so that I can verify
it is fixed whenever I do find the cause. I have a binding in vim that
allows me to quickly run
npm test so that I can verify my code quickly and
constantly as I work on it.
Once my new test passes (and all of my old ones don’t fail!)
# stage whatever files have been altered git add index.js # commit my changes git commit -m 'fixes hypothetical bug' # bump the version of my module in the package.json, commit and tag npm version patch # push changes to github git push --tags origin master # .. wait for travis build, and then .. npm publish
And there you have it, from creation to publishing, to inevitable maintenance. The benefits of this particular workflow for me are:
- I’m not tied to any specific system that gets in my way
- I can write small, focused tests
- I can write concise, pointed documentation
- I can patch bugs and make changes quickly and confidently
- Because modules are generalized, I can potentially reuse them for future projects. And so can other people!
- I don’t have to maintain tons of configuration files or build scripts
- From start to publish goes very quick, so I feel more inclined to create