CINXE.COM

Chapter 15 R code | Bioconductor Packages: Development, Maintenance, and Peer Review

<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>Chapter 15 R code | Bioconductor Packages: Development, Maintenance, and Peer Review</title> <meta name="author" content="Kevin Rue-Albrecht"> <meta name="author" content="Daniela Cassol"> <meta name="author" content="Johannes Rainer"> <meta name="author" content="Lori Shepherd"> <meta name="description" content="Everyone has their own coding style and formats. There are however some best practice guidelines that Bioconductor reviewers will look for. can be a robust, fast and efficient programming language..."> <meta name="generator" content="bookdown 0.41 with bs4_book()"> <meta property="og:title" content="Chapter 15 R code | Bioconductor Packages: Development, Maintenance, and Peer Review"> <meta property="og:type" content="book"> <meta property="og:description" content="Everyone has their own coding style and formats. There are however some best practice guidelines that Bioconductor reviewers will look for. can be a robust, fast and efficient programming language..."> <meta name="twitter:card" content="summary"> <meta name="twitter:title" content="Chapter 15 R code | Bioconductor Packages: Development, Maintenance, and Peer Review"> <meta name="twitter:description" content="Everyone has their own coding style and formats. There are however some best practice guidelines that Bioconductor reviewers will look for. can be a robust, fast and efficient programming language..."> <!-- JS --><script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.6/clipboard.min.js" integrity="sha256-inc5kl9MA1hkeYUt+EC3BhlIgyp/2jDIyBLS6k3UxPI=" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/6.4.6/fuse.js" integrity="sha512-zv6Ywkjyktsohkbp9bb45V6tEMoWhzFzXis+LrMehmJZZSys19Yxf1dopHx7WzIKxr5tK2dVcYmaCk2uqdjF4A==" crossorigin="anonymous"></script><script src="https://kit.fontawesome.com/6ecbd6c532.js" crossorigin="anonymous"></script><script src="libs/jquery-3.6.0/jquery-3.6.0.min.js"></script><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link href="libs/bootstrap-4.6.0/bootstrap.min.css" rel="stylesheet"> <script src="libs/bootstrap-4.6.0/bootstrap.bundle.min.js"></script><script src="libs/bs3compat-0.8.0/transition.js"></script><script src="libs/bs3compat-0.8.0/tabs.js"></script><script src="libs/bs3compat-0.8.0/bs3compat.js"></script><link href="libs/bs4_book-1.0.0/bs4_book.css" rel="stylesheet"> <script src="libs/bs4_book-1.0.0/bs4_book.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/autocomplete.js/0.38.0/autocomplete.jquery.min.js" integrity="sha512-GU9ayf+66Xx2TmpxqJpliWbT5PiGYxpaG8rfnBEk1LL8l1KGkRShhngwdXK1UgqhAzWpZHSiYPc09/NwDQIGyg==" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js" integrity="sha512-5CYOlHXGh6QpOFA/TeTylKLWfB3ftPsde7AnmhuitiTX4K5SqCLBeKro6sPS8ilsz1Q4NRx3v8Ko2IBiszzdww==" crossorigin="anonymous"></script><!-- CSS --><style type="text/css"> div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} </style> </head> <body data-spy="scroll" data-target="#toc"> <div class="container-fluid"> <div class="row"> <header class="col-sm-12 col-lg-3 sidebar sidebar-book"><a class="sr-only sr-only-focusable" href="#content">Skip to main content</a> <div class="d-flex align-items-start justify-content-between"> <h1> <a href="index.html" title="">Bioconductor Packages: Development, Maintenance, and Peer Review</a> </h1> <button class="btn btn-outline-primary d-lg-none ml-2 mt-1" type="button" data-toggle="collapse" data-target="#main-nav" aria-expanded="true" aria-controls="main-nav"><i class="fas fa-bars"></i><span class="sr-only">Show table of contents</span></button> </div> <div id="main-nav" class="collapse-lg"> <form role="search"> <input id="search" class="form-control" type="search" placeholder="Search" aria-label="Search"> </form> <nav aria-label="Table of contents"><h2>Table of contents</h2> <ul class="book-toc list-unstyled"> <li><a class="" href="index.html">Welcome</a></li> <li class="book-part">Package Submissions</li> <li><a class="" href="submission-overview.html">Overview</a></li> <li><a class="" href="bioconductor-package-submissions.html"><span class="header-section-number">1</span> Bioconductor Package Submissions</a></li> <li class="book-part">Package Development Guidelines</li> <li><a class="" href="develop-overview.html">Overview</a></li> <li><a class="" href="package-name.html"><span class="header-section-number">2</span> Package name</a></li> <li><a class="" href="general.html"><span class="header-section-number">3</span> General Bioconductor Package Development</a></li> <li><a class="" href="important-bioconductor-package-development-features.html"><span class="header-section-number">4</span> Important Bioconductor Package Development Features</a></li> <li><a class="" href="readme.html"><span class="header-section-number">5</span> The README file</a></li> <li><a class="" href="description.html"><span class="header-section-number">6</span> The DESCRIPTION file</a></li> <li><a class="" href="namespace.html"><span class="header-section-number">7</span> The NAMESPACE file</a></li> <li><a class="" href="news.html"><span class="header-section-number">8</span> The NEWS file</a></li> <li><a class="" href="license.html"><span class="header-section-number">9</span> The LICENSE file</a></li> <li><a class="" href="citation.html"><span class="header-section-number">10</span> The CITATION file</a></li> <li><a class="" href="sysdep.html"><span class="header-section-number">11</span> The INSTALL file</a></li> <li><a class="" href="docs.html"><span class="header-section-number">12</span> Documentation</a></li> <li><a class="" href="data.html"><span class="header-section-number">13</span> Package data</a></li> <li><a class="" href="tests.html"><span class="header-section-number">14</span> Unit tests</a></li> <li><a class="active" href="r-code.html"><span class="header-section-number">15</span> R code</a></li> <li><a class="" href="other-than-Rcode.html"><span class="header-section-number">16</span> Fortran / C / C++ / Python / Third-Party Code</a></li> <li><a class="" href="shiny.html"><span class="header-section-number">17</span> Shiny apps</a></li> <li><a class="" href="non-software.html"><span class="header-section-number">18</span> Non-Software Packages</a></li> <li><a class="" href="gitignore.html"><span class="header-section-number">19</span> The .gitignore file</a></li> <li><a class="" href="conclusion.html"><span class="header-section-number">20</span> Conclusion</a></li> <li class="book-part">Bioconductor Package Maintenance</li> <li><a class="" href="package-maintenance.html">Overview</a></li> <li><a class="" href="git-version-control.html"><span class="header-section-number">21</span> Git Version Control</a></li> <li><a class="" href="versionnum.html"><span class="header-section-number">22</span> Version Numbering</a></li> <li><a class="" href="troubleshooting-build-report.html"><span class="header-section-number">23</span> Troubleshooting Build Report</a></li> <li><a class="" href="debugging-cc-code.html"><span class="header-section-number">24</span> Debugging C/C++ code</a></li> <li><a class="" href="deprecation.html"><span class="header-section-number">25</span> Deprecation Guidelines</a></li> <li><a class="" href="package-end-of-life-policy.html"><span class="header-section-number">26</span> Package End of Life Policy</a></li> <li><a class="" href="branch-rename-faqs.html"><span class="header-section-number">27</span> Branch Rename FAQs</a></li> <li class="book-part">Package Reviewer Resources</li> <li><a class="" href="reviewer-resources-overview.html">Overview</a></li> <li><a class="" href="review-expectation.html"><span class="header-section-number">28</span> Review Expectations</a></li> <li><a class="" href="reviewtools.html"><span class="header-section-number">29</span> Reviewer Resources and Tools</a></li> <li><a class="" href="review-volunteer-chapter.html"><span class="header-section-number">30</span> Volunteer to Review</a></li> <li class="book-part">Appendix</li> <li><a class="" href="use-devel.html"><span class="header-section-number">A</span> Using the ‘Devel’ Version of Bioconductor</a></li> <li><a class="" href="long-tests.html"><span class="header-section-number">B</span> Long Tests</a></li> <li><a class="" href="querying-web-resources.html"><span class="header-section-number">C</span> Querying Web Resources</a></li> <li><a class="" href="c-fortran.html"><span class="header-section-number">D</span> C and Fortran code</a></li> <li><a class="" href="cmavericks-best-practices.html"><span class="header-section-number">E</span> C++/Mavericks Best Practices</a></li> <li><a class="" href="man-links.html"><span class="header-section-number">F</span> Debug: Links in Rd files</a></li> <li><a class="" href="booknews.html"><span class="header-section-number">G</span> NEWS</a></li> </ul> <div class="book-extra"> <p><a id="book-repo" href="https://github.com/Bioconductor/pkgrevdocs">View book source <i class="fab fa-github"></i></a></p> </div> </nav> </div> </header><main class="col-sm-12 col-md-9 col-lg-7" id="content"><div id="r-code" class="section level1" number="15"> <h1> <span class="header-section-number">15</span> R code<a class="anchor" aria-label="anchor" href="#r-code"><i class="fas fa-link"></i></a> </h1> <p>Everyone has their own coding style and formats. There are however some best practice guidelines that <a href="https://bioconductor.org/about/package-reviewers/"><em>Bioconductor</em> reviewers</a> will look for.</p> <p><i class="fab fa-r-project"></i> can be a robust, fast and efficient programming language but often some coding practices result in less than ideal use of resources.</p> <p>This section will review some key points, suggestions, and best practices that will aid in the package review process and assist in making code more robust and efficient.</p> <div id="rcode-license" class="section level2" number="15.1"> <h2> <span class="header-section-number">15.1</span> License<a class="anchor" aria-label="anchor" href="#rcode-license"><i class="fas fa-link"></i></a> </h2> <p>Only contain code that can be distributed under the license specified (see also <a href="description.html#description-license">The DESCRIPTION file</a>).</p> </div> <div id="r-code-development" class="section level2" number="15.2"> <h2> <span class="header-section-number">15.2</span> R Code Development<a class="anchor" aria-label="anchor" href="#r-code-development"><i class="fas fa-link"></i></a> </h2> <div id="rcode-reuse" class="section level3" number="15.2.1"> <h3> <span class="header-section-number">15.2.1</span> Re-use of functionality, classes, and generics<a class="anchor" aria-label="anchor" href="#rcode-reuse"><i class="fas fa-link"></i></a> </h3> <p>Avoid re-implementing functionality or classes (see also <a href="description.html#depends-imports-suggests-enhances">The DESCRIPTION file</a>). Make use of appropriate existing packages (e.g., <em><a href="https://bioconductor.org/packages/3.21/biomaRt">biomaRt</a></em>, <em><a href="https://bioconductor.org/packages/3.21/AnnotationDbi">AnnotationDbi</a></em>, <em><a href="https://bioconductor.org/packages/3.21/Biostrings">Biostrings</a></em>, <em><a href="https://bioconductor.org/packages/3.21/GenomicRanges">GenomicRanges</a></em>) and classes (e.g., <em><a href="https://bioconductor.org/packages/3.21/SummarizedExperiment">SummarizedExperiment</a></em>, <em><a href="https://bioconductor.org/packages/3.21/Biobase">Biobase</a></em>::AnnotatedDataFrame, <em><a href="https://bioconductor.org/packages/3.21/GenomicRanges">GenomicRanges</a></em>:;GRanges, <em><a href="https://bioconductor.org/packages/3.21/Biostrings">Biostrings</a></em>::DNAStringSet) to avoid duplication of functionality available in other <a href="https://bioconductor.org"><em>Bioconductor</em></a> packages. See also <a href="important-bioconductor-package-development-features.html#reusebioc">Common Bioconductor Methods and Classes</a>.</p> <p>This encourages interoperability and simplifies your own package development. If a new representation is needed, see <a href="r-code.html#class-development">class development section</a>. In general, <a href="https://bioconductor.org"><em>Bioconductor</em></a> will insist on interoperability with <a href="important-bioconductor-package-development-features.html#commonclass">Common Classes</a> for acceptance.</p> <p>Developers should make an effort to re-use generics that fit the generic contract for the proposed class-method pair i.e., the behavior of the method aligns with the originally proposed behavior of the generic. Specifically, the behavior can be one where the return value is of the same class across methods. The method behavior can also be a performant conceptual transformation or procedure across classes as described by the generic. <em><a href="https://bioconductor.org/packages/3.21/BiocGenerics">BiocGenerics</a></em> lists commonly used generics in Bioconductor. One example of a generic and method implementation is that of the <code>rowSums</code> generic and the corresponding method within the <em><a href="https://bioconductor.org/packages/3.21/DelayedArray">DelayedArray</a></em> package. This generic contract returns a numeric vector of the same length as the rows and is adhered to across classes including the <code>DelayedMatrix</code> class. Re-using generics reduces the amount of new generics by consolidating existing operations and avoids the mistake of introducing a “new” generic with the same name. Generic name collisions may mask or be masked by previous definitions in ways that are hard to diagnose. More recently, we recommend the use of <em><a href="https://CRAN.R-project.org/package=conflicted">conflicted</a></em> to identify namespace collisions.</p> <p>If there are problems, e.g., in performance or parsing your particular file type, ask for input from other developers on the <a href="https://stat.ethz.ch/mailman/listinfo/bioc-devel">bioc-devel</a> mailing list. Common disadvantages to ‘implementing your own’ are the introduction of non-standard data representations (e.g., neglecting to translate coordinate systems of file formats to Bioconductor objects) and user bewilderment. Therefore, in such case, we recommend to use standard file format classes inheriting from <em><a href="https://bioconductor.org/packages/3.21/BiocIO">BiocIO</a></em>’s <code>BiocFile</code> class in packages such as <em><a href="https://bioconductor.org/packages/3.21/rtracklayer">rtracklayer</a></em> and <em><a href="https://bioconductor.org/packages/3.21/BiocIO">BiocIO</a></em>.</p> </div> <div id="naming-functions" class="section level3" number="15.2.2"> <h3> <span class="header-section-number">15.2.2</span> Naming of packages, functions, and classes<a class="anchor" aria-label="anchor" href="#naming-functions"><i class="fas fa-link"></i></a> </h3> <p>See section on <a href="package-name.html#package-name">package naming</a>. The concepts there should also apply to function names, class names, etc.</p> <p>Avoid names that:</p> <ul> <li>Are easily confused with existing package names, function names, class names.</li> <li>Imply a temporal (e.g. <code>ExistingPackage2</code>) or qualitative (e.g. <code>ExistingPackagePlus</code>) relationship.</li> <li>Suggest hate speech, slurs or profanity, either implicitly or explicitly.</li> <li>Invoke or refer to any historical, ethical, or political contexts.</li> <li>Reference well known people, characters, brands, places or icons.</li> </ul> </div> <div id="rcode-method-development" class="section level3" number="15.2.3"> <h3> <span class="header-section-number">15.2.3</span> Methods development<a class="anchor" aria-label="anchor" href="#rcode-method-development"><i class="fas fa-link"></i></a> </h3> <p>We encourage maintainers to only create new methods for classes exported within their packages. We discourage the generation of methods for external classes, i.e., classes outside of the package <a href="namespace.html#namespace"><code>NAMESPACE</code></a>. This can potentially cause method name collisions (i.e., where two methods defined on the same object but in different packages) and pollute the methods environment for those external classes. New methods for established classes can also cause confusion among users given that the new method and class definition are in separate packages.</p> </div> <div id="rcode-file-names" class="section level3" number="15.2.4"> <h3> <span class="header-section-number">15.2.4</span> File names<a class="anchor" aria-label="anchor" href="#rcode-file-names"><i class="fas fa-link"></i></a> </h3> <ul> <li>Filename extension for R code should be ‘.R’. Use the prefix ‘methods-’ for S4 class methods, e.g., ‘methods-coverage.R’. Generic definitions can be listed in a single file, ‘AllGenerics.R’, and class definitions in ‘AllClasses.R’.</li> <li>Filename extension for man pages should be ‘.Rd’.</li> </ul> </div> <div id="class-development" class="section level3" number="15.2.5"> <h3> <span class="header-section-number">15.2.5</span> Class development<a class="anchor" aria-label="anchor" href="#class-development"><i class="fas fa-link"></i></a> </h3> <p>Remember to <strong>re-use</strong> <a href="important-bioconductor-package-development-features.html#reusebioc">common <em>Bioconductor</em> methods and classes</a> before implementing new representations. This encourages interoperability and simplifies your own package development.</p> <div id="class-names" class="section level4" number="15.2.5.1"> <h4> <span class="header-section-number">15.2.5.1</span> Class Names<a class="anchor" aria-label="anchor" href="#class-names"><i class="fas fa-link"></i></a> </h4> <p>Use CamelCaps: initial upper case, then alternate case between words.</p> </div> <div id="class-design" class="section level4" number="15.2.5.2"> <h4> <span class="header-section-number">15.2.5.2</span> Class design<a class="anchor" aria-label="anchor" href="#class-design"><i class="fas fa-link"></i></a> </h4> <p><em>Bioconductor</em> prefers the use of S4 classes over S3 class. Please use the S4 representation for designing new classes. Again, we can not emphasize enough to reuse existing class structure if at all possible. If an existing class structure is not sufficient, it is also encouraged to look at extending or containing an <a href="important-bioconductor-package-development-features.html#commonclass">existing <em>Bioconductor</em> class</a>.</p> <p>If your data requires a new representation or function, carefully design an S4 class or generic so that other package developers with similar needs will be able to re-use your hard work, and so that users of related packages will be able to seamlessly use your data structures. Do not hesitate to ask on the Bioc-devel mailing list for advice.</p> <p>For any class you define, implement and use a ‘constructor’ for object creation. A constructor is usually plain-old-function (rather than, e.g., a generic with methods). It provides documented and user-friendly arguments, while allowing for developer-friendly implementation. Use the constructor throughout your own code, examples, and vignette.</p> <p>Implement a <code>show()</code> method to effectively convey information to your users without overwhelming them with detail.</p> <p>Accessors (simple functions that return components of your object) rather than direct slot access (using <code>@</code>) help to isolate the implementation of your class from its interface. Generally <code>@</code> should only be used in an accessor, all other code should use the accessor. The accessor does not need to be exported from the class if the user has no need or business accessing parts of your data object. Plain-old-functions (rather than generic + method) are often sufficient for accessors; it’s often useful to employ (consistently) a lightweight name mangling scheme (e.g., starting the accessor method name with a 2 or 3 letter acronym for your package) to avoid name collisions between similarly named functions in other packages.</p> <p>The following layout is sometimes used to organize classes and methods; other approaches are possible and acceptable.</p> <ul> <li>All class definitions in R/AllClasses.R</li> <li>All generic function definitions in R/AllGenerics.R</li> <li>Methods are defined in a file named by the generic function. For example, all <code>show</code> methods would go in R/show-methods.R.</li> </ul> <p>A Collate: field in the DESCRIPTION file may be necessary to order class and method definitions appropriately during package installation.</p> </div> </div> <div id="function-development" class="section level3" number="15.2.6"> <h3> <span class="header-section-number">15.2.6</span> Function development<a class="anchor" aria-label="anchor" href="#function-development"><i class="fas fa-link"></i></a> </h3> <div id="rcode-function-names" class="section level4" number="15.2.6.1"> <h4> <span class="header-section-number">15.2.6.1</span> Functions Names<a class="anchor" aria-label="anchor" href="#rcode-function-names"><i class="fas fa-link"></i></a> </h4> <p>Function names should follow the following conventions:</p> <ul> <li>Use camelCase: initial lower case, then alternate case between words.</li> <li>Do not use ‘.’ (in the S3 class system, <code>some(x)</code> where <code>x</code> is class <code>A</code> will dispatch to <code>some.A</code>).</li> <li>Prefix non-exported functions with a ‘.’.</li> </ul> </div> <div id="functional-programming-and-length" class="section level4" number="15.2.6.2"> <h4> <span class="header-section-number">15.2.6.2</span> Functional Programming and Length<a class="anchor" aria-label="anchor" href="#functional-programming-and-length"><i class="fas fa-link"></i></a> </h4> <p>Guiding principle: Smaller functions are easier to read, test, debug and reuse.</p> <ul> <li><p>Avoid large chunks of repeated code. If code is being repeated this is generally a good indication a helper function could be implemented.</p></li> <li><p>Excessively long functions should also be avoided. Write small functions.</p></li> <li><p>It is best if each function has only one job that it needs to do. And it is also best if that function does that job in as few lines of code as possible. If you find yourself writing great long functions that extend for more than a screen, then you should probably take a moment to split it up into smaller helper functions.</p></li> <li><p>Nesting functions should be avoiding. It unnecessarily increases the main function length and makes the main function harder to read. Helper functions and internal functions should avoid being nested and include at the end of the file or as a seperate file (e.g. internal.R, helpers.R, utils.R)</p></li> </ul> </div> <div id="function-arguments" class="section level4" number="15.2.6.3"> <h4> <span class="header-section-number">15.2.6.3</span> Function arguments<a class="anchor" aria-label="anchor" href="#function-arguments"><i class="fas fa-link"></i></a> </h4> <ul> <li>Argument names to functions should be descriptive and well documented.</li> <li>Arguments should generally have default values.</li> <li>Check arguments against a validity check or <code>stopifnot</code> </li> </ul> </div> <div id="variable-names" class="section level4" number="15.2.6.4"> <h4> <span class="header-section-number">15.2.6.4</span> Variable names<a class="anchor" aria-label="anchor" href="#variable-names"><i class="fas fa-link"></i></a> </h4> <ul> <li>Use camelCase: initial lowercase, then alternate case between words.</li> </ul> </div> <div id="rcode-sysdep" class="section level4" number="15.2.6.5"> <h4> <span class="header-section-number">15.2.6.5</span> Additional files and dependencies<a class="anchor" aria-label="anchor" href="#rcode-sysdep"><i class="fas fa-link"></i></a> </h4> <p>Do NOT install anything on a users system! System dependencies, applications, and additionally needed packages should be assumed already present on the user’s system.</p> <p>Direct calls to external commands via system() or system2() are not ideal so should only be used when there is no other alternative. For example, if a CRAN or Bioconductor package already provides the functionality that you are after, you should use that instead.</p> <p>Now if your package <strong>absolutely</strong> must rely on external software then you need to make sure that those requirements are listed in the SystemRequirements field of the DESCRIPTION file of the package. These requirements should be “reasonable” requirements, that is, trusted software only, open source, and relatively easy to install.</p> <p>Additionally we ask that the package contains an <a href="sysdep.html#sysdep">INSTALL file</a> (in the top-level folder) that provides instructions for installing the external software on the 3 major OS that we support: Linux, Windows, and Mac. This will not only help your users get the external software on their machines, but it will also help us install it on the build machines if it’s not already there.</p> <p>All system and package dependencies should be the latest publically available version. All package dependencies must actively be on CRAN or Bioconductor. Bioconductor will not recognize Remotes in Description and will not install a lower version of a package or dependency.</p> </div> <div id="rcode-namespaces" class="section level4" number="15.2.6.6"> <h4> <span class="header-section-number">15.2.6.6</span> Namespaces<a class="anchor" aria-label="anchor" href="#rcode-namespaces"><i class="fas fa-link"></i></a> </h4> <ul> <li>Import all symbols used from packages other than “base”. Except for default packages (base, graphics, stats, etc.) or when overly tedious, fully enumerate imports.</li> <li>Export all symbols useful to end users. Fully enumerate exports.</li> </ul> </div> </div> <div id="coding-style" class="section level3" number="15.2.7"> <h3> <span class="header-section-number">15.2.7</span> Coding Style<a class="anchor" aria-label="anchor" href="#coding-style"><i class="fas fa-link"></i></a> </h3> <p>While it may seem arbitrary, being consistent with coding style helps other understand, evaluate, and debug code easier. While these are optional, it is highly encouraged.</p> <div id="indentation" class="section level4" number="15.2.7.1"> <h4> <span class="header-section-number">15.2.7.1</span> Indentation<a class="anchor" aria-label="anchor" href="#indentation"><i class="fas fa-link"></i></a> </h4> <ul> <li>Use 4 spaces for indenting. No tabs.</li> <li>No lines longer than 80 characters.</li> </ul> </div> <div id="use-of-space" class="section level4" number="15.2.7.2"> <h4> <span class="header-section-number">15.2.7.2</span> Use of space<a class="anchor" aria-label="anchor" href="#use-of-space"><i class="fas fa-link"></i></a> </h4> <ul> <li>Always use space after a comma. This: <code>a, b, c</code>.</li> <li>No space around “=” when using named arguments to functions. This: <code>somefunc(a=1, b=2)</code> </li> <li>Space around all binary operators: <code>a == b</code>.</li> </ul> </div> <div id="rcode-comments" class="section level4" number="15.2.7.3"> <h4> <span class="header-section-number">15.2.7.3</span> Comments<a class="anchor" aria-label="anchor" href="#rcode-comments"><i class="fas fa-link"></i></a> </h4> <ul> <li>Use “##” to start full-line comments.</li> <li>Indent at the same level as surrounding code.</li> <li>Comments should be for clarification, notes, and documentation only.</li> <li>Do not leave in commented out code chunks that are not utilized</li> <li>Commenting TODO’s should be avoided in published package code</li> </ul> </div> <div id="additonal-style-and-formatting-references" class="section level4" number="15.2.7.4"> <h4> <span class="header-section-number">15.2.7.4</span> Additonal style and formatting references<a class="anchor" aria-label="anchor" href="#additonal-style-and-formatting-references"><i class="fas fa-link"></i></a> </h4> <ul> <li><p><a href="https://cran.r-project.org/web/packages/formatR/index.html">formatR</a> a package that assists with formatting.</p></li> <li><p><a href="https://style.tidyverse.org/">Hadley Wickhams’s R Style Guide</a>.</p></li> </ul> </div> </div> </div> <div id="r-code-best-practices-and-guidelines" class="section level2" number="15.3"> <h2> <span class="header-section-number">15.3</span> R Code Best Practices and Guidelines<a class="anchor" aria-label="anchor" href="#r-code-best-practices-and-guidelines"><i class="fas fa-link"></i></a> </h2> <p>Many common coding and syntax issues are flagged in <code>R CMD check</code> and <code>BiocCheck()</code> (see the <code>R CMD check</code> <a href="http://r-pkgs.had.co.nz/check.html">cheatsheet</a> and <em><a href="https://bioconductor.org/packages/3.21/BiocCheck/vignettes/BiocCheck.html">BiocCheck</a></em> vignette. Every effort should be made to clear up ERROR, WARNING, or NOTEs produced from these checks.</p> <div id="code-syntax-and-efficiency" class="section level3" number="15.3.1"> <h3> <span class="header-section-number">15.3.1</span> Code syntax and efficiency<a class="anchor" aria-label="anchor" href="#code-syntax-and-efficiency"><i class="fas fa-link"></i></a> </h3> <ul> <li>Use <code><a href="https://rdrr.io/r/base/lapply.html">vapply()</a></code> instead of <code><a href="https://rdrr.io/r/base/lapply.html">sapply()</a></code>, and use the various <code>apply</code> functions instead of <code>for</code> loops. See below section on vectorize.</li> <li>Use <code><a href="https://rdrr.io/r/base/seq.html">seq_len()</a></code> or <code><a href="https://rdrr.io/r/base/seq.html">seq_along()</a></code> instead of <code>1:...</code>. See below section on avoid <code>1:n</code> style iterations</li> <li>Use <code>TRUE</code> and <code>FALSE</code> instead of <code>T</code> and <code>F</code>.</li> <li>Use numeric indices at <em>lower</em> level interfaces (e.g., internal subset ops) for computational efficiency.</li> <li>Use named indices at <em>higher</em> level interfaces (e.g., function arguments) for robustness.</li> <li>Use <code>is()</code> instead of <code>class() ==</code> and <code>class() !=</code>.</li> <li>Use <code><a href="https://rdrr.io/r/base/system2.html">system2()</a></code> instead of <code><a href="https://rdrr.io/r/base/system.html">system()</a></code>.</li> <li>Do not use <code><a href="https://rdrr.io/r/base/Random.html">set.seed()</a></code> in any internal <i class="fab fa-r-project"></i> code.</li> <li>Do not use <code><a href="https://rdrr.io/r/base/browser.html">browser()</a></code> in any internal <i class="fab fa-r-project"></i> code.</li> <li>Avoid the use of <code>&lt;&lt;-</code>.</li> <li>Avoid use of direct slot access with <code>@</code> or <code>slot()</code>. Accessor methods should be created and utilized</li> <li>Use the packages <em><a href="https://bioconductor.org/packages/3.21/ExperimentHub">ExperimentHub</a></em> and <em><a href="https://bioconductor.org/packages/3.21/AnnotationHub">AnnotationHub</a></em> instead of downloading external data from unsanctioned providers such as <i class="fab fa-github"></i> GitHub, &lt;i * class=“fa fa-dropbox” aria-hidden=“true”&gt; Dropbox, etc. In general, data utlilized in packages should be downloaded from trusted public databases. See also section on web querying and file caching.</li> <li>Use <code>&lt;-</code> instead of <code>=</code> for assigning variables except in function arguments.</li> </ul> </div> <div id="cyclomatic-complexity" class="section level3" number="15.3.2"> <h3> <span class="header-section-number">15.3.2</span> Cyclomatic Complexity<a class="anchor" aria-label="anchor" href="#cyclomatic-complexity"><i class="fas fa-link"></i></a> </h3> <p>A metric developed by Thomas J. McCabe, cyclomatic complexity describes the control-flow of a program. The higher the value, the more complex the code is said to be.</p> <p>In the <code>BiocCheck</code> example below, we have a series of control-flow statements that check for multiple conditions and return a value if some of those conditions are true. The function <code>hasValueSection</code> is checking that the documentation contains a ‘value’ Rd tag i.e., a return section in the documentation.</p> <div class="sourceCode" id="cb28"><pre class="downlit sourceCode r"> <code class="sourceCode R"><span><span class="va">hasValueSection</span> <span class="op">&lt;-</span> <span class="kw">function</span><span class="op">(</span><span class="va">manpage</span><span class="op">)</span> <span class="op">{</span></span> <span> <span class="va">rd</span> <span class="op">&lt;-</span> <span class="fu">tools</span><span class="fu">::</span><span class="fu"><a href="https://rdrr.io/r/tools/parse_Rd.html">parse_Rd</a></span><span class="op">(</span><span class="va">manpage</span><span class="op">)</span></span> <span> <span class="va">type</span> <span class="op">&lt;-</span> <span class="fu">BiocCheck</span><span class="fu">:::</span><span class="fu">docType</span><span class="op">(</span><span class="va">rd</span><span class="op">)</span></span> <span> <span class="kw">if</span> <span class="op">(</span><span class="fu"><a href="https://rdrr.io/r/base/identical.html">identical</a></span><span class="op">(</span><span class="va">type</span>, <span class="st">"data"</span><span class="op">)</span><span class="op">)</span></span> <span> <span class="kw"><a href="https://rdrr.io/r/base/function.html">return</a></span><span class="op">(</span><span class="cn">TRUE</span><span class="op">)</span></span> <span> <span class="va">tags</span> <span class="op">&lt;-</span> <span class="fu">tools</span><span class="fu">:::</span><span class="fu">RdTags</span><span class="op">(</span><span class="va">rd</span><span class="op">)</span></span> <span> <span class="kw">if</span> <span class="op">(</span><span class="st">"\\usage"</span> <span class="op"><a href="https://rdrr.io/r/base/match.html">%in%</a></span> <span class="va">tags</span> <span class="op">&amp;&amp;</span> <span class="op">(</span><span class="op">!</span><span class="st">"\\value"</span> <span class="op"><a href="https://rdrr.io/r/base/match.html">%in%</a></span> <span class="va">tags</span><span class="op">)</span><span class="op">)</span></span> <span> <span class="kw"><a href="https://rdrr.io/r/base/function.html">return</a></span><span class="op">(</span><span class="cn">FALSE</span><span class="op">)</span></span> <span> <span class="va">value</span> <span class="op">&lt;-</span> <span class="cn">NULL</span></span> <span> <span class="kw">if</span> <span class="op">(</span><span class="st">"\\value"</span> <span class="op"><a href="https://rdrr.io/r/base/match.html">%in%</a></span> <span class="va">tags</span><span class="op">)</span></span> <span> <span class="va">value</span> <span class="op">&lt;-</span> <span class="va">rd</span><span class="op">[</span><span class="fu"><a href="https://rdrr.io/r/base/grep.html">grep</a></span><span class="op">(</span><span class="st">"\\value"</span>, <span class="va">tags</span><span class="op">)</span><span class="op">]</span></span> <span> <span class="kw">if</span> <span class="op">(</span><span class="st">"\\usage"</span> <span class="op"><a href="https://rdrr.io/r/base/match.html">%in%</a></span> <span class="va">tags</span> <span class="op">&amp;&amp;</span> <span class="op">(</span><span class="op">!</span><span class="st">"\\value"</span> <span class="op"><a href="https://rdrr.io/r/base/match.html">%in%</a></span> <span class="va">tags</span><span class="op">)</span><span class="op">)</span> <span class="op">{</span></span> <span> <span class="va">values</span> <span class="op">&lt;-</span> <span class="fu"><a href="https://rdrr.io/r/base/paste.html">paste</a></span><span class="op">(</span><span class="fu"><a href="https://rdrr.io/r/base/unlist.html">unlist</a></span><span class="op">(</span><span class="va">value</span><span class="op">)</span>, collapse<span class="op">=</span><span class="st">''</span><span class="op">)</span></span> <span> <span class="va">test</span> <span class="op">&lt;-</span> <span class="op">(</span><span class="fu"><a href="https://rdrr.io/r/base/list.html">is.list</a></span><span class="op">(</span><span class="va">value</span><span class="op">[[</span><span class="fl">1</span><span class="op">]</span><span class="op">]</span><span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="fu"><a href="https://rdrr.io/r/base/length.html">length</a></span><span class="op">(</span><span class="va">value</span><span class="op">[[</span><span class="fl">1</span><span class="op">]</span><span class="op">]</span><span class="op">)</span> <span class="op">==</span> <span class="fl">0</span><span class="op">)</span> <span class="op">||</span></span> <span> <span class="fu"><a href="https://rdrr.io/r/base/nchar.html">nchar</a></span><span class="op">(</span><span class="fu"><a href="https://rdrr.io/r/base/grep.html">gsub</a></span><span class="op">(</span><span class="st">" "</span>, <span class="st">""</span>, <span class="va">values</span><span class="op">)</span><span class="op">)</span> <span class="op">==</span> <span class="fl">0</span></span> <span> <span class="kw">if</span> <span class="op">(</span><span class="va">test</span><span class="op">)</span></span> <span> <span class="kw"><a href="https://rdrr.io/r/base/function.html">return</a></span><span class="op">(</span><span class="cn">FALSE</span><span class="op">)</span></span> <span> <span class="op">}</span></span> <span> <span class="cn">TRUE</span></span> <span><span class="op">}</span></span></code></pre></div> <p>As you can see, the code here is quite complex, creating <code>if</code> statements for specific conditions. The measured cyclomatic complexity as given by the <code>cyclocomp</code> package is a value of 16.</p> <div class="sourceCode" id="cb29"><pre class="downlit sourceCode r"> <code class="sourceCode R"><span><span class="kw"><a href="https://rdrr.io/r/base/library.html">library</a></span><span class="op">(</span><span class="va"><a href="https://github.com/gaborcsardi/cyclocomp">cyclocomp</a></span><span class="op">)</span></span> <span><span class="fu">cyclocomp</span><span class="op">(</span><span class="va">hasValueSection</span><span class="op">)</span></span> <span><span class="co">#&gt; [1] 16</span></span></code></pre></div> <p>Let’s re-write the function to reduce the complexity and use a base character vector representation.</p> <div class="sourceCode" id="cb30"><pre class="downlit sourceCode r"> <code class="sourceCode R"><span><span class="va">hasValueSection2</span> <span class="op">&lt;-</span> <span class="kw">function</span><span class="op">(</span><span class="va">manpage</span><span class="op">)</span> <span class="op">{</span></span> <span> <span class="va">rd</span> <span class="op">&lt;-</span> <span class="fu">tools</span><span class="fu">::</span><span class="fu"><a href="https://rdrr.io/r/tools/parse_Rd.html">parse_Rd</a></span><span class="op">(</span><span class="va">manpage</span><span class="op">)</span></span> <span> <span class="va">tags</span> <span class="op">&lt;-</span> <span class="fu">tools</span><span class="fu">:::</span><span class="fu">RdTags</span><span class="op">(</span><span class="va">rd</span><span class="op">)</span></span> <span> <span class="va">value</span> <span class="op">&lt;-</span> <span class="va">rd</span><span class="op">[</span><span class="fu"><a href="https://rdrr.io/r/base/grep.html">grepl</a></span><span class="op">(</span><span class="st">"\\value"</span>, <span class="va">tags</span><span class="op">)</span><span class="op">]</span></span> <span> <span class="va">value</span> <span class="op">&lt;-</span> <span class="fu"><a href="https://rdrr.io/r/base/unlist.html">unlist</a></span><span class="op">(</span><span class="va">value</span>, recursive <span class="op">=</span> <span class="cn">FALSE</span><span class="op">)</span></span> <span> <span class="va">value</span> <span class="op">&lt;-</span> <span class="fu"><a href="https://rdrr.io/r/base/funprog.html">Filter</a></span><span class="op">(</span><span class="kw">function</span><span class="op">(</span><span class="va">x</span><span class="op">)</span> <span class="fu"><a href="https://rdrr.io/r/base/attr.html">attr</a></span><span class="op">(</span><span class="va">x</span>, <span class="st">"Rd_tag"</span><span class="op">)</span> <span class="op">!=</span> <span class="st">"COMMENT"</span>, <span class="va">value</span><span class="op">)</span></span> <span> <span class="va">values</span> <span class="op">&lt;-</span> <span class="fu"><a href="https://rdrr.io/r/base/paste.html">paste</a></span><span class="op">(</span><span class="va">value</span>, collapse<span class="op">=</span><span class="st">''</span><span class="op">)</span></span> <span> <span class="fu"><a href="https://rdrr.io/r/base/nchar.html">nzchar</a></span><span class="op">(</span><span class="fu"><a href="https://rdrr.io/r/base/trimws.html">trimws</a></span><span class="op">(</span><span class="va">values</span><span class="op">)</span><span class="op">)</span> <span class="op">&amp;&amp;</span> <span class="fu"><a href="https://rdrr.io/r/base/length.html">length</a></span><span class="op">(</span><span class="va">value</span><span class="op">)</span></span> <span><span class="op">}</span></span></code></pre></div> <p>By internalizing a base character vector representation in the code, the successive functions will operate on that representation. This gives us code that is less complex and easier to understand and maintain with a complexity metric value of 2.</p> <div class="sourceCode" id="cb31"><pre class="downlit sourceCode r"> <code class="sourceCode R"><span><span class="fu">cyclocomp</span><span class="op">(</span><span class="va">hasValueSection2</span><span class="op">)</span></span> <span><span class="co">#&gt; [1] 2</span></span></code></pre></div> <p>Note. Switches based on <code>docType</code> should be outside of the function as a filter for the <code>manpage</code> input instead.</p> <div id="end-user-messages" class="section level4" number="15.3.2.1"> <h4> <span class="header-section-number">15.3.2.1</span> End-User messages<a class="anchor" aria-label="anchor" href="#end-user-messages"><i class="fas fa-link"></i></a> </h4> <p>Use the functions <code><a href="https://rdrr.io/r/base/message.html">message()</a></code>, <code><a href="https://rdrr.io/r/base/warning.html">warning()</a></code> and <code>error()</code>, instead of the <code><a href="https://rdrr.io/r/base/cat.html">cat()</a></code> function (except for customized <code>show()</code> methods). <code><a href="https://rdrr.io/r/base/paste.html">paste0()</a></code> should generally not be used in these methods except for collapsing multiple values from a variable.</p> <ul> <li> <code><a href="https://rdrr.io/r/base/message.html">message()</a></code> communicates diagnostic messages (e.g., progress during lengthy computations) during code evaluation.</li> <li> <code><a href="https://rdrr.io/r/base/warning.html">warning()</a></code> communicates unusual situations handled by your code.</li> <li> <code><a href="https://rdrr.io/r/base/stop.html">stop()</a></code> indicates an error condition.</li> <li> <code><a href="https://rdrr.io/r/base/cat.html">cat()</a></code> or <code><a href="https://rdrr.io/r/base/print.html">print()</a></code> are used only when displaying an object to the user in a <code>show</code> method.</li> </ul> </div> <div id="graphic-device" class="section level4" number="15.3.2.2"> <h4> <span class="header-section-number">15.3.2.2</span> Graphic Device<a class="anchor" aria-label="anchor" href="#graphic-device"><i class="fas fa-link"></i></a> </h4> <p>Use <code><a href="https://rdrr.io/r/grDevices/dev.html">dev.new()</a></code> to start a graphics drive if necessary. Avoid using <code><a href="https://rdrr.io/r/grDevices/x11.html">x11()</a></code> or <code><a href="https://rdrr.io/r/grDevices/x11.html">X11()</a></code>, for it can only be called on machines that have access to an X server.</p> </div> <div id="web-querying-and-file-caching" class="section level4" number="15.3.2.3"> <h4> <span class="header-section-number">15.3.2.3</span> Web Querying and File caching<a class="anchor" aria-label="anchor" href="#web-querying-and-file-caching"><i class="fas fa-link"></i></a> </h4> <p>Files downloaded should be cached. Please use <em><a href="https://bioconductor.org/packages/3.21/BiocFileCache">BiocFileCache</a></em>. If a maintainer creates their own caching directory, it should utilize standard caching directories <code>tools::R_user_dir(package, which="cache")</code>. It is not allowed to download or write any files to a users home directory, working directory, or installed package directory. Files should be cached as stated above with <code>BiocFileCache</code> (preferred) or <code>R_user_dir</code> or <code>tempdir()/tempfile()</code> if files should not be persistent.</p> <p>Please also follow guiding principles in Appendix section <a href="querying-web-resources.html#querying-web-resources">Querying Web Resources</a>, if applicable.</p> </div> </div> </div> <div id="robust-and-efficient-r-code" class="section level2" number="15.4"> <h2> <span class="header-section-number">15.4</span> Robust and Efficient R Code<a class="anchor" aria-label="anchor" href="#robust-and-efficient-r-code"><i class="fas fa-link"></i></a> </h2> <p><em>R</em> can be a robust, fast and efficient programming language, but some coding practices can be very unfortunate. Here are some suggestions.</p> <div id="guiding-principles" class="section level3" number="15.4.1"> <h3> <span class="header-section-number">15.4.1</span> Guiding Principles<a class="anchor" aria-label="anchor" href="#guiding-principles"><i class="fas fa-link"></i></a> </h3> <ol style="list-style-type: decimal"> <li><p>The primary principle is to make sure your code is <strong>correct</strong>. Use <code><a href="https://rdrr.io/r/base/identical.html">identical()</a></code> or <code><a href="https://rdrr.io/r/base/all.equal.html">all.equal()</a></code> to ensure correctness, and <a href="tests.html#tests">unit tests</a> to ensure consistent results across code revisions.</p></li> <li><p>Write robust code. Avoid efficiencies that do not easily handle edge cases such as 0 length or <code>NA</code> values.</p></li> <li><p>Know when to stop trying to be efficient. If the code takes a fraction of a second to evaluate, there is no sense in trying for further improvement. Use <code><a href="https://rdrr.io/r/base/system.time.html">system.time()</a></code> or a package like <a href="https://cran.r-project.org/web/packages/microbenchmark">microbenchmark</a> to quantify performance gains.</p></li> </ol> </div> <div id="reuse-existing-functionality-and-classes" class="section level3" number="15.4.2"> <h3> <span class="header-section-number">15.4.2</span> Reuse Existing Functionality and Classes<a class="anchor" aria-label="anchor" href="#reuse-existing-functionality-and-classes"><i class="fas fa-link"></i></a> </h3> <p>Emphasized again for good measure! Reuse existing import/export methods, functionality, and classes whenever possible.</p> </div> <div id="vectorize" class="section level3" number="15.4.3"> <h3> <span class="header-section-number">15.4.3</span> Vectorize<a class="anchor" aria-label="anchor" href="#vectorize"><i class="fas fa-link"></i></a> </h3> <p>Many R operations are performed on the whole object, not just the elements of the object (e.g., <code>sum(x)</code> instead of <code>x[1] + x[2] + x[2] + ...</code>). In particular, relatively few situations require an explicit <code>for</code> loop.</p> <p>Vectorize, rather than iterate (<code>for</code> loops, <code><a href="https://rdrr.io/r/base/lapply.html">lapply()</a></code>, <code><a href="https://rdrr.io/r/base/apply.html">apply()</a></code> are common iteration idioms in <em>R</em>). A single call <code>y &lt;- sqrt(x)</code> with a vector <code>x</code> of length <code>n</code> is an example of a vectorized function. A call such as <code>y &lt;- sapply(x, sqrt)</code> or a <code>for</code> loop <code>for (i in seq_along(x)) y[i] &lt;- sqrt(x[i])</code> is an iterative version of the same call, and should be avoided. Often, iterative calculations that can be vectorized are “hidden” in the body of a <code>for</code> loop</p> <pre><code>for (i in seq_len(n)) { ## ... tmp &lt;- foo(x[i]) y &lt;- tmp + ## ... }</code></pre> <p>and can be ‘hoisted’ out of the loop</p> <pre><code>tmp &lt;- foo(x) for (i in seq_len(n)) { ## ... y &lt;- tmp[i] + ## }</code></pre> <p>Often this principle can be applied repeatedly, and an iterative <code>for</code> loop becomes a few lines of vectorized function calls.</p> </div> <div id="pre-allocate-and-fill-if-iterations-are-necessary" class="section level3" number="15.4.4"> <h3> <span class="header-section-number">15.4.4</span> ‘Pre-allocate and fill’ if iterations are necessary<a class="anchor" aria-label="anchor" href="#pre-allocate-and-fill-if-iterations-are-necessary"><i class="fas fa-link"></i></a> </h3> <p>Preallocate-and-fill (usually via <code><a href="https://rdrr.io/r/base/lapply.html">lapply()</a></code> or <code><a href="https://rdrr.io/r/base/lapply.html">vapply()</a></code>) rather than copy-and-append. If creating a vector or list of results, use <code><a href="https://rdrr.io/r/base/lapply.html">lapply()</a></code> (to create a list) or <code><a href="https://rdrr.io/r/base/lapply.html">vapply()</a></code> (to create a vector) rather than a <code>for</code> loop. For instance,</p> <pre><code>n &lt;- 10000 x &lt;- vapply(seq_len(n), function(i) { ## ... }, integer(1))</code></pre> <p>manages the memory allocation of <code>x</code> and compactly represents the transformation being performed. A <code>for</code> loop might be appropriate if the iteration has side effects (e.g., displaying a plot) or where calculation of one value depends on a previous value. When creating a vector in a <code>for</code> loop, always pre-allocate the result</p> <pre><code>x &lt;- integer(n) if (n &gt; 0) x[1] &lt;- 0 for (i in seq_len(n - 1)) { ## x[i + 1] &lt;- ... }</code></pre> <p><strong>Never</strong> adopt a strategy of ‘copy-and-append’</p> <pre><code>not_this &lt;- function(n) { x &lt;- integer() for (i in seq_len(n)) x[i] = i x }</code></pre> <p>This pattern copies the current value of <code>x</code> each time through the loop, making <code>n^2 / 2</code> total copies, and scale very poorly even for trivial computations:</p> <pre><code>&gt; system.time(not_this(1000) user system elapsed 0.004 0.000 0.004 &gt; system.time(not_this(10000)) user system elapsed 0.169 0.000 0.168 &gt; system.time(not_this(100000)) user system elapsed 22.827 1.120 23.936</code></pre> </div> <div id="avoid-1n-style-iterations" class="section level3" number="15.4.5"> <h3> <span class="header-section-number">15.4.5</span> Avoid <code>1:n</code> style iterations<a class="anchor" aria-label="anchor" href="#avoid-1n-style-iterations"><i class="fas fa-link"></i></a> </h3> <p>Write <code>seq_len(n)</code> or <code>seq_along(x)</code> rather than <code>1:n</code> or <code>1:length(x)</code>. This protects against the case when <code>n</code> or <code>length(x)</code> is 0 (which often occurs as an unexpected ‘edge case’ in real code) or negative.</p> </div> <div id="parallel-recommendations" class="section level3" number="15.4.6"> <h3> <span class="header-section-number">15.4.6</span> Parallel Recommendations<a class="anchor" aria-label="anchor" href="#parallel-recommendations"><i class="fas fa-link"></i></a> </h3> <p>We recommend using <em><a href="https://bioconductor.org/packages/3.21/BiocParallel">BiocParallel</a></em>. It provides a consistent interface to the user and supports the major parallel computing styles: forks and processes on a single computer, ad hoc clusters, batch schedulers and cloud computing. By default, <code>BiocParallel</code> chooses a parallel back-end appropriate for the OS and is supported across Unix, Mac and Windows. Coding requirements for <code>BiocParallel</code> are:</p> <ul> <li>Use <code><a href="https://rdrr.io/r/base/lapply.html">lapply()</a></code>-style iteration instead of explicit for loops.</li> <li>The <code>FUN</code> argument to <code>bplapply()</code> must be a self-contained function; all symbols used in the function are from default R packages, from packages <code><a href="https://rdrr.io/r/base/library.html">require()</a></code>’ed in the function, or passed in as arguments.</li> <li>Allow the user to specify the BiocParallel back-end. Do this by invoking <code>bplapply()</code> <em>without</em> specifying <code>BPPARAM</code>; the user can then override the default choice with <code>BiocParallel::register()</code>.</li> </ul> <p>For more information see the <a href="https://bioconductor.org/packages/devel/bioc/vignettes/BiocParallel/inst/doc/Introduction_To_BiocParallel.pdf">BiocParallel vignette</a>.</p> <p>When implementing in package development, a minimal number of cores (1 or 2) should be set as a default.</p> </div> </div> </div> <div class="chapter-nav"> <div class="prev"><a href="tests.html"><span class="header-section-number">14</span> Unit tests</a></div> <div class="next"><a href="other-than-Rcode.html"><span class="header-section-number">16</span> Fortran / C / C++ / Python / Third-Party Code</a></div> </div></main><div class="col-md-3 col-lg-2 d-none d-md-block sidebar sidebar-chapter"> <nav id="toc" data-toggle="toc" aria-label="On this page"><h2>On this page</h2> <ul class="nav navbar-nav"> <li><a class="nav-link" href="#r-code"><span class="header-section-number">15</span> R code</a></li> <li><a class="nav-link" href="#rcode-license"><span class="header-section-number">15.1</span> License</a></li> <li> <a class="nav-link" href="#r-code-development"><span class="header-section-number">15.2</span> R Code Development</a><ul class="nav navbar-nav"> <li><a class="nav-link" href="#rcode-reuse"><span class="header-section-number">15.2.1</span> Re-use of functionality, classes, and generics</a></li> <li><a class="nav-link" href="#naming-functions"><span class="header-section-number">15.2.2</span> Naming of packages, functions, and classes</a></li> <li><a class="nav-link" href="#rcode-method-development"><span class="header-section-number">15.2.3</span> Methods development</a></li> <li><a class="nav-link" href="#rcode-file-names"><span class="header-section-number">15.2.4</span> File names</a></li> <li><a class="nav-link" href="#class-development"><span class="header-section-number">15.2.5</span> Class development</a></li> <li><a class="nav-link" href="#function-development"><span class="header-section-number">15.2.6</span> Function development</a></li> <li><a class="nav-link" href="#coding-style"><span class="header-section-number">15.2.7</span> Coding Style</a></li> </ul> </li> <li> <a class="nav-link" href="#r-code-best-practices-and-guidelines"><span class="header-section-number">15.3</span> R Code Best Practices and Guidelines</a><ul class="nav navbar-nav"> <li><a class="nav-link" href="#code-syntax-and-efficiency"><span class="header-section-number">15.3.1</span> Code syntax and efficiency</a></li> <li><a class="nav-link" href="#cyclomatic-complexity"><span class="header-section-number">15.3.2</span> Cyclomatic Complexity</a></li> </ul> </li> <li> <a class="nav-link" href="#robust-and-efficient-r-code"><span class="header-section-number">15.4</span> Robust and Efficient R Code</a><ul class="nav navbar-nav"> <li><a class="nav-link" href="#guiding-principles"><span class="header-section-number">15.4.1</span> Guiding Principles</a></li> <li><a class="nav-link" href="#reuse-existing-functionality-and-classes"><span class="header-section-number">15.4.2</span> Reuse Existing Functionality and Classes</a></li> <li><a class="nav-link" href="#vectorize"><span class="header-section-number">15.4.3</span> Vectorize</a></li> <li><a class="nav-link" href="#pre-allocate-and-fill-if-iterations-are-necessary"><span class="header-section-number">15.4.4</span> ‘Pre-allocate and fill’ if iterations are necessary</a></li> <li><a class="nav-link" href="#avoid-1n-style-iterations"><span class="header-section-number">15.4.5</span> Avoid 1:n style iterations</a></li> <li><a class="nav-link" href="#parallel-recommendations"><span class="header-section-number">15.4.6</span> Parallel Recommendations</a></li> </ul> </li> </ul> <div class="book-extra"> <ul class="list-unstyled"> <li><a id="book-source" href="https://github.com/Bioconductor/pkgrevdocs/blob/devel/r-code.Rmd">View source <i class="fab fa-github"></i></a></li> <li><a id="book-edit" href="https://github.com/Bioconductor/pkgrevdocs/edit/devel/r-code.Rmd">Edit this page <i class="fab fa-github"></i></a></li> </ul> </div> </nav> </div> </div> </div> <!-- .container --> <footer class="bg-primary text-light mt-5"><div class="container"><div class="row"> <div class="col-12 col-md-6 mt-3"> <p>"<strong>Bioconductor Packages: Development, Maintenance, and Peer Review</strong>" was written by Kevin Rue-Albrecht, Daniela Cassol, Johannes Rainer, Lori Shepherd. It was last built on 2024-11-20.</p> </div> <div class="col-12 col-md-6 mt-3"> <p>This book was built by the <a class="text-light" href="https://bookdown.org">bookdown</a> R package.</p> </div> </div></div> </footer><!-- dynamically load mathjax for compatibility with self-contained --><script> (function () { var script = document.createElement("script"); script.type = "text/javascript"; var src = "true"; if (src === "" || src === "true") src = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/latest.js?config=TeX-MML-AM_CHTML"; if (location.protocol !== "file:") if (/^https?:/.test(src)) src = src.replace(/^https?:/, ''); script.src = src; document.getElementsByTagName("head")[0].appendChild(script); })(); </script><script type="text/x-mathjax-config">const popovers = document.querySelectorAll('a.footnote-ref[data-toggle="popover"]'); for (let popover of popovers) { const div = document.createElement('div'); div.setAttribute('style', 'position: absolute; top: 0, left:0; width:0, height:0, overflow: hidden; visibility: hidden;'); div.innerHTML = popover.getAttribute('data-content'); var has_math = div.querySelector("span.math"); if (has_math) { document.body.appendChild(div); MathJax.Hub.Queue(["Typeset", MathJax.Hub, div]); MathJax.Hub.Queue(function() { popover.setAttribute('data-content', div.innerHTML); document.body.removeChild(div); }) } } </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10