<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" xml:lang="en">
  <teiHeader>
    <fileDesc>
      <titleStmt>
        <title>Best Practices for Scientific Computing</title>
        <author>Greg Wilson</author>
        <author>D. A. Aruliah</author>
        <author>C. Titus Brown</author>
        <author>Neil P. Chue Hong</author>
        <author>Matt Davis</author>
        <author>Richard T. Guy</author>
        <author>Steven H. D. Haddock</author>
        <author>Kathryn D. Huff</author>
        <author>Ian M. Mitchell</author>
        <author>Mark D. Plumbley</author>
        <author>Ben Waugh</author>
        <author>Ethan P. White</author>
        <author>Paul Wilson</author>
      </titleStmt>
      <publicationStmt>
        <p>Tag layer of the DHSS Meta-Tagging Project. The article text is reproduced from the
           staged copy named in sourceDesc and is not altered; the tags are held separately in
           standOff so that overlapping and nested spans are preserved.</p>
      </publicationStmt>
      <sourceDesc>
        <bibl>
          <title>Best Practices for Scientific Computing</title>
          <date>2014</date>
          <publisher>PLoS Biology</publisher>
          <idno type="DOI">10.1371/journal.pbio.1001745</idno>
          
          <idno type="record">wilson2014-best-practices-scientific-computing</idno>
          <note type="staged-file">wilson2014-best-practices-scientific-computing.txt, the project's staged copy</note>
          <note type="text-sha1">2ec8ac0648b1d9110c33d51545db5fe013cde47b</note>
          <note type="rights">cc-by</note>
        </bibl>
      </sourceDesc>
    </fileDesc>
    <profileDesc>
      <textClass><keywords><term>scientific-computing</term></keywords></textClass>
      <particDesc>
        <person xml:id="paper"><p>the paper's own words</p></person>
        <person xml:id="tagger"><p>the tag layer; a sentence written by the tagger about the
          paper, always anchored to a quotation but not itself a quotation</p></person>
      </particDesc>
    </profileDesc>
    <revisionDesc>
      <change when="2026-10-06"
              who="build_paper_edition.py">199 spans located by searching the stored text for the quote's exact words, allowing any whitespace between them</change>
    </revisionDesc>
  </teiHeader>
  <standOff>
    <spanGrp type="tags">
      <span xml:id="t0" from="#a1" to="#a2" type="object_of_study" ana="#object_of_study" resp="#paper">practical software-development techniques for improving the productivity, reliability, maintainability, and reproducibility of scientific computing</span>
      <span xml:id="t1" from="#a11" to="#a12" type="research_question" ana="#research_question" resp="#paper">which established development practices scientists can adopt to reduce software errors, support reuse, and preserve reproducible computational results</span>
      <span xml:id="t2" from="#a88" to="#a89" type="contribution" ana="#contribution" resp="#paper">twenty-four recommendations organized around readability, automation, incremental change, reuse, testing, optimization, documentation, and collaboration</span>
      <span xml:id="t3" from="#a1" to="#a2" type="claim_type" ana="#claim_type" resp="#paper">method</span>
      <span xml:id="t4" from="#a7" to="#a8" type="phenomenon" ana="#phenomenon" resp="#paper">scientific conclusions made unreliable or irreproducible by fragile, opaque, untested, or poorly managed research software</span>
      <span xml:id="t5" from="#a11" to="#a12" type="method" ana="#method" resp="#paper">practice-report<term>practice-report</term></span>
      <span xml:id="t6" from="#a9" to="#a10" type="mechanisms" ana="#mechanisms[0]" resp="#tagger" cert="0.99">mechanisms<term>reused software errors cascade across projects and can trigger downstream publication corrections or retractions</term></span>
      <span xml:id="t7" from="#a17" to="#a18" type="mechanisms" ana="#mechanisms[1]" resp="#tagger" cert="0.99">mechanisms<term>single-task functions keep the number of facts required for comprehension within working-memory limits</term></span>
      <span xml:id="t8" from="#a29" to="#a30" type="mechanisms" ana="#mechanisms[2]" resp="#tagger" cert="0.99">mechanisms<term>saved commands and build tools convert repetitive manual operations into repeatable dependency-driven workflows</term></span>
      <span xml:id="t9" from="#a31" to="#a33" type="mechanisms" ana="#mechanisms[3]" resp="#tagger" cert="0.99">mechanisms<term>identifiers, versions, parameters, and program names provide machine-readable provenance for regenerated output</term></span>
      <span xml:id="t10" from="#a36" to="#a37" type="mechanisms" ana="#mechanisms[4]" resp="#tagger" cert="0.99">mechanisms<term>short iterations produce working code while incorporating feedback as scientific requirements change</term></span>
      <span xml:id="t11" from="#a42" to="#a43" type="mechanisms" ana="#mechanisms[5]" resp="#tagger" cert="0.99">mechanisms<term>version control stores snapshots, conflicts, history, authorship, and change comments for code and data</term></span>
      <span xml:id="t12" from="#a50" to="#a51" type="mechanisms" ana="#mechanisms[6]" resp="#tagger" cert="0.99">mechanisms<term>single authoritative representations and modular reuse let one correction propagate everywhere</term></span>
      <span xml:id="t13" from="#a58" to="#a59" type="mechanisms" ana="#mechanisms[7]" resp="#tagger" cert="0.99">mechanisms<term>assertions stop execution near the fault while simultaneously documenting conditions the program expects</term></span>
      <span xml:id="t14" from="#a60" to="#a61" type="mechanisms" ana="#mechanisms[8]" resp="#tagger" cert="0.99">mechanisms<term>unit, integration, and regression tests check components, combinations, and behavioral stability</term></span>
      <span xml:id="t15" from="#a62" to="#a63" type="mechanisms" ana="#mechanisms[9]" resp="#tagger" cert="0.99">mechanisms<term>turning a discovered bug into a test case prevents unnoticed recurrence</term></span>
      <span xml:id="t16" from="#a66" to="#a67" type="mechanisms" ana="#mechanisms[10]" resp="#tagger" cert="0.99">mechanisms<term>profiling locates actual bottlenecks before low-level optimization effort is spent</term></span>
      <span xml:id="t17" from="#a70" to="#a71" type="mechanisms" ana="#mechanisms[11]" resp="#tagger" cert="0.99">mechanisms<term>high-level prototypes provide rapid design feedback and trusted outputs for optimized implementations</term></span>
      <span xml:id="t18" from="#a78" to="#a79" type="mechanisms" ana="#mechanisms[12]" resp="#tagger" cert="0.99">mechanisms<term>embedded documentation and generators keep human-readable references close to changing source code</term></span>
      <span xml:id="t19" from="#a80" to="#a81" type="mechanisms" ana="#mechanisms[13]" resp="#tagger" cert="0.99">mechanisms<term>pre-merge review, pair roles, and issue tracking distribute defect finding and project knowledge</term></span>
      <span xml:id="t20" from="#a5" to="#a6" type="limitations" ana="#limitations[0]" resp="#tagger" cert="0.99">most scientists are self-taught programmers without exposure to basic development practices</span>
      <span xml:id="t21" from="#a11" to="#a12" type="limitations" ana="#limitations[1]" resp="#tagger" cert="0.99">the recommendations cannot guarantee efficient or error-free software development</span>
      <span xml:id="t22" from="#a13" to="#a14" type="limitations" ana="#limitations[2]" resp="#tagger" cert="0.99">the paper does not cover reproducible-research policy, code and data citation, publication, or open science in detail</span>
      <span xml:id="t23" from="#a34" to="#a35" type="limitations" ana="#limitations[3]" resp="#tagger" cert="0.99">scientific software requirements are rarely frozen and often become knowable only after current results exist</span>
      <span xml:id="t24" from="#a44" to="#a45" type="limitations" ana="#limitations[4]" resp="#tagger" cert="0.99">binary files may be unsuitable for version control and may require separate archival storage plus metadata</span>
      <span xml:id="t25" from="#a54" to="#a55" type="limitations" ana="#limitations[5]" resp="#tagger" cert="0.99">no single defensive or testing practice catches or prevents every mistake</span>
      <span xml:id="t26" from="#a62" to="#a63" type="limitations" ana="#limitations[6]" resp="#tagger" cert="0.99">tests can only compare code against the researcher&#x27;s expectations and understanding of the problem</span>
      <span xml:id="t27" from="#a64" to="#a65" type="limitations" ana="#limitations[7]" resp="#tagger" cert="0.99">reasonably complex code will contain initial bugs regardless of overall practice quality</span>
      <span xml:id="t28" from="#a74" to="#a75" type="limitations" ana="#limitations[8]" resp="#tagger" cert="0.99">some intrinsically difficult code cannot always be made self-explanatory by refactoring</span>
      <span xml:id="t29" from="#a84" to="#a85" type="limitations" ana="#limitations[9]" resp="#tagger" cert="0.99">pair programming may improve productivity but many programmers find it intrusive</span>
      <span xml:id="t30" from="#a90" to="#a91" type="limitations" ana="#limitations[10]" resp="#tagger" cert="0.99">the twenty-four recommendations are a starting point rather than a complete endpoint</span>
      <span xml:id="t31" from="#a92" to="#a93" type="limitations" ana="#limitations[11]" resp="#tagger" cert="0.99">groups should adopt practices incrementally rather than attempt every recommendation at once</span>
      <span xml:id="t32" from="#a1" to="#a2" type="concepts" ana="#concepts[0]" resp="#paper" cert="0.99">best practices for scientific software development<term>best practices for scientific software development</term></span>
      <span xml:id="t33" from="#a1" to="#a2" type="concepts" ana="#concepts[1]" resp="#paper" cert="0.99">scientists&#x27; productivity<term>scientists&#x27; productivity</term></span>
      <span xml:id="t34" from="#a1" to="#a2" type="concepts" ana="#concepts[2]" resp="#paper" cert="0.99">reliability of their software<term>reliability of their software</term></span>
      <span xml:id="t35" from="#a3" to="#a4" type="concepts" ana="#concepts[3]" resp="#paper" cert="0.99">scientific research<term>scientific research</term></span>
      <span xml:id="t36" from="#a7" to="#a8" type="concepts" ana="#concepts[4]" resp="#paper" cert="0.99">software<term>software</term></span>
      <span xml:id="t37" from="#a7" to="#a8" type="concepts" ana="#concepts[5]" resp="#paper" cert="0.99">experimental apparatus<term>experimental apparatus</term></span>
      <span xml:id="t38" from="#a7" to="#a8" type="concepts" ana="#concepts[6]" resp="#paper" cert="0.99">computational methods<term>computational methods</term></span>
      <span xml:id="t39" from="#a7" to="#a8" type="concepts" ana="#concepts[7]" resp="#paper" cert="0.99">central conclusions of published research<term>central conclusions of published research</term></span>
      <span xml:id="t40" from="#a9" to="#a10" type="concepts" ana="#concepts[8]" resp="#paper" cert="0.99">computing errors<term>computing errors</term></span>
      <span xml:id="t41" from="#a9" to="#a10" type="concepts" ana="#concepts[9]" resp="#paper" cert="0.99">prominent retractions<term>prominent retractions</term></span>
      <span xml:id="t42" from="#a11" to="#a12" type="concepts" ana="#concepts[10]" resp="#paper" cert="0.99">best practices<term>best practices</term></span>
      <span xml:id="t43" from="#a11" to="#a12" type="concepts" ana="#concepts[11]" resp="#paper" cert="0.99">error-free software development<term>error-free software development</term></span>
      <span xml:id="t44" from="#a13" to="#a14" type="concepts" ana="#concepts[12]" resp="#paper" cert="0.99">reproducible research<term>reproducible research</term></span>
      <span xml:id="t45" from="#a13" to="#a14" type="concepts" ana="#concepts[13]" resp="#paper" cert="0.99">open science<term>open science</term></span>
      <span xml:id="t46" from="#a15" to="#a16" type="concepts" ana="#concepts[14]" resp="#paper" cert="0.99">program<term>program</term></span>
      <span xml:id="t47" from="#a17" to="#a18" type="concepts" ana="#concepts[15]" resp="#paper" cert="0.99">human working memory<term>human working memory</term></span>
      <span xml:id="t48" from="#a17" to="#a18" type="concepts" ana="#concepts[16]" resp="#paper" cert="0.99">functions<term>functions</term></span>
      <span xml:id="t49" from="#a19" to="#a20" type="concepts" ana="#concepts[17]" resp="#paper" cert="0.99">names<term>names</term></span>
      <span xml:id="t50" from="#a21" to="#a22" type="concepts" ana="#concepts[18]" resp="#paper" cert="0.99">code style and formatting<term>code style and formatting</term></span>
      <span xml:id="t51" from="#a23" to="#a24" type="concepts" ana="#concepts[19]" resp="#paper" cert="0.99">repetition of computational tasks<term>repetition of computational tasks</term></span>
      <span xml:id="t52" from="#a25" to="#a26" type="concepts" ana="#concepts[20]" resp="#paper" cert="0.99">recent commands<term>recent commands</term></span>
      <span xml:id="t53" from="#a27" to="#a28" type="concepts" ana="#concepts[21]" resp="#paper" cert="0.99">script<term>script</term></span>
      <span xml:id="t54" from="#a27" to="#a28" type="concepts" ana="#concepts[22]" resp="#paper" cert="0.99">workflow management tool<term>workflow management tool</term></span>
      <span xml:id="t55" from="#a27" to="#a28" type="concepts" ana="#concepts[23]" resp="#paper" cert="0.99">dependencies between files<term>dependencies between files</term></span>
      <span xml:id="t56" from="#a29" to="#a30" type="concepts" ana="#concepts[24]" resp="#paper" cert="0.99">build tool<term>build tool</term></span>
      <span xml:id="t57" from="#a31" to="#a33" type="concepts" ana="#concepts[25]" resp="#paper" cert="0.99">provenance of data<term>provenance of data</term></span>
      <span xml:id="t58" from="#a31" to="#a33" type="concepts" ana="#concepts[26]" resp="#paper" cert="0.99">unique identifiers and version numbers<term>unique identifiers and version numbers</term></span>
      <span xml:id="t59" from="#a31" to="#a33" type="concepts" ana="#concepts[27]" resp="#paper" cert="0.99">values of parameters<term>values of parameters</term></span>
      <span xml:id="t60" from="#a34" to="#a35" type="concepts" ana="#concepts[28]" resp="#paper" cert="0.99">scientific programmers<term>scientific programmers</term></span>
      <span xml:id="t61" from="#a34" to="#a35" type="concepts" ana="#concepts[29]" resp="#paper" cert="0.99">traditional commercial software developers<term>traditional commercial software developers</term></span>
      <span xml:id="t62" from="#a36" to="#a37" type="concepts" ana="#concepts[30]" resp="#paper" cert="0.99">small steps with frequent feedback and course correction<term>small steps with frequent feedback and course correction</term></span>
      <span xml:id="t63" from="#a36" to="#a37" type="concepts" ana="#concepts[31]" resp="#paper" cert="0.99">agile development<term>agile development</term></span>
      <span xml:id="t64" from="#a40" to="#a41" type="concepts" ana="#concepts[32]" resp="#paper" cert="0.99">version control system<term>version control system</term></span>
      <span xml:id="t65" from="#a40" to="#a41" type="concepts" ana="#concepts[33]" resp="#paper" cert="0.99">VCS<term>VCS</term></span>
      <span xml:id="t66" from="#a40" to="#a41" type="concepts" ana="#concepts[34]" resp="#paper" cert="0.99">snapshots of a project&#x27;s files<term>snapshots of a project&#x27;s files</term></span>
      <span xml:id="t67" from="#a40" to="#a41" type="concepts" ana="#concepts[35]" resp="#paper" cert="0.99">repository<term>repository</term></span>
      <span xml:id="t68" from="#a40" to="#a41" type="concepts" ana="#concepts[36]" resp="#paper" cert="0.99">working copy<term>working copy</term></span>
      <span xml:id="t69" from="#a42" to="#a43" type="concepts" ana="#concepts[37]" resp="#paper" cert="0.99">conflicts<term>conflicts</term></span>
      <span xml:id="t70" from="#a42" to="#a43" type="concepts" ana="#concepts[38]" resp="#paper" cert="0.99">entire history of those files<term>entire history of those files</term></span>
      <span xml:id="t71" from="#a44" to="#a45" type="concepts" ana="#concepts[39]" resp="#paper" cert="0.99">everything that has been created manually<term>everything that has been created manually</term></span>
      <span xml:id="t72" from="#a46" to="#a47" type="concepts" ana="#concepts[40]" resp="#paper" cert="0.99">DRY Principle<term>DRY Principle</term></span>
      <span xml:id="t73" from="#a48" to="#a49" type="concepts" ana="#concepts[41]" resp="#paper" cert="0.99">single authoritative representation<term>single authoritative representation</term></span>
      <span xml:id="t74" from="#a50" to="#a51" type="concepts" ana="#concepts[42]" resp="#paper" cert="0.99">code clones<term>code clones</term></span>
      <span xml:id="t75" from="#a50" to="#a51" type="concepts" ana="#concepts[43]" resp="#paper" cert="0.99">modularize code<term>modularize code</term></span>
      <span xml:id="t76" from="#a52" to="#a53" type="concepts" ana="#concepts[44]" resp="#paper" cert="0.99">re-use code<term>re-use code</term></span>
      <span xml:id="t77" from="#a52" to="#a53" type="concepts" ana="#concepts[45]" resp="#paper" cert="0.99">established library or package<term>established library or package</term></span>
      <span xml:id="t78" from="#a56" to="#a57" type="concepts" ana="#concepts[46]" resp="#paper" cert="0.99">defensive programming<term>defensive programming</term></span>
      <span xml:id="t79" from="#a56" to="#a57" type="concepts" ana="#concepts[47]" resp="#paper" cert="0.99">assertion<term>assertion</term></span>
      <span xml:id="t80" from="#a56" to="#a57" type="concepts" ana="#concepts[48]" resp="#paper" cert="0.99">statement<term>statement</term></span>
      <span xml:id="t81" from="#a58" to="#a59" type="concepts" ana="#concepts[49]" resp="#paper" cert="0.99">executable documentation<term>executable documentation</term></span>
      <span xml:id="t82" from="#a60" to="#a61" type="concepts" ana="#concepts[50]" resp="#paper" cert="0.99">automated testing<term>automated testing</term></span>
      <span xml:id="t83" from="#a60" to="#a61" type="concepts" ana="#concepts[51]" resp="#paper" cert="0.99">unit tests<term>unit tests</term></span>
      <span xml:id="t84" from="#a60" to="#a61" type="concepts" ana="#concepts[52]" resp="#paper" cert="0.99">integration tests<term>integration tests</term></span>
      <span xml:id="t85" from="#a60" to="#a61" type="concepts" ana="#concepts[53]" resp="#paper" cert="0.99">regression tests<term>regression tests</term></span>
      <span xml:id="t86" from="#a60" to="#a61" type="concepts" ana="#concepts[54]" resp="#paper" cert="0.99">unit testing library<term>unit testing library</term></span>
      <span xml:id="t87" from="#a62" to="#a63" type="concepts" ana="#concepts[55]" resp="#paper" cert="0.99">bugs<term>bugs</term></span>
      <span xml:id="t88" from="#a62" to="#a63" type="concepts" ana="#concepts[56]" resp="#paper" cert="0.99">test cases<term>test cases</term></span>
      <span xml:id="t89" from="#a62" to="#a63" type="concepts" ana="#concepts[57]" resp="#paper" cert="0.99">testable<term>testable</term></span>
      <span xml:id="t90" from="#a64" to="#a65" type="concepts" ana="#concepts[58]" resp="#paper" cert="0.99">symbolic debugger<term>symbolic debugger</term></span>
      <span xml:id="t91" from="#a66" to="#a67" type="concepts" ana="#concepts[59]" resp="#paper" cert="0.99">performance bottlenecks<term>performance bottlenecks</term></span>
      <span xml:id="t92" from="#a66" to="#a67" type="concepts" ana="#concepts[60]" resp="#paper" cert="0.99">profiler<term>profiler</term></span>
      <span xml:id="t93" from="#a68" to="#a69" type="concepts" ana="#concepts[61]" resp="#paper" cert="0.99">highest-level language possible<term>highest-level language possible</term></span>
      <span xml:id="t94" from="#a68" to="#a69" type="concepts" ana="#concepts[62]" resp="#paper" cert="0.99">low-level languages<term>low-level languages</term></span>
      <span xml:id="t95" from="#a70" to="#a71" type="concepts" ana="#concepts[63]" resp="#paper" cert="0.99">rapid prototyping<term>rapid prototyping</term></span>
      <span xml:id="t96" from="#a70" to="#a71" type="concepts" ana="#concepts[64]" resp="#paper" cert="0.99">test oracle<term>test oracle</term></span>
      <span xml:id="t97" from="#a72" to="#a73" type="concepts" ana="#concepts[65]" resp="#paper" cert="0.99">good documentation<term>good documentation</term></span>
      <span xml:id="t98" from="#a72" to="#a73" type="concepts" ana="#concepts[66]" resp="#paper" cert="0.99">maintenance costs<term>maintenance costs</term></span>
      <span xml:id="t99" from="#a72" to="#a73" type="concepts" ana="#concepts[67]" resp="#paper" cert="0.99">interfaces and reasons<term>interfaces and reasons</term></span>
      <span xml:id="t100" from="#a72" to="#a73" type="concepts" ana="#concepts[68]" resp="#paper" cert="0.99">implementations<term>implementations</term></span>
      <span xml:id="t101" from="#a74" to="#a75" type="concepts" ana="#concepts[69]" resp="#paper" cert="0.99">refactor code<term>refactor code</term></span>
      <span xml:id="t102" from="#a76" to="#a77" type="concepts" ana="#concepts[70]" resp="#paper" cert="0.99">reference documentation<term>reference documentation</term></span>
      <span xml:id="t103" from="#a78" to="#a79" type="concepts" ana="#concepts[71]" resp="#paper" cert="0.99">documentation generator<term>documentation generator</term></span>
      <span xml:id="t104" from="#a78" to="#a79" type="concepts" ana="#concepts[72]" resp="#paper" cert="0.99">literate programming<term>literate programming</term></span>
      <span xml:id="t105" from="#a80" to="#a81" type="concepts" ana="#concepts[73]" resp="#paper" cert="0.99">code reviews<term>code reviews</term></span>
      <span xml:id="t106" from="#a80" to="#a81" type="concepts" ana="#concepts[74]" resp="#paper" cert="0.99">source code<term>source code</term></span>
      <span xml:id="t107" from="#a82" to="#a83" type="concepts" ana="#concepts[75]" resp="#paper" cert="0.99">pre-merge code reviews<term>pre-merge code reviews</term></span>
      <span xml:id="t108" from="#a84" to="#a85" type="concepts" ana="#concepts[76]" resp="#paper" cert="0.99">pair programming<term>pair programming</term></span>
      <span xml:id="t109" from="#a84" to="#a85" type="concepts" ana="#concepts[77]" resp="#paper" cert="0.99">code review<term>code review</term></span>
      <span xml:id="t110" from="#a84" to="#a85" type="concepts" ana="#concepts[78]" resp="#paper" cert="0.99">driver<term>driver</term></span>
      <span xml:id="t111" from="#a84" to="#a85" type="concepts" ana="#concepts[79]" resp="#paper" cert="0.99">navigator<term>navigator</term></span>
      <span xml:id="t112" from="#a86" to="#a87" type="concepts" ana="#concepts[80]" resp="#paper" cert="0.99">issue tracking tool<term>issue tracking tool</term></span>
      <span xml:id="t113" from="#a86" to="#a87" type="concepts" ana="#concepts[81]" resp="#paper" cert="0.99">duplicated effort<term>duplicated effort</term></span>
      <span xml:id="t114" from="#a88" to="#a89" type="concepts" ana="#concepts[82]" resp="#paper" cert="0.99">reproducible computational research<term>reproducible computational research</term></span>
      <span xml:id="t115" from="#a90" to="#a91" type="concepts" ana="#concepts[83]" resp="#paper" cert="0.99">24 recommendations<term>24 recommendations</term></span>
      <span xml:id="t116" from="#a92" to="#a93" type="concepts" ana="#concepts[84]" resp="#paper" cert="0.99">time cost<term>time cost</term></span>
      <span xml:id="t117" from="#a94" to="#a95" type="concepts" ana="#concepts[85]" resp="#paper" cert="0.99">training<term>training</term></span>
      <span xml:id="t118" from="#a5" to="#a6" type="concepts" ana="#concepts[86]" resp="#paper" cert="0.99">primarily self-taught<term>primarily self-taught</term></span>
      <span xml:id="t119" from="#a5" to="#a6" type="concepts" ana="#concepts[87]" resp="#paper" cert="0.99">basic software development practices<term>basic software development practices</term></span>
      <span xml:id="t120" from="#a7" to="#a8" type="concepts" ana="#concepts[88]" resp="#paper" cert="0.99">how reliable their software is<term>how reliable their software is</term></span>
      <span xml:id="t121" from="#a31" to="#a32" type="concepts" ana="#concepts[89]" resp="#paper" cert="0.99">reproducibility<term>reproducibility</term></span>
      <span xml:id="t122" from="#a21" to="#a22" type="concepts" ana="#concepts[90]" resp="#paper" cert="0.99">readers make more mistakes<term>readers make more mistakes</term></span>
      <span xml:id="t123" from="#a54" to="#a55" type="concepts" ana="#concepts[91]" resp="#paper" cert="0.99">mistakes<term>mistakes</term></span>
      <span xml:id="t124" from="#a36" to="#a37" type="concepts" ana="#concepts[92]" resp="#paper" cert="0.99">requirements are constantly changing<term>requirements are constantly changing</term></span>
      <span xml:id="t125" from="#a38" to="#a39" type="concepts" ana="#concepts[93]" resp="#paper" cert="0.99">lost work<term>lost work</term></span>
      <span xml:id="t126" from="#a42" to="#a43" type="concepts" ana="#concepts[94]" resp="#paper" cert="0.99">provenance for both code and data<term>provenance for both code and data</term></span>
      <span xml:id="t127" from="#a46" to="#a47" type="concepts" ana="#concepts[95]" resp="#paper" cert="0.99">errors and inconsistencies<term>errors and inconsistencies</term></span>
      <span xml:id="t128" from="#a58" to="#a59" type="concepts" ana="#concepts[96]" resp="#paper" cert="0.99">debugging<term>debugging</term></span>
      <span xml:id="t129" from="#a62" to="#a63" type="concepts" ana="#concepts[97]" resp="#paper" cert="0.99">confidence that scientific code is operating properly<term>confidence that scientific code is operating properly</term></span>
      <span xml:id="t130" from="#a64" to="#a65" type="concepts" ana="#concepts[98]" resp="#paper" cert="0.99">witness what is going wrong directly<term>witness what is going wrong directly</term></span>
      <span xml:id="t131" from="#a74" to="#a75" type="concepts" ana="#concepts[99]" resp="#paper" cert="0.99">explaining how it works<term>explaining how it works</term></span>
      <span xml:id="t132" from="#a82" to="#a83" type="concepts" ana="#concepts[100]" resp="#paper" cert="0.99">shared version control repository<term>shared version control repository</term></span>
      <span xml:id="t133" from="#a84" to="#a85" type="concepts" ana="#concepts[101]" resp="#paper" cert="0.99">productivity<term>productivity</term></span>
      <span xml:id="t134" from="#a90" to="#a91" type="concepts" ana="#concepts[102]" resp="#paper" cert="0.99">advanced practices<term>advanced practices</term></span>
      <span xml:id="t135" from="#a92" to="#a93" type="concepts" ana="#concepts[103]" resp="#paper" cert="0.99">productivity of the programmers involved<term>productivity of the programmers involved</term></span>
      <span xml:id="t136" from="#a94" to="#a95" type="concepts" ana="#concepts[104]" resp="#paper" cert="0.99">adoption of these tools<term>adoption of these tools</term></span>
      <span xml:id="t137" from="#a7" to="#a8" type="unhoused_relations" ana="#unhoused_relations[0]" resp="#tagger" cert="0.99">software → experimental apparatus<note>Software is another kind of experimental apparatus.</note></span>
      <span xml:id="t138" from="#a27" to="#a28" type="unhoused_relations" ana="#unhoused_relations[1]" resp="#tagger" cert="0.99">script → program<note>There is no real difference between a script and a program.</note></span>
      <span xml:id="t139" from="#a56" to="#a57" type="unhoused_relations" ana="#unhoused_relations[2]" resp="#tagger" cert="0.99">assertion → statement<note>An assertion is simply a statement that something holds true at a particular point in a program.</note></span>
      <span xml:id="t140" from="#a84" to="#a85" type="unhoused_relations" ana="#unhoused_relations[3]" resp="#tagger" cert="0.99">pair programming → code review<note>Pair programming is an extreme form of code review.</note></span>
      <span xml:id="t141" from="#a5" to="#a6" type="unhoused_relations" ana="#unhoused_relations[4]" resp="#tagger" cert="0.99">primarily self-taught → basic software development practices<note>Most scientific programmers are self-taught and lack exposure to basic development practices.</note></span>
      <span xml:id="t142" from="#a7" to="#a8" type="unhoused_relations" ana="#unhoused_relations[5]" resp="#tagger" cert="0.99">how reliable their software is → central conclusions of published research<note>Unknown software reliability can lead to errors that affect central research conclusions.</note></span>
      <span xml:id="t143" from="#a11" to="#a12" type="unhoused_relations" ana="#unhoused_relations[6]" resp="#tagger" cert="0.99">best practices → error-free software development<note>No combination of the recommended practices guarantees efficient error-free development.</note></span>
      <span xml:id="t144" from="#a13" to="#a14" type="unhoused_relations" ana="#unhoused_relations[7]" resp="#tagger" cert="0.99">best practices → reproducible research<note>The described skills make reproducible research and open science easier to implement.</note></span>
      <span xml:id="t145" from="#a17" to="#a18" type="unhoused_relations" ana="#unhoused_relations[8]" resp="#tagger" cert="0.99">human working memory → functions<note>Limited working memory motivates breaking programs into single-task functions.</note></span>
      <span xml:id="t146" from="#a21" to="#a22" type="unhoused_relations" ana="#unhoused_relations[9]" resp="#tagger" cert="0.99">code style and formatting → readers make more mistakes<note>Inconsistent formatting makes code slower to read and causes more reader mistakes.</note></span>
      <span xml:id="t147" from="#a23" to="#a24" type="unhoused_relations" ana="#unhoused_relations[10]" resp="#tagger" cert="0.99">repetition of computational tasks → mistakes<note>Manual repetition wastes time and eventually produces mistakes.</note></span>
      <span xml:id="t148" from="#a29" to="#a30" type="unhoused_relations" ana="#unhoused_relations[11]" resp="#tagger" cert="0.99">build tool → dependencies between files<note>A build tool uses declared file dependencies to automate scientific workflows.</note></span>
      <span xml:id="t149" from="#a31" to="#a32" type="unhoused_relations" ana="#unhoused_relations[12]" resp="#tagger" cert="0.99">provenance of data → reproducibility<note>Machine-readable provenance records everything needed to recreate output.</note></span>
      <span xml:id="t150" from="#a36" to="#a37" type="unhoused_relations" ana="#unhoused_relations[13]" resp="#tagger" cert="0.99">small steps with frequent feedback and course correction → requirements are constantly changing<note>Small iterative steps accommodate changing scientific requirements.</note></span>
      <span xml:id="t151" from="#a38" to="#a39" type="unhoused_relations" ana="#unhoused_relations[14]" resp="#tagger" cert="0.99">version control system → lost work<note>Version control replaces fragile copying practices that can cause confusion and lost work.</note></span>
      <span xml:id="t152" from="#a42" to="#a43" type="unhoused_relations" ana="#unhoused_relations[15]" resp="#tagger" cert="0.99">version control system → provenance for both code and data<note>Stored histories and metadata provide provenance for code and data.</note></span>
      <span xml:id="t153" from="#a44" to="#a45" type="unhoused_relations" ana="#unhoused_relations[16]" resp="#tagger" cert="0.99">everything that has been created manually → version control system<note>Reproducibility is maximized when all manually created materials are version controlled.</note></span>
      <span xml:id="t154" from="#a46" to="#a47" type="unhoused_relations" ana="#unhoused_relations[17]" resp="#tagger" cert="0.99">DRY Principle → errors and inconsistencies<note>Avoiding repeated representations reduces the chance of update errors and inconsistencies.</note></span>
      <span xml:id="t155" from="#a50" to="#a51" type="unhoused_relations" ana="#unhoused_relations[18]" resp="#tagger" cert="0.99">modularize code → code clones<note>Modularization avoids code clones and lets fixes take effect everywhere.</note></span>
      <span xml:id="t156" from="#a52" to="#a53" type="unhoused_relations" ana="#unhoused_relations[19]" resp="#tagger" cert="0.99">re-use code → established library or package<note>Scientific programmers should use established packages for solved problems rather than rewrite them.</note></span>
      <span xml:id="t157" from="#a54" to="#a55" type="unhoused_relations" ana="#unhoused_relations[20]" resp="#tagger" cert="0.99">defensive programming → mistakes<note>Assertions and tests form complementary defenses because no single practice catches every mistake.</note></span>
      <span xml:id="t158" from="#a58" to="#a59" type="unhoused_relations" ana="#unhoused_relations[21]" resp="#tagger" cert="0.99">assertion → debugging<note>An assertion halts a failing program immediately and simplifies debugging.</note></span>
      <span xml:id="t159" from="#a62" to="#a63" type="unhoused_relations" ana="#unhoused_relations[22]" resp="#tagger" cert="0.99">automated testing → confidence that scientific code is operating properly<note>Combined tests improve confidence that code and results are valid.</note></span>
      <span xml:id="t160" from="#a64" to="#a65" type="unhoused_relations" ana="#unhoused_relations[23]" resp="#tagger" cert="0.99">symbolic debugger → witness what is going wrong directly<note>A debugger exposes execution directly rather than requiring inference from logs.</note></span>
      <span xml:id="t161" from="#a66" to="#a67" type="unhoused_relations" ana="#unhoused_relations[24]" resp="#tagger" cert="0.99">profiler → performance bottlenecks<note>A profiler is used to identify bottlenecks only after correctness and need are established.</note></span>
      <span xml:id="t162" from="#a68" to="#a69" type="unhoused_relations" ana="#unhoused_relations[25]" resp="#tagger" cert="0.99">highest-level language possible → scientists&#x27; productivity<note>Higher-level languages increase productivity because equivalent tasks require fewer lines of code.</note></span>
      <span xml:id="t163" from="#a70" to="#a71" type="unhoused_relations" ana="#unhoused_relations[26]" resp="#tagger" cert="0.99">rapid prototyping → test oracle<note>A high-level prototype can serve as a test oracle for a low-level reimplementation.</note></span>
      <span xml:id="t164" from="#a72" to="#a73" type="unhoused_relations" ana="#unhoused_relations[27]" resp="#tagger" cert="0.99">good documentation → maintenance costs<note>Good documentation improves reuse and lowers software maintenance costs.</note></span>
      <span xml:id="t165" from="#a72" to="#a73" type="unhoused_relations" ana="#unhoused_relations[28]" resp="#tagger" cert="0.99">interfaces and reasons → implementations<note>Documentation should cover interfaces and reasons rather than implementation mechanics.</note></span>
      <span xml:id="t166" from="#a74" to="#a75" type="unhoused_relations" ana="#unhoused_relations[29]" resp="#tagger" cert="0.99">refactor code → explaining how it works<note>Complex code should be refactored instead of explained in a long implementation description.</note></span>
      <span xml:id="t167" from="#a76" to="#a77" type="unhoused_relations" ana="#unhoused_relations[30]" resp="#tagger" cert="0.99">reference documentation → software<note>Embedding reference documentation in software increases the chance it changes with the code.</note></span>
      <span xml:id="t168" from="#a80" to="#a81" type="unhoused_relations" ana="#unhoused_relations[31]" resp="#tagger" cert="0.99">code reviews → bugs<note>Code reviews eliminate bugs, improve readability, and spread knowledge and practice.</note></span>
      <span xml:id="t169" from="#a82" to="#a83" type="unhoused_relations" ana="#unhoused_relations[32]" resp="#tagger" cert="0.99">pre-merge code reviews → shared version control repository<note>Requiring review before merge prevents review from disappearing in practice.</note></span>
      <span xml:id="t170" from="#a84" to="#a85" type="unhoused_relations" ana="#unhoused_relations[33]" resp="#tagger" cert="0.99">pair programming → productivity<note>Studies report productivity improvement from pair programming, but many programmers find it intrusive.</note></span>
      <span xml:id="t171" from="#a86" to="#a87" type="unhoused_relations" ana="#unhoused_relations[34]" resp="#tagger" cert="0.99">issue tracking tool → duplicated effort<note>Issue tracking helps teams avoid duplicated effort and dropped tasks.</note></span>
      <span xml:id="t172" from="#a88" to="#a89" type="unhoused_relations" ana="#unhoused_relations[35]" resp="#tagger" cert="0.99">best practices → reproducible computational research<note>Readable, tested, version-controlled software is presented as a prerequisite for reproducible computational research.</note></span>
      <span xml:id="t173" from="#a90" to="#a91" type="unhoused_relations" ana="#unhoused_relations[36]" resp="#tagger" cert="0.99">24 recommendations → advanced practices<note>The twenty-four recommendations are a beginning that leads toward more advanced practice.</note></span>
      <span xml:id="t174" from="#a92" to="#a93" type="unhoused_relations" ana="#unhoused_relations[37]" resp="#tagger" cert="0.99">time cost → productivity of the programmers involved<note>The time cost of adopting the practices is almost immediately offset by productivity gains.</note></span>
      <span xml:id="t175" from="#a94" to="#a95" type="unhoused_relations" ana="#unhoused_relations[38]" resp="#tagger" cert="0.99">training → adoption of these tools<note>Tutorials, workshops, and classes have proven effective at driving adoption.</note></span>
      <span xml:id="t176" from="#a7" to="#a8" type="senses" ana="#senses[0]" resp="#tagger" cert="0.99">software - a kind of experimental apparatus that requires validation and careful use</span>
      <span xml:id="t177" from="#a27" to="#a28" type="senses" ana="#senses[1]" resp="#tagger" cert="0.99">script - a command file with no substantive difference from a program</span>
      <span xml:id="t178" from="#a31" to="#a33" type="senses" ana="#senses[2]" resp="#tagger" cert="0.99">provenance of data - machine-readable identifiers, versions, parameters, and programs needed to recreate output</span>
      <span xml:id="t179" from="#a40" to="#a41" type="senses" ana="#senses[3]" resp="#tagger" cert="0.99">VCS - a version control system storing snapshots and project history in repositories</span>
      <span xml:id="t180" from="#a48" to="#a49" type="senses" ana="#senses[4]" resp="#tagger" cert="0.99">DRY Principle - one authoritative representation for each datum and reusable rather than copied code</span>
      <span xml:id="t181" from="#a56" to="#a57" type="senses" ana="#senses[5]" resp="#tagger" cert="0.99">assertion - an executable statement that a condition holds at a point in a program</span>
      <span xml:id="t182" from="#a60" to="#a61" type="senses" ana="#senses[6]" resp="#tagger" cert="0.99">automated testing - unit, integration, and regression checks rerun by a computer</span>
      <span xml:id="t183" from="#a64" to="#a65" type="senses" ana="#senses[7]" resp="#tagger" cert="0.99">symbolic debugger - an interactive program inspector exposing live execution state</span>
      <span xml:id="t184" from="#a84" to="#a85" type="senses" ana="#senses[8]" resp="#tagger" cert="0.99">pair programming - an extreme code-review form joining a code-writing driver and feedback-oriented navigator</span>
      <span xml:id="t185" from="#a88" to="#a89" type="senses" ana="#senses[9]" resp="#tagger" cert="0.99">reproducible computational research - results supported by software that is version controlled, readable, and tested</span>
      <span xml:id="t186" from="#a1" to="#a2" type="claim_relations" ana="#claim_relations[0]" resp="#tagger" cert="0.99">proposes → a research- and experience-based set of scientific software-development practices<note>note: The paper&#x27;s stated contribution.</note></span>
      <span xml:id="t187" from="#a7" to="#a8" type="claim_relations" ana="#claim_relations[1]" resp="#tagger" cert="0.99">argues → scientific software should be validated as carefully as physical experimental apparatus<note>note: The central scientific-accountability analogy.</note></span>
      <span xml:id="t188" from="#a15" to="#a16" type="claim_relations" ana="#claim_relations[2]" resp="#tagger" cert="0.99">recommends → programs designed for limited human working memory and reliable comprehension<note>note: The human-readable-program practice.</note></span>
      <span xml:id="t189" from="#a29" to="#a30" type="claim_relations" ana="#claim_relations[3]" resp="#tagger" cert="0.99">recommends → automated workflows with machine-readable provenance<note>note: The automation and provenance practice.</note></span>
      <span xml:id="t190" from="#a36" to="#a37" type="claim_relations" ana="#claim_relations[4]" resp="#tagger" cert="0.99">supports → small incremental changes and version control under changing research requirements<note>note: The incremental-development practice.</note></span>
      <span xml:id="t191" from="#a50" to="#a51" type="claim_relations" ana="#claim_relations[5]" resp="#tagger" cert="0.99">recommends → single-source data, modular code, and reuse of established libraries<note>note: The DRY and reuse practice.</note></span>
      <span xml:id="t192" from="#a60" to="#a61" type="claim_relations" ana="#claim_relations[6]" resp="#tagger" cert="0.99">supports → layered defensive programming, automated tests, regression cases, and interactive debugging<note>note: The plan-for-mistakes practice.</note></span>
      <span xml:id="t193" from="#a66" to="#a67" type="claim_relations" ana="#claim_relations[7]" resp="#tagger" cert="0.99">recommends → correctness before profiler-guided optimization and low-level reimplementation<note>note: The optimization practice.</note></span>
      <span xml:id="t194" from="#a72" to="#a73" type="claim_relations" ana="#claim_relations[8]" resp="#tagger" cert="0.99">recommends → documentation of interfaces, reasons, design, and purpose rather than mechanics<note>note: The documentation practice.</note></span>
      <span xml:id="t195" from="#a80" to="#a81" type="claim_relations" ana="#claim_relations[9]" resp="#tagger" cert="0.99">supports → pre-merge review, selective pair programming, and issue tracking for collaboration<note>note: The collaboration practice.</note></span>
      <span xml:id="t196" from="#a9" to="#a10" type="concept_edges" ana="#concept_edges[0]" resp="#tagger" cert="0.99">computing errors —causes→ prominent retractions<note>the relation itself is separately evidenced · strength of the relation: 0.8 · note: Direct positive causal direction. · the relation stated: A cascading error from reused code caused several prominent retractions.</note><term>computing errors</term><term>prominent retractions</term></span>
      <span xml:id="t197" from="#a34" to="#a35" type="concept_edges" ana="#concept_edges[1]" resp="#tagger" cert="0.99">scientific programmers —distinct-from→ traditional commercial software developers<note>the relation itself is separately evidenced · strength of the relation: 1 · note: Explicit unlike contrast. · the relation stated: Scientific programmers differ from traditional commercial developers because their requirements are rarely fixed in advance.</note><term>scientific programmers</term><term>traditional commercial software developers</term></span>
      <span xml:id="t198" from="#a84" to="#a85" type="concept_edges" ana="#concept_edges[2]" resp="#tagger" cert="0.99">driver —distinct-from→ navigator<note>the relation itself is separately evidenced · strength of the relation: 1 · note: Explicit role contrast within one method. · the relation stated: The driver writes code whereas the navigator provides real-time feedback and tracks larger design issues.</note><term>driver</term><term>navigator</term></span>
    </spanGrp>
  </standOff>
  <text>
    <body>
        <p><anchor xml:id="a0"/> Best Practices for Scientific Computing</p>
        <p>Abstract</p>
        <p><anchor xml:id="a1"/>We describe a set of best practices for scientific software development, based on research and experience, that will improve scientists&#x27; productivity and the reliability of their software.<anchor xml:id="a2"/></p>
        <p>Introduction</p>
        <p>Scientists spend an increasing amount of time building and using software. However, most scientists are never taught how to do this efficiently. As a result, many are unaware of tools and practices that would allow them to write more reliable and maintainable code with less effort. We describe a set of best practices for scientific software development that have solid foundations in research and experience, and that improve scientists&#x27; productivity and the reliability of their software.</p>
        <p><anchor xml:id="a3"/>Software is as important to modern scientific research as telescopes and test tubes. From groups that work exclusively on computational problems, to traditional laboratory and field scientists, more and more of the daily operation of science revolves around developing new algorithms, managing and analyzing the large amounts of data that are generated in single research projects, combining disparate datasets to assess synthetic problems, and other computational tasks.<anchor xml:id="a4"/></p>
        <p><anchor xml:id="a5"/>Scientists typically develop their own software for these purposes because doing so requires substantial domain-specific knowledge. As a result, recent studies have found that scientists typically spend 30% or more of their time developing software [1] , [2] . However, 90% or more of them are primarily self-taught [1] , [2] , and therefore lack exposure to basic software development practices such as writing maintainable code, using version control and issue trackers, code reviews, unit testing, and task automation.<anchor xml:id="a6"/></p>
        <p><anchor xml:id="a7"/>We believe that software is just another kind of experimental apparatus [3] and should be built, checked, and used as carefully as any physical apparatus. However, while most scientists are careful to validate their laboratory and field equipment, most do not know how reliable their software is [4] , [5] . This can lead to serious errors impacting the central conclusions of published research [6] : recent high-profile retractions, technical comments, and corrections because of errors in computational methods include papers in Science [7] , [8] , PNAS [9] , the Journal of Molecular Biology [10] , Ecology Letters [11] , [12] , the Journal of Mammalogy [13] , Journal of the American College of Cardiology [14] , Hypertension [15] , and The American Economic Review [16] .<anchor xml:id="a8"/></p>
        <p><anchor xml:id="a9"/>In addition, because software is often used for more than a single project, and is often reused by other scientists, computing errors can have disproportionate impacts on the scientific process. This type of cascading impact caused several prominent retractions when an error from another group&#x27;s code was not discovered until after publication [6] . As with bench experiments, not everything must be done to the most exacting standards; however, scientists need to be aware of best practices both to improve their own approaches and for reviewing computational work by others.<anchor xml:id="a10"/></p>
        <p><anchor xml:id="a11"/>This paper describes a set of practices that are easy to adopt and have proven effective in many research settings. Our recommendations are based on several decades of collective experience both building scientific software and teaching computing to scientists [17] , [18] , reports from many other groups [19] –, guidelines for commercial and open source software development [26] ,, and on empirical studies of scientific computing [28] – [31] and software development in general (summarized in [32] ). None of these practices will guarantee efficient, error-free software development, but used in concert they will reduce the number of errors in scientific software, make it easier to reuse, and save the authors of the software time and effort that can used for focusing on the underlying scientific questions.<anchor xml:id="a12"/></p>
        <p><anchor xml:id="a13"/>Our practices are summarized in Box 1 ; labels in the main text such as “(1a)” refer to items in that summary. For reasons of space, we do not discuss the equally important (but independent) issues of reproducible research, publication and citation of code and data, and open science. We do believe, however, that all of these will be much easier to implement if scientists have the skills we describe.<anchor xml:id="a14"/></p>
        <p>Box 1. Summary of Best Practices</p>
        <p>Write programs for people, not computers. A program should not require its readers to hold more than a handful of facts in memory at once. Make names consistent, distinctive, and meaningful. Make code style and formatting consistent.</p>
        <p>Let the computer do the work. Make the computer repeat tasks. Save recent commands in a file for re-use. Use a build tool to automate workflows.</p>
        <p>Make incremental changes. Work in small steps with frequent feedback and course correction. Use a version control system. Put everything that has been created manually in version control.</p>
        <p>Don&#x27;t repeat yourself (or others). Every piece of data must have a single authoritative representation in the system. Modularize code rather than copying and pasting. Re-use code instead of rewriting it.</p>
        <p>Plan for mistakes. Add assertions to programs to check their operation. Use an off-the-shelf unit testing library. Turn bugs into test cases. Use a symbolic debugger.</p>
        <p>Optimize software only after it works correctly. Use a profiler to identify bottlenecks. Write code in the highest-level language possible.</p>
        <p>Document design and purpose, not mechanics. Document interfaces and reasons, not implementations. Refactor code in preference to explaining how it works. Embed the documentation for a piece of software in that software.</p>
        <p>Collaborate. Use pre-merge code reviews. Use pair programming when bringing someone new up to speed and when tackling particularly tricky problems. Use an issue tracking tool.</p>
        <p>Write Programs for People, Not Computers</p>
        <p><anchor xml:id="a15"/>Scientists writing software need to write code that both executes correctly and can be easily read and understood by other programmers (especially the author&#x27;s future self). If software cannot be easily read and understood, it is much more difficult to know that it is actually doing what it is intended to do. To be productive, software developers must therefore take several aspects of human cognition into account: in particular, that human working memory is limited, human pattern matching abilities are finely tuned, and human attention span is short [33] – [37] .<anchor xml:id="a16"/></p>
        <p><anchor xml:id="a17"/>First, a program should not require its readers to hold more than a handful of facts in memory at once (1a) . Human working memory can hold only a handful of items at a time, where each item is either a single fact or a “chunk” aggregating several facts [33] , [34] , so programs should limit the total number of items to be remembered to accomplish a task. The primary way to accomplish this is to break programs up into easily understood functions, each of which conducts a single, easily understood, task. This serves to make each piece of the program easier to understand in the same way that breaking up a scientific paper using sections and paragraphs makes it easier to read.<anchor xml:id="a18"/></p>
        <p><anchor xml:id="a19"/>Second, scientists should make names consistent, distinctive, and meaningful (1b) . For example, using non-descriptive names, like a and foo, or names that are very similar, like results and results2, is likely to cause confusion.<anchor xml:id="a20"/></p>
        <p><anchor xml:id="a21"/>Third, scientists should make code style and formatting consistent (1c) . If different parts of a scientific paper used different formatting and capitalization, it would make that paper more difficult to read. Likewise, if different parts of a program are indented differently, or if programmers mix CamelCaseNaming and pothole_case_naming, code takes longer to read and readers make more mistakes [35] , [36] .<anchor xml:id="a22"/></p>
        <p>Let the Computer Do the Work</p>
        <p><anchor xml:id="a23"/>Science often involves repetition of computational tasks such as processing large numbers of data files in the same way or regenerating figures each time new data are added to an existing analysis. Computers were invented to do these kinds of repetitive tasks but, even today, many scientists type the same commands in over and over again or click the same buttons repeatedly [17] . In addition to wasting time, sooner or later even the most careful researcher will lose focus while doing this and make mistakes.<anchor xml:id="a24"/></p>
        <p><anchor xml:id="a25"/>Scientists should therefore make the computer repeat tasks (2a) and save recent commands in a file for re-use (2b) . For example, most command-line tools have a “history” option that lets users display and re-execute recent commands, with minor edits to filenames or parameters. This is often cited as one reason command-line interfaces remain popular [38] , [39] : “do this again” saves time and reduces errors.<anchor xml:id="a26"/></p>
        <p><anchor xml:id="a27"/>A file containing commands for an interactive system is often called a script , though there is real no difference between this and a program. When these scripts are repeatedly used in the same way, or in combination, a workflow management tool can be used. The paradigmatic example is compiling and linking programs in languages such as Fortran, C++, Java, and C# [40] . The most widely used tool for this task is probably Make ( http://www.gnu.org/software/make ), although many alternatives are now available [41] . All of these allow people to express dependencies between files, i.e., to say that if A or B has changed, then C needs to be updated using a specific set of commands. These tools have been successfully adopted for scientific workflows as well [42] .<anchor xml:id="a28"/></p>
        <p><anchor xml:id="a29"/>To avoid errors and inefficiencies from repeating commands manually, we recommend that scientists use a build tool to automate workflows (2c) , e.g., specify the ways in which intermediate data files and final results depend on each other, and on the programs that create them, so that a single command will regenerate anything that needs to be regenerated.<anchor xml:id="a30"/></p>
        <p><anchor xml:id="a31"/>In order to maximize reproducibility, everything needed to re-create the output should be recorded automatically in a format that other programs can read. (Borrowing a term from archaeology and forensics, this is often called the provenance of data.) There have been some initiatives to automate the collection of this information, and standardize its format [43] , but it is already possible to record the following without additional tools:<anchor xml:id="a32"/></p>
        <p>unique identifiers and version numbers for raw data records (which scientists may need to create themselves);</p>
        <p>unique identifiers and version numbers for programs and libraries;</p>
        <p>the values of parameters used to generate any given output; and</p>
        <p>the names and version numbers of programs (however small) used to generate those outputs.<anchor xml:id="a33"/></p>
        <p>Make Incremental Changes</p>
        <p><anchor xml:id="a34"/>Unlike traditional commercial software developers, but very much like developers in open source projects or startups, scientific programmers usually don&#x27;t get their requirements from customers, and their requirements are rarely frozen [31] , [44] . In fact, scientists often can&#x27;t know what their programs should do next until the current version has produced some results. This challenges design approaches that rely on specifying requirements in advance.<anchor xml:id="a35"/></p>
        <p><anchor xml:id="a36"/>Programmers are most productive when they work in small steps with frequent feedback and course correction (3a) rather than trying to plan months or years of work in advance. While the details vary from team to team, these developers typically work in steps that are sized to be about an hour long, and these steps are often grouped in iterations that last roughly one week. This accommodates the cognitive constraints discussed in the first section, and acknowledges the reality that real-world requirements are constantly changing. The goal is to produce working (if incomplete) code after each iteration. While these practices have been around for decades, they gained prominence starting in the late 1990s under the banner of agile development [45] , [46] .<anchor xml:id="a37"/></p>
        <p><anchor xml:id="a38"/>Two of the biggest challenges scientists and other programmers face when working with code and data are keeping track of changes (and being able to revert them if things go wrong), and collaborating on a program or dataset [23] . Typical solutions are to email software to colleagues or to copy successive versions of it to a shared folder, e.g., Dropbox ( http://www.dropbox.com ). However, both approaches are fragile and can lead to confusion and lost work when important changes are overwritten or out-of-date files are used. It&#x27;s also difficult to find out which changes are in which versions or to say exactly how particular results were computed at a later date.<anchor xml:id="a39"/></p>
        <p><anchor xml:id="a40"/>The standard solution in both industry and open source is to use a version control system (3b) (VCS) [27] , [47] . A VCS stores snapshots of a project&#x27;s files in a repository (or a set of repositories). Programmers can modify their working copy of the project at will, then commit changes to the repository when they are satisfied with the results to share them with colleagues.<anchor xml:id="a41"/></p>
        <p><anchor xml:id="a42"/>Crucially, if several people have edited files simultaneously, the VCS highlights the differences and requires them to resolve any conflicts before accepting the changes. The VCS also stores the entire history of those files, allowing arbitrary versions to be retrieved and compared, together with metadata such as comments on what was changed and the author of the changes. All of this information can be extracted to provide provenance for both code and data.<anchor xml:id="a43"/></p>
        <p>Many good VCSes are open source and freely available, including Git ( http://git-scm.com ), Subversion ( http://subversion.apache.org ), and Mercurial ( http://mercurial.selenic.com ). Many free hosting services are available as well, with GitHub ( https://github.com ), BitBucket ( https://bitbucket.org ), SourceForge ( http://sourceforge.net ), and Google Code ( http://code.google.com ) being the most popular. As with coding style, the best one to use is almost always whatever your colleagues are already using [27] .</p>
        <p><anchor xml:id="a44"/>Reproducibility is maximized when scientists put everything that has been created manually in version control (3c) , including programs, original field observations, and the source files for papers. Automated output and intermediate files can be regenerated as needed. Binary files (e.g., images and audio clips) may be stored in version control, but it is often more sensible to use an archiving system for them, and store the metadata describing their contents in version control instead [48] .<anchor xml:id="a45"/></p>
        <p>Don&#x27;t Repeat Yourself (or Others)</p>
        <p><anchor xml:id="a46"/>Anything that is repeated in two or more places is more difficult to maintain. Every time a change or correction is made, multiple locations must be updated, which increases the chance of errors and inconsistencies. To avoid this, programmers follow the DRY Principle [49] , for “don&#x27;t repeat yourself,” which applies to both data and code.<anchor xml:id="a47"/></p>
        <p><anchor xml:id="a48"/>For data, this maxim holds that every piece of data must have a single authoritative representation in the system (4a) . Physical constants ought to be defined exactly once to ensure that the entire program is using the same value; raw data files should have a single canonical version, every geographic location from which data has been collected should be given an ID that can be used to look up its latitude and longitude, and so on.<anchor xml:id="a49"/></p>
        <p><anchor xml:id="a50"/>The DRY Principle applies to code at two scales. At small scales, modularize code rather than copying and pasting (4b) . Avoiding “code clones” has been shown to reduce error rates [50] : when a change is made or a bug is fixed, that change or fix takes effect everywhere, and people&#x27;s mental model of the program (i.e., their belief that “this one&#x27;s been fixed”) remains accurate. As a side effect, modularizing code allows people to remember its functionality as a single mental chunk, which in turn makes code easier to understand. Modularized code can also be more easily repurposed for other projects.<anchor xml:id="a51"/></p>
        <p><anchor xml:id="a52"/>At larger scales, it is vital that scientific programmers re-use code instead of rewriting it (4c) . Tens of millions of lines of high-quality open source software are freely available on the web, and at least as much is available commercially. It is typically better to find an established library or package that solves a problem than to attempt to write one&#x27;s own routines for well established problems (e.g., numerical integration, matrix inversions, etc.).<anchor xml:id="a53"/></p>
        <p>Plan for Mistakes</p>
        <p><anchor xml:id="a54"/>Mistakes are inevitable, so verifying and maintaining the validity of code over time is immensely challenging [51] . While no single practice has been shown to catch or prevent all mistakes, several are very effective when used in combination [47] , [52] , [53] .<anchor xml:id="a55"/></p>
        <p><anchor xml:id="a56"/>The first line of defense is defensive programming . Experienced programmers add assertions to programs to check their operation (5a) because experience has taught them that everyone (including their future self) makes mistakes. An assertion is simply a statement that something holds true at a particular point in a program; as the example below shows, assertions can be used to ensure that inputs are valid, outputs are consistent, and so on.<anchor xml:id="a57"/></p>
        <p><anchor xml:id="a58"/>Assertions can make up a sizeable fraction of the code in well-written applications, just as tools for calibrating scientific instruments can make up a sizeable fraction of the equipment in a lab. These assertions serve two purposes. First, they ensure that if something does go wrong, the program will halt immediately, which simplifies debugging. Second, assertions are executable documentation , i.e., they explain the program as well as checking its behavior. This makes them more useful in many cases than comments since the reader can be sure that they are accurate and up to date.<anchor xml:id="a59"/></p>
        <p><anchor xml:id="a60"/>The second layer of defense is automated testing . Automated tests can check to make sure that a single unit of code is returning correct results ( unit tests ), that pieces of code work correctly when combined ( integration tests ), and that the behavior of a program doesn&#x27;t change when the details are modified ( regression tests ). These tests are conducted by the computer, so that they are easy to rerun every time the program is modified. Creating and managing tests is easier if programmers use an off-the-shelf unit testing library (5b) to initialize inputs, run tests, and report their results in a uniform way. These libraries are available for all major programming languages including those commonly used in scientific computing [54] – [56] .<anchor xml:id="a61"/></p>
        <p><anchor xml:id="a62"/>Tests check to see whether the code matches the researcher&#x27;s expectations of its behavior, which depends on the researcher&#x27;s understanding of the problem at hand [57] – [59] . For example, in scientific computing, tests are often conducted by comparing output to simplified cases, experimental data, or the results of earlier programs that are trusted. Another approach for generating tests is to turn bugs into test cases (5c) by writing tests that trigger a bug that has been found in the code and (once fixed) will prevent the bug from reappearing unnoticed. In combination these kinds of testing can improve our confidence that scientific code is operating properly and that the results it produces are valid. An additional benefit of testing is that it encourages programmers to design and build code that is testable (i.e., self-contained functions and classes that can run more or less independently of one another). Code that is designed this way is also easier to understand and more reusable.<anchor xml:id="a63"/></p>
        <p><anchor xml:id="a64"/>No matter how good one&#x27;s computational practice is, reasonably complex code will always initially contain bugs. Fixing bugs that have been identified is often easier if you use a symbolic debugger (5d) to track them down. A better name for this kind of tool would be “interactive program inspector” since a debugger allows users to pause a program at any line (or when some condition is true), inspect the values of variables, and walk up and down active function calls to figure out why things are behaving the way they are. Debuggers are usually more productive than adding and removing print statements or scrolling through hundreds of lines of log output [60] , because they allow the user to see exactly how the code is executing rather than just snapshots of state of the program at a few moments in time. In other words, the debugger allows the scientist to witness what is going wrong directly, rather than having to anticipate the error or infer the problem using indirect evidence.<anchor xml:id="a65"/></p>
        <p>Optimize Software Only after It Works Correctly</p>
        <p><anchor xml:id="a66"/>Today&#x27;s computers and software are so complex that even experts find it hard to predict which parts of any particular program will be performance bottlenecks [61] . The most productive way to make code fast is therefore to make it work correctly, determine whether it&#x27;s actually worth speeding it up, and—in those cases where it is—to use a profiler to identify bottlenecks (6a) .<anchor xml:id="a67"/></p>
        <p><anchor xml:id="a68"/>This strategy also has interesting implications for choice of programming language. Research has confirmed that most programmers write roughly the same number of lines of code per unit time regardless of the language they use [62] . Since faster, lower level, languages require more lines of code to accomplish the same task, scientists are most productive when they write code in the highest-level language possible (6b) , and shift to low-level languages like C and Fortran only when they are sure the performance boost is needed. (Using higher-level languages also helps program comprehensibility, since such languages have, in a sense, “pre-chunked” the facts that programmers need to have in short-term memory.)<anchor xml:id="a69"/></p>
        <p><anchor xml:id="a70"/>Taking this approach allows more code to be written (and tested) in the same amount of time. Even when it is known before coding begins that a low-level language will ultimately be necessary, rapid prototyping in a high-level language helps programmers make and evaluate design decisions quickly. Programmers can also use a high-level prototype as a test oracle for a high-performance low-level reimplementation, i.e., compare the output of the optimized (and usually more complex) program against the output from its unoptimized (but usually simpler) predecessor in order to check its correctness.<anchor xml:id="a71"/></p>
        <p>Document Design and Purpose, Not Mechanics</p>
        <p><anchor xml:id="a72"/>In the same way that a well documented experimental protocol makes research methods easier to reproduce, good documentation helps people understand code. This makes the code more reusable and lowers maintenance costs [47] . As a result, code that is well documented makes it easier to transition when the graduate students and postdocs who have been writing code in a lab transition to the next career phase. Reference documentation and descriptions of design decisions are key for improving the understandability of code. However, inline documentation that recapitulates code is not useful. Therefore we recommend that scientific programmers document interfaces and reasons, not implementations (7a) . For example, a clear description like this at the beginning of a function that describes what it does and its inputs and outputs is useful:<anchor xml:id="a73"/></p>
        <p>In contrast, the comment in the code fragment below does nothing to aid comprehension:</p>
        <p><anchor xml:id="a74"/>If a substantial description of the implementation of a piece of software is needed, it is better to refactor code in preference to explaining how it works (7b) , i.e., rather than write a paragraph to explain a complex piece of code, reorganize the code itself so that it doesn&#x27;t need such an explanation. This may not always be possible—some pieces of code are intrinsically difficult—but the onus should always be on the author to convince his or her peers of that.<anchor xml:id="a75"/></p>
        <p><anchor xml:id="a76"/>The best way to create and maintain reference documentation is to embed the documentation for a piece of software in that software (7c) . Doing this increases the probability that when programmers change the code, they will update the documentation at the same time.<anchor xml:id="a77"/></p>
        <p><anchor xml:id="a78"/>Embedded documentation usually takes the form of specially-formatted and placed comments. Typically, a documentation generator such as Javadoc, Doxygen, or Sphinx extracts these comments and generates well-formatted web pages and other human-friendly documents ( http://en.wikipedia.org/wiki/Comparison_of_documentation_generators ). Alternatively, code can be embedded in a larger document that includes information about what the code is doing (i.e., literate programming). Common approaches to this include this use of knitr [63] and IPython Notebooks [64] .<anchor xml:id="a79"/></p>
        <p>Collaborate</p>
        <p><anchor xml:id="a80"/>In the same way that having manuscripts reviewed by other scientists can reduce errors and make research easier to understand, reviews of source code can eliminate bugs and improve readability. A large body of research has shown that code reviews are the most cost-effective way of finding bugs in code [65] , [66] . They are also a good way to spread knowledge and good practices around a team. In projects with shifting membership, such as most academic labs, code reviews help ensure that critical knowledge isn&#x27;t lost when a student or postdoc leaves the lab.<anchor xml:id="a81"/></p>
        <p><anchor xml:id="a82"/>Code can be reviewed either before or after it has been committed to a shared version control repository. Experience shows that if reviews don&#x27;t have to be done in order to get code into the repository, they will soon not be done at all [27] . We therefore recommend that projects use pre-merge code reviews (8a) .<anchor xml:id="a83"/></p>
        <p><anchor xml:id="a84"/>An extreme form of code review is pair programming , in which two developers sit together while writing code. One (the driver) actually writes the code; the other (the navigator) provides real-time feedback and is free to track larger issues of design and consistency. Several studies have found that pair programming improves productivity [67] , but many programmers find it intrusive. We therefore recommend that teams use pair programming when bringing someone new up to speed and when tackling particularly tricky problems (8b) .<anchor xml:id="a85"/></p>
        <p><anchor xml:id="a86"/>Once a team grows beyond a certain size, it becomes difficult to keep track of what needs to be reviewed, or of who&#x27;s doing what. Teams can avoid a lot of duplicated effort and dropped balls if they use an issue tracking tool (8c) to maintain a list of tasks to be performed and bugs to be fixed [68] . This helps avoid duplicated work and makes it easier for tasks to be transferred to different people. Free repository hosting services like GitHub include issue tracking tools, and many good standalone tools exist as well, such as Trac ( http://trac.edgewall.org ).<anchor xml:id="a87"/></p>
        <p>Conclusion</p>
        <p><anchor xml:id="a88"/>We have outlined a series of recommended best practices for scientific computing based on extensive research, as well as our collective experience. These practices can be applied to individual work as readily as group work; separately and together, they improve the productivity of scientific programming and the reliability of the resulting code, and therefore the speed with which we produce results and our confidence in them. They are also, we believe, prerequisites for reproducible computational research: if software is not version controlled, readable, and tested, the chances of its authors (much less anyone else) being able to re-create results are remote.<anchor xml:id="a89"/></p>
        <p><anchor xml:id="a90"/>Our 24 recommendations are a beginning, not an end. Individuals and groups who have incorporated them into their work will find links to more advanced practices at Software Carpentry ( http://software-carpentry.org ).<anchor xml:id="a91"/></p>
        <p><anchor xml:id="a92"/>Research suggests that the time cost of implementing these kinds of tools and approaches in scientific computing is almost immediately offset by the gains in productivity of the programmers involved [17] . Even so, the recommendations described above may seem intimidating to implement. Fortunately, the different practices reinforce and support one another, so the effort required is less than the sum of adding each component separately. Nevertheless, we do not recommend that research groups attempt to implement all of these recommendations at once, but instead suggest that these tools be introduced incrementally over a period of time.<anchor xml:id="a93"/></p>
        <p><anchor xml:id="a94"/>How to implement the recommended practices can be learned from many excellent tutorials available online or through workshops and classes organized by groups like Software Carpentry. This type of training has proven effective at driving adoption of these tools in scientific settings [17] , [69] .<anchor xml:id="a95"/></p>
        <p>For computing to achieve the level of rigor that is expected throughout other parts of science, it is necessary for scientists to begin to adopt the tools and approaches that are known to improve both the quality of software and the efficiency with which it is produced. To facilitate this adoption, universities and funding agencies need to support the training of scientists in the use of these tools and the investment of time and money in building better scientific software. Investment in these approaches by both individuals and institutions will improve our confidence in the results of computational science and will allow us to make more rapid progress on important scientific questions than would otherwise be possible.</p>
        <p>Acknowledgments</p>
        <p>We are grateful to Joel Adamson, Aron Ahmadia, Roscoe Bartlett, Erik Bray, Stephen Crouch, Michael Jackson, Justin Kitzes, Adam Obeng, Karthik Ram, Yoav Ram, and Tracy Teal for feedback on this paper.</p>
        <p>Funding Statement</p>
        <p>Neil Chue Hong was supported by the UK Engineering and Physical Sciences Research Council (EPSRC) Grant EP/H043160/1 for the UK Software Sustainability Institute. Ian M. Mitchell was supported by NSERC Discovery Grant #298211. Mark Plumbley was supported by EPSRC through a Leadership Fellowship (EP/G007144/1) and a grant (EP/H043101/1) for SoundSoftware.ac.uk. Ethan White was supported by a CAREER grant from the US National Science Foundation (DEB 0953694). Greg Wilson was supported by a grant from the Sloan Foundation. The funders had no role in study design, data collection and analysis, decision to publish, or preparation of the manuscript.</p>
        <p>References<anchor xml:id="a96"/></p>
    </body>
  </text>
</TEI>
