git-flow’s val­ue depends on the nature of a project. Take cre­ative writ­ing: Randy Ingermanson’s Snowflake Method makes you start from a crude—yet complete—one-sentence sto­ry and iter­ate until you are left with a good sto­ry. Require­ments imposed by The Snowflake Method are anal­o­gous to git-flow’s role for the master branch. Giv­en a LaTeX project man­aged with a com­bi­na­tion of git-flow and the Snowflake Method (“Snowflow”), we get some inter­est­ing prop­er­ties.

Assume this file sys­tem:

build.sh          # Compile PDF(s) in dist using story/
dist/             # .pdf files
concepts/         # whatever
story/            # .tex files
    aggregate.tex # \document{book} 

At min­i­mum build.sh runs some­thing like pdflatex -halt-on-error -output-directory ./dist ./story/aggregate.tex to make a PDF of your sto­ry. The concepts/ direc­to­ry con­tains assets describ­ing char­ac­ters, set­tings, con­flicts and plot deci­sions. One rule for this project is that the concepts/ direc­to­ry be checked in, but nev­er be processed by code. This allows free-form cre­ativ­i­ty in asset pro­duc­tion that a pre­cise process would oth­er­wise cur­tail.

A woman writing on a Mac, hopefully with help from the Snowflake Method

Snowflow branch­es behave anal­o­gous­ly to their git-flow coun­ter­parts, with some added expec­ta­tions.

  • The master branch holds a project that com­piles to PDF and tells a com­plete sto­ry.
  • An elaborate (develop) branch adds detail to the sto­ry.
  • concept (feature) branch intro­duces at least one unique, self-con­tained con­cept in concept/ lat­er used to elaborate.
  • review (release) branch holds a com­plete sto­ry for review. If the sto­ry is of suf­fi­cient edi­to­r­i­al qual­i­ty it may merge to master.
  • reconcile (hotfix) branch fix­es press­ing log­i­cal errors such as plot­holes.
  • seed (support) branch address­es cir­cum­stan­tial con­cerns such as dif­fer­ences in sto­ry arcs or fic­tion­al uni­vers­es.

To enable the Snowflake Method, master should a com­plete sto­ry, but that sto­ry does not have to be pub­lish­able. On that note an ear­ly iter­a­tion for Therac-25’s firmware shouldn’t have seen the light of day. It may seem insen­si­tive to com­pare death by radi­a­tion over­dose to bad writ­ing, but only if you’ve nev­er read any­thing by Dan Sacharow.

A Snowflow project will face a “soft end” on a com­mit to master rep­re­sent­ing a pub­lish­able sto­ry. Unless you come up with dif­fer­ent uni­vers­es, sto­ry arcs or deriv­a­tive prod­ucts there may be no need to mea­sure pro­gres­sion or com­pat­i­bil­i­ty with ver­sion num­bers or tags.

In exper­i­ment­ing with this work­flow my favorite dis­cov­ery is that concepts/ even­tu­al­ly takes the shape of “behind the scenes” con­tent for read­ers, which may be sep­a­rate­ly pack­aged and sold. So long as com­mits are dis­ci­plined, the com­mit his­to­ry helps you build sev­er­al prod­ucts at once, where the main sto­ry you intend to pub­lish implic­it­ly pro­motes con­tent you could pro­duce using infor­ma­tion in concepts/.

The concepts/ direc­to­ry also serves as a sand­box for inspired writ­ing ses­sions. Writ­ing is pret­ty moody. Some­times I feel dis­ci­plined and can see how to pack­age my com­mits, and oth­er times I just want to write with no dis­trac­tions. So if you want to ham­mer out a few thou­sand words in a text file in concepts/, go nuts. You can always wor­ry about struc­tur­ing the con­tent with Snowflow when you are ready.

Elaboration process

I must elab­o­rate on the elaborate branch. elaborate may either expand on the sto­ry or per­form tech­ni­cal tasks using LaTeX. In the for­mer sce­nario, I use foot­notes con­tain­ing at least one ques­tion or instruc­tion to iden­ti­fy oppor­tu­ni­ties to build on the sto­ry.

You don’t have to use foot­notes, but keep in mind that some­one who reviews your work should not have to be a devel­op­er. I like hav­ing some­thing vis­i­ble in the prod­uct for an author and edi­tor to dis­cuss.

For exam­ple:

Bob jumped over Alice. \footnote{But WHY did Bob jump over Alice?}

To make the elab­o­ra­tion process sen­si­ble, you should write con­tent that address­es a foot­note either in the vicin­i­ty of where the foot­note appeared, or in a loca­tion that bet­ter estab­lish­es con­text. When you resolve the mat­ter raised by a foot­note, remove that foot­note.

When you com­mit to an elaborate branch you may add at least zero foot­notes, but you must remove at least one of the foot­notes found when you start­ed. By the time you start a review branch there should not exist any foot­notes.

Review process

  1. Elab­o­rate on all rel­e­vant foot­notes.
  2. git flow release start ...
  3. Com­pile a PDF to release to trust­ed read­ers for feed­back.
  4. From the feed­back, insert a list of foot­notes (or oth­er anno­ta­tions) where applic­a­ble accord­ing to your own best judge­ment.
  5. Address all foot­notes.
  6. Repeat steps 3–6 until there exist no foot­notes.
  7. git flow release finish

Guidelines

Writ­ing can’t be con­strained by too many rules, but I did note these guide­lines and obser­va­tions down as I worked.

  • Do not adjust the story/ to the concepts/, adjust the concepts/ to the story/.
  • Do not mod­i­fy story/ when on a concept branch.
  • Your com­fort and focus on writ­ing comes before the process. Don’t be afraid of relax­ing with pen and paper to decide what to do. Lay down on the floor and sketch on a bunch of Post-Its next to a cup of tea before typ­ing any­thing.

Licensing Snowflake Method content

If you decide to write using this process, stay mind­ful of where you pub­lish your work­ing code. If your prod­uct is a book, license it like a book. But more than any­thing, con­sult some­one qual­i­fied to talk about licens­ing. Of course some books like You Don’t Know JS are open source, but if you are con­cerned about dis­tri­b­u­tion, do your research and choose a license.

Recruiters might ask me to change my résumé, and by “might” I mean “always.” Some­times it’s reorder­ing sec­tions. Oth­er times it’s giv­ing them a Word doc­u­ment instead of a PDF. This hap­pened enough times to jus­ti­fy at least some lev­el of automa­tion, so I wrote Spin, a CLI that gen­er­ates résumés tai­lored to dif­fer­ent audi­ences. Spin con­verts a super­set of Mark­down Extra to HTML5. So if I made fur­ni­ture on the side, I can gen­er­ate two résumés with $ spin ./woodworker ./programmer.

The woodworker and programmer pro­files are writ­ten in Mark­down Extra mixed with @ direc­tives. The direc­tives define sec­tions and expe­ri­ences with infor­ma­tion like start and end dates. Check out the exam­ples in Spin’s source.

Mak­ing résumés com­piled prod­ucts yield some ben­e­fits:

  • Code reuse. Two pro­files may share let­ter­heads, con­tact info and sec­tions. Corol­lary to this, chang­ing a résumé to entice Agile Cube Farm LLC doesn’t have to change the résumé I lat­er send to Hour­Long Standup Co.
  • Con­sol­i­da­tion. I can write every­thing I ever did in my life in one place. I may now jour­nal my qual­i­fi­ca­tions freely in world’s most obses­sive­ly struc­tured diary.
  • It’s free. Spin is not friend­ly to peo­ple who aren’t used to cod­ing. But all of the résumé man­age­ment tools I’ve seen so far cost mon­ey, are down, don’t sup­port pro­files, or require more labor than I want to put in. I got every­thing I want with Spin for free after the ini­tial time invest­ment.

Implementation notes

I picked PHP to churn this out quick­ly and gen­er­ate doc­u­ments in HTML5 to allow an inter­me­di­ary step for styling and script­ing for those who care enough. I didn’t want to use PHP­Word because my use of it would be too opin­ion­at­ed and would force con­sumers to fuss with PHP exten­sions. Pan­doc works just fine thank youverymuch.

One can use Spin to main­tain a few pro­files and con­vert every out­put doc­u­ment to DOCX and PDF using Pan­doc. My qual­i­fi­ca­tions serve as a real-world exam­ple of this. The base HTML doc­u­ments them­selves may also have extra fea­tures that make them more pleas­ant for view­ing on a brows­er.

If Spin helps you, please con­sid­er buy­ing me a beer!

In the Code­less Code, a cre­ative blog on soft­ware engi­neer­ing, there’s this scribe named Qi and he is a total badass. Qi is source con­trol per­son­i­fied; a prag­mat­ic sto­ry­teller that rea­sons about sys­tems as the sum total of all that came before.

I wrote the qi CLI tool (GitHub, PyPi) as a hat-tip to the author—and with his gra­cious per­mis­sion for use of the name. The idea is to bring devel­op­ers lever­age in dis­cus­sions with man­age­ment through a notice­ably less vio­lent vari­ant of Case 89qi is only a Python wrap­per to git that prints revi­sion hash­es at the end of fixed time inter­vals. This enables run­ning an analy­sis at, say, the end of every week over the past two quar­ters to check if a team deci­sion in Jan­u­ary is hav­ing an intend­ed effect in June.

This helps devel­op­ers and man­agers accept the same facts under pres­sure. I once worked in a high­ly active JS shop with over 30 devel­op­ers and over one hun­dred com­mits every day. We had Bam­boo run­ning builds and auto­mat­ed tests every so often to catch prob­lem­at­ic changes, but it was hard to know if our changes this sprint fol­lowed a spe­cif­ic “direc­tion” for sys­tem qual­i­ty, what­ev­er that meant.  After I wrote and ran qi, I dis­cov­ered that the team was, on aver­age, cre­at­ing sev­en pro­duc­tion code files for every one test suite. To make mat­ters worse, rough­ly 20% of our com­bined JS and CSS went com­plete­ly unused.

We all knew that these things hap­pened, but once I had the num­bers to show that mat­ters were get­ting worse due to man­age­ment pres­sure, we re-pri­or­i­tized to allow more time to increase code cov­er­age for crit­i­cal tests. Qi knew that com­mit his­to­ry could not just be read, but lever­aged.

qi is use­ful when one of the fol­low­ing con­di­tions apply to you:

  • You want to gath­er facts and cor­re­la­tions to study the code’s his­to­ry, review recent changes, or to prove a point.
  • You have no way to mon­i­tor the state of a code­base in terms of met­rics or cor­re­la­tions that are impor­tant to you or man­age­ment.

qi is not use­ful under these con­di­tions:

  • Your project(s) are small or neglect­ed because there is rarely a big pic­ture to derive, let alone a desire to find one.
  • Your team has a strong grasp on the sys­tem being main­tained, or already per­forms suf­fi­cient analy­sis.

What’s happening?

Con­sid­er the com­mand qi --every month --past "3 years".

The com­mand does what it says. It will print revi­sion hash­es that mark the end of every month for the past three years, with some caveats:

  • qi starts from HEAD. The query against his­to­ry will search 3 years pri­or to the com­mit date from HEAD, not from the time you ran the com­mand.
  • If HEAD is younger than 3 years, then the out­put will end at the com­mit mark­ing the end of the first month of devel­op­ment.
  • If HEAD is not even a month old, there will be no out­put.

Print­ing hash­es is one thing, but we want to do some­thing with this infor­ma­tion. Since qi is basi­cal­ly a time iter­a­tor, we can tell it to run a com­mand at each com­mit. Note that qi’s short options use the same let­ter that starts their long options.

qi -e month -p "3 years" -c "./analyze"

When you spec­i­fy a com­mand for qi to run, qi will check out each sig­nif­i­cant com­mit (detach­ing HEAD) and run the com­mand against the code­base at that time.
If your analy­sis fin­ish­es or crash­es, qi will attempt to put HEAD back where it start­ed. But if qi crash­es, HEAD will be left detached and you will need to run git checkout to put it back your­self.

qi -c lets you mod­el infor­ma­tion­al met­rics over time, such as the pro­por­tion of dead code in the project and the cur­rent code cov­er­age by tests. You decide what met­rics mat­ter, because qi is not a report­ing tool, it is one kind of iter­a­tor a report­ing tool might use.

Let’s look at a cou­ple of fun exam­ples.

For triv­ia, if you run qi -e year -p "12 years" -c "du -sh ." on Torvald’s Lin­ux source, you will see the disk usage growth of the project over it’s time on GitHub.

[sage linux]$ qi -e year -p "12 years" -c "du -sh ."
2.8G . # 2017 (to date)
2.7G . # 2016
2.6G . # 2015
2.6G . # 2014
2.5G . # 2013
2.5G . # 2012
2.4G . # 2011
2.4G . # 2010
2.4G . # 2009
2.3G . # 2008
2.2G . # 2007
2.2G . # 2006
2.2G . # 2005

Anoth­er exam­ple is if you want React’s com­plex­i­ty report at the end of every year of its devel­op­ment. In this case you could use this set­up:

$ git clone https://github.com/facebook/react.git && cd react
$ qi --every year --past "3 years" --command "./analyze.sh"

analyze.sh

#!/bin/bash
TIME=$(git show -s --format=%ct HEAD)

# Using https://www.npmjs.com/package/complexity-report
cr -e -f json ./src > $TIME.json