mirror of
https://github.com/corda/corda.git
synced 2024-12-21 05:53:23 +00:00
commit
882217fa9d
162
docs/build/html/_sources/codestyle.txt
vendored
Normal file
162
docs/build/html/_sources/codestyle.txt
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
Code style guide
|
||||
================
|
||||
|
||||
This document explains the coding style used in the R3 prototyping repository. You will be expected to follow these
|
||||
recommendations when submitting patches for review. Please take the time to read them and internalise them, to save
|
||||
time during code review.
|
||||
|
||||
What follows are *recommendations* and not *rules*. They are in places intentionally vague, so use your good judgement
|
||||
when interpreting them.
|
||||
|
||||
.. note:: Parts of the codebase may not follow this style guide yet. If you see a place that doesn't, please fix it!
|
||||
|
||||
1. General style
|
||||
################
|
||||
|
||||
We use the standard Java coding style from Sun, adapted for Kotlin in ways that should be fairly intuitive.
|
||||
|
||||
We aim for line widths of no more than 120 characters. That is wide enough to avoid lots of pointless wrapping but
|
||||
narrow enough that with a widescreen monitor and a 12 point fixed width font (like Menlo) you can fit two files
|
||||
next to each other. This is not a rigidly enforced rule and if wrapping a line would be excessively awkward, let it
|
||||
overflow. Overflow of a few characters here and there isn't a big deal: the goal is general convenience.
|
||||
|
||||
Code is vertically dense, blank lines in methods are used sparingly. This is so more code can fit on screen at once.
|
||||
|
||||
Each file has a copyright notice at the top. Copy it from the existing files if you create a new one. We do not mark
|
||||
classes with @author Javadoc annotations.
|
||||
|
||||
In Kotlin code, KDoc is used rather than JavaDoc. It's very similar except it uses Markdown for formatting instead
|
||||
of HTML tags.
|
||||
|
||||
We target Java 8 and use the latest Java APIs whenever convenient. We use ``java.time.Instant`` to represent timestamps
|
||||
and ``java.nio.file.Path`` to represent file paths.
|
||||
|
||||
We use spaces and not tabs.
|
||||
|
||||
Never apply any design pattern religiously. There are no silver bullets in programming and if something is fashionable,
|
||||
that doesn't mean it's always better. In particular:
|
||||
|
||||
* Use functional programming patterns like map, filter, fold only where it's genuinely more convenient. Never be afraid
|
||||
to use a simple imperative construct like a for loop or a mutable counter if that results in more direct, English-like
|
||||
code.
|
||||
* Use immutability when you don't anticipate very rapid or complex changes to the content. Immutability can help avoid
|
||||
bugs, but over-used it can make code that has to adjust fields of an immutable object (in a clone) hard to read and
|
||||
stress the garbage collector. When such code becomes a widespread pattern it can lead to code that is just generically
|
||||
slow but without hotspots.
|
||||
* The tradeoffs between various thread safety techniques are complex, subtle, and no technique is always superior to
|
||||
the others. Our code uses a mix of locks, worker threads and messaging depending on the situation.
|
||||
|
||||
2. Comments
|
||||
###########
|
||||
|
||||
We like them as long as they add detail that is missing from the code. Comments that simply repeat the story already
|
||||
told by the code are best deleted. Comments should:
|
||||
|
||||
* Explain what the code is doing at a higher level than is obtainable from just examining the statement and
|
||||
surrounding code.
|
||||
* Explain why certain choices were made and the tradeoffs considered.
|
||||
* Explain how things can go wrong, which is a detail often not easily seen just by reading the code.
|
||||
* Use good grammar with capital letters and full stops. This gets us in the right frame of mind for writing real
|
||||
explanations of things.
|
||||
|
||||
When writing code, imagine that you have an intelligent colleague looking over your shoulder asking you questions
|
||||
as you go. Think about what they might ask, and then put your answers in the code.
|
||||
|
||||
Don’t be afraid of redundancy, many people will start reading your code in the middle with little or no idea of what
|
||||
it’s about, eg, due to a bug or a need to introduce a new feature. It’s OK to repeat basic facts or descriptions in
|
||||
different places if that increases the chance developers will see something important.
|
||||
|
||||
API docs: all public methods, constants and classes should have doc comments in either JavaDoc or KDoc. API docs should:
|
||||
|
||||
* Explain what the method does in words different to how the code describes it.
|
||||
* Always have some text, annotation-only JavaDocs don’t render well. Write “Returns a blah blah blah” rather
|
||||
than “@returns blah blah blah” if that's the only content (or leave it out if you have nothing more to say than the
|
||||
code already says).
|
||||
* Illustrate with examples when you might want to use the method or class. Point the user at alternatives if this code
|
||||
is not always right.
|
||||
* Make good use of {@link} annotations.
|
||||
|
||||
Bad JavaDocs look like this:
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
/** @return the size of the Bloom filter. */
|
||||
public int getBloomFilterSize() {
|
||||
return block;
|
||||
}
|
||||
|
||||
Good JavaDocs look like this:
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
/**
|
||||
* Returns the size of the current {@link BloomFilter} in bytes. Larger filters have
|
||||
* lower false positive rates for the same number of inserted keys and thus lower privacy,
|
||||
* but bandwidth usage is also correspondingly reduced.
|
||||
*/
|
||||
public int getBloomFilterSize() { ... }
|
||||
|
||||
We use C-style (``/** */``) comments for API docs and we use C++ style comments (``//``) for explanations that are
|
||||
only intended to be viewed by people who read the code.
|
||||
|
||||
3. Threading
|
||||
############
|
||||
|
||||
Classes that are thread safe should be annotated with the ``@ThreadSafe`` annotation. The class or method comments
|
||||
should describe how threads are expected to interact with your code, unless it's obvious because the class is
|
||||
(for example) a simple immutable data holder.
|
||||
|
||||
Code that supports callbacks or event listeners should always accept an ``Executor`` argument that defaults to
|
||||
``MoreExecutors.directThreadExecutor()`` (i.e. the calling thread) when registering the callback. This makes it easy
|
||||
to integrate the callbacks with whatever threading environment the calling code expects, e.g. serialised onto a single
|
||||
worker thread if necessary, or run directly on the background threads used by the class if the callback is thread safe
|
||||
and doesn't care in what context it's invoked.
|
||||
|
||||
In the prototyping code it's OK to use synchronised methods i.e. with an exposed lock when the use of locking is quite
|
||||
trivial. If the synchronisation in your code is getting more complex, consider the following:
|
||||
|
||||
1. Is the complexity necessary? At this early stage, don't worry too much about performance or scalability, as we're
|
||||
exploring the design space rather than making an optimal implementation of a design that's already nailed down.
|
||||
2. Could you simplify it by making the data be owned by a dedicated, encapsulated worker thread? If so, remember to
|
||||
think about flow control and what happens if a work queue fills up: the actor model can often be useful but be aware
|
||||
of the downsides and try to avoid explicitly defining messages, prefer to send closures onto the worker thread
|
||||
instead.
|
||||
3. If you use an explicit lock and the locking gets complex, and *always* if the class supports callbacks, use the
|
||||
cycle detecting locks from the Guava library.
|
||||
4. Can you simplify some things by using thread-safe collections like ``CopyOnWriteArrayList`` or ``ConcurrentHashMap``?
|
||||
These data structures are more expensive than their non-thread-safe equivalents but can be worth it if it lets us
|
||||
simplify the code.
|
||||
|
||||
Immutable data structures can be very useful for making it easier to reason about multi-threaded code. Kotlin makes it
|
||||
easy to define these via the "data" attribute, which auto-generates a copy() method. That lets you create clones of
|
||||
an immutable object with arbitrary fields adjusted in the clone. But if you can't use the data attribute for some
|
||||
reason, for instance, you are working in Java or because you need an inheritance heirarchy, then consider that making
|
||||
a class fully immutable may result in very awkward code if there's ever a need to make complex changes to it. If in
|
||||
doubt, ask. Remember, never apply any design pattern religiously.
|
||||
|
||||
4. Assertions and errors
|
||||
########################
|
||||
|
||||
We use them liberally and we use them at runtime, in production. That means we avoid the "assert" keyword in Java,
|
||||
and instead prefer to use the ``check()`` or ``require()`` functions in Kotlin (for an ``IllegalStateException`` or
|
||||
``IllegalArgumentException`` respectively), or the Guava ``Preconditions.check`` method from Java.
|
||||
|
||||
We define new exception types liberally. We prefer not to provide English language error messages in exceptions at
|
||||
the throw site, instead we define new types with any useful information as fields, with a toString() method if
|
||||
really necessary. In other words, don't do this:
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
throw new Exception("The foo broke")
|
||||
|
||||
instead do this
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
class FooBrokenException extends Exception {}
|
||||
throw new FooBrokenException()
|
||||
|
||||
The latter is easier to catch and handle if later necessary, and the type name should explain what went wrong.
|
||||
|
||||
Note that Kotlin does not require exception types to be declared in method prototypes like Java does.
|
||||
|
1
docs/build/html/_sources/index.txt
vendored
1
docs/build/html/_sources/index.txt
vendored
@ -41,4 +41,5 @@ Read on to learn:
|
||||
|
||||
visualiser
|
||||
roadmap
|
||||
codestyle
|
||||
|
||||
|
@ -146,8 +146,8 @@ each side.
|
||||
)
|
||||
|
||||
|
||||
private class UnacceptablePriceException(val givenPrice: Amount) : Exception()
|
||||
private class AssetMismatchException(val expectedTypeName: String, val typeName: String) : Exception() {
|
||||
class UnacceptablePriceException(val givenPrice: Amount) : Exception()
|
||||
class AssetMismatchException(val expectedTypeName: String, val typeName: String) : Exception() {
|
||||
override fun toString() = "The submitted asset didn't match the expected type: $expectedTypeName vs $typeName"
|
||||
}
|
||||
|
||||
|
2
docs/build/html/_static/basic.css
vendored
2
docs/build/html/_static/basic.css
vendored
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
2
docs/build/html/_static/doctools.js
vendored
2
docs/build/html/_static/doctools.js
vendored
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Sphinx JavaScript utilities for all documentation.
|
||||
*
|
||||
* :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
2
docs/build/html/_static/pygments.css
vendored
2
docs/build/html/_static/pygments.css
vendored
@ -4,8 +4,10 @@
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
|
47
docs/build/html/_static/searchtools.js
vendored
47
docs/build/html/_static/searchtools.js
vendored
@ -4,12 +4,13 @@
|
||||
*
|
||||
* Sphinx JavaScript utilties for the full-text search.
|
||||
*
|
||||
* :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Non-minified version JS is _stemmer.js if file is provided */
|
||||
/**
|
||||
* Porter Stemmer
|
||||
*/
|
||||
@ -373,8 +374,7 @@ var Search = {
|
||||
}
|
||||
|
||||
// lookup as search terms in fulltext
|
||||
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, Scorer.term))
|
||||
.concat(this.performTermsSearch(searchterms, excluded, titleterms, Scorer.title));
|
||||
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
|
||||
|
||||
// let the scorer override scores with a custom scoring function
|
||||
if (Scorer.score) {
|
||||
@ -538,23 +538,47 @@ var Search = {
|
||||
/**
|
||||
* search for full-text terms in the index
|
||||
*/
|
||||
performTermsSearch : function(searchterms, excluded, terms, score) {
|
||||
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
|
||||
var filenames = this._index.filenames;
|
||||
var titles = this._index.titles;
|
||||
|
||||
var i, j, file, files;
|
||||
var i, j, file;
|
||||
var fileMap = {};
|
||||
var scoreMap = {};
|
||||
var results = [];
|
||||
|
||||
// perform the search on the required terms
|
||||
for (i = 0; i < searchterms.length; i++) {
|
||||
var word = searchterms[i];
|
||||
var files = [];
|
||||
var _o = [
|
||||
{files: terms[word], score: Scorer.term},
|
||||
{files: titleterms[word], score: Scorer.title}
|
||||
];
|
||||
|
||||
// no match but word was a required one
|
||||
if ((files = terms[word]) === undefined)
|
||||
if ($u.every(_o, function(o){return o.files === undefined;})) {
|
||||
break;
|
||||
if (files.length === undefined) {
|
||||
files = [files];
|
||||
}
|
||||
// found search word in contents
|
||||
$u.each(_o, function(o) {
|
||||
var _files = o.files;
|
||||
if (_files === undefined)
|
||||
return
|
||||
|
||||
if (_files.length === undefined)
|
||||
_files = [_files];
|
||||
files = files.concat(_files);
|
||||
|
||||
// set score for the word in each file to Scorer.term
|
||||
for (j = 0; j < _files.length; j++) {
|
||||
file = _files[j];
|
||||
if (!(file in scoreMap))
|
||||
scoreMap[file] = {}
|
||||
scoreMap[file][word] = o.score;
|
||||
}
|
||||
});
|
||||
|
||||
// create the mapping
|
||||
for (j = 0; j < files.length; j++) {
|
||||
file = files[j];
|
||||
@ -576,7 +600,9 @@ var Search = {
|
||||
// ensure that none of the excluded terms is in the search result
|
||||
for (i = 0; i < excluded.length; i++) {
|
||||
if (terms[excluded[i]] == file ||
|
||||
$u.contains(terms[excluded[i]] || [], file)) {
|
||||
titleterms[excluded[i]] == file ||
|
||||
$u.contains(terms[excluded[i]] || [], file) ||
|
||||
$u.contains(titleterms[excluded[i]] || [], file)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
@ -584,6 +610,9 @@ var Search = {
|
||||
|
||||
// if we have still a valid result we can add it to the result list
|
||||
if (valid) {
|
||||
// select one (max) score for the file.
|
||||
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
|
||||
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
|
||||
results.push([filenames[file], titles[file], '', null, score]);
|
||||
}
|
||||
}
|
||||
|
2
docs/build/html/_static/websupport.js
vendored
2
docs/build/html/_static/websupport.js
vendored
@ -4,7 +4,7 @@
|
||||
*
|
||||
* sphinx.websupport utilties for all documentation.
|
||||
*
|
||||
* :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
355
docs/build/html/codestyle.html
vendored
Normal file
355
docs/build/html/codestyle.html
vendored
Normal file
@ -0,0 +1,355 @@
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>Code style guide — R3 Prototyping 0.1 documentation</title>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="_static/css/custom.css" type="text/css" />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="top" title="R3 Prototyping 0.1 documentation" href="index.html"/>
|
||||
<link rel="prev" title="Roadmap" href="roadmap.html"/>
|
||||
|
||||
|
||||
<script src="_static/js/modernizr.min.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="wy-body-for-nav" role="document">
|
||||
|
||||
<div class="wy-grid-for-nav">
|
||||
|
||||
|
||||
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
||||
<div class="wy-side-scroll">
|
||||
<div class="wy-side-nav-search">
|
||||
|
||||
|
||||
|
||||
<a href="index.html" class="icon icon-home"> R3 Prototyping
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="version">
|
||||
0.1
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div role="search">
|
||||
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
|
||||
<input type="text" name="q" placeholder="Search docs" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
|
||||
|
||||
|
||||
|
||||
<p class="caption"><span class="caption-text">Overview</span></p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="inthebox.html">What’s included?</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="data-model.html">Data model</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="messaging.html">Networking and messaging</a></li>
|
||||
</ul>
|
||||
<p class="caption"><span class="caption-text">Tutorials</span></p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="tutorial.html">Writing a contract</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="protocol-state-machines.html">Protocol state machines</a></li>
|
||||
</ul>
|
||||
<p class="caption"><span class="caption-text">Appendix</span></p>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="">Code style guide</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#general-style">1. General style</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#comments">2. Comments</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#threading">3. Threading</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#assertions-and-errors">4. Assertions and errors</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||||
|
||||
|
||||
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
|
||||
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||||
<a href="index.html">R3 Prototyping</a>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
<div class="wy-nav-content">
|
||||
<div class="rst-content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div role="navigation" aria-label="breadcrumbs navigation">
|
||||
<ul class="wy-breadcrumbs">
|
||||
<li><a href="index.html">Docs</a> »</li>
|
||||
|
||||
<li>Code style guide</li>
|
||||
<li class="wy-breadcrumbs-aside">
|
||||
|
||||
|
||||
<a href="_sources/codestyle.txt" rel="nofollow"> View page source</a>
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
</div>
|
||||
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||||
<div itemprop="articleBody">
|
||||
|
||||
<div class="section" id="code-style-guide">
|
||||
<h1>Code style guide<a class="headerlink" href="#code-style-guide" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This document explains the coding style used in the R3 prototyping repository. You will be expected to follow these
|
||||
recommendations when submitting patches for review. Please take the time to read them and internalise them, to save
|
||||
time during code review.</p>
|
||||
<p>What follows are <em>recommendations</em> and not <em>rules</em>. They are in places intentionally vague, so use your good judgement
|
||||
when interpreting them.</p>
|
||||
<div class="admonition note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
<p class="last">Parts of the codebase may not follow this style guide yet. If you see a place that doesn’t, please fix it!</p>
|
||||
</div>
|
||||
<div class="section" id="general-style">
|
||||
<h2>1. General style<a class="headerlink" href="#general-style" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We use the standard Java coding style from Sun, adapted for Kotlin in ways that should be fairly intuitive.</p>
|
||||
<p>We aim for line widths of no more than 120 characters. That is wide enough to avoid lots of pointless wrapping but
|
||||
narrow enough that with a widescreen monitor and a 12 point fixed width font (like Menlo) you can fit two files
|
||||
next to each other. This is not a rigidly enforced rule and if wrapping a line would be excessively awkward, let it
|
||||
overflow. Overflow of a few characters here and there isn’t a big deal: the goal is general convenience.</p>
|
||||
<p>Code is vertically dense, blank lines in methods are used sparingly. This is so more code can fit on screen at once.</p>
|
||||
<p>Each file has a copyright notice at the top. Copy it from the existing files if you create a new one. We do not mark
|
||||
classes with @author Javadoc annotations.</p>
|
||||
<p>In Kotlin code, KDoc is used rather than JavaDoc. It’s very similar except it uses Markdown for formatting instead
|
||||
of HTML tags.</p>
|
||||
<p>We target Java 8 and use the latest Java APIs whenever convenient. We use <code class="docutils literal"><span class="pre">java.time.Instant</span></code> to represent timestamps
|
||||
and <code class="docutils literal"><span class="pre">java.nio.file.Path</span></code> to represent file paths.</p>
|
||||
<p>We use spaces and not tabs.</p>
|
||||
<p>Never apply any design pattern religiously. There are no silver bullets in programming and if something is fashionable,
|
||||
that doesn’t mean it’s always better. In particular:</p>
|
||||
<ul class="simple">
|
||||
<li>Use functional programming patterns like map, filter, fold only where it’s genuinely more convenient. Never be afraid
|
||||
to use a simple imperative construct like a for loop or a mutable counter if that results in more direct, English-like
|
||||
code.</li>
|
||||
<li>Use immutability when you don’t anticipate very rapid or complex changes to the content. Immutability can help avoid
|
||||
bugs, but over-used it can make code that has to adjust fields of an immutable object (in a clone) hard to read and
|
||||
stress the garbage collector. When such code becomes a widespread pattern it can lead to code that is just generically
|
||||
slow but without hotspots.</li>
|
||||
<li>The tradeoffs between various thread safety techniques are complex, subtle, and no technique is always superior to
|
||||
the others. Our code uses a mix of locks, worker threads and messaging depending on the situation.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="comments">
|
||||
<h2>2. Comments<a class="headerlink" href="#comments" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We like them as long as they add detail that is missing from the code. Comments that simply repeat the story already
|
||||
told by the code are best deleted. Comments should:</p>
|
||||
<ul class="simple">
|
||||
<li>Explain what the code is doing at a higher level than is obtainable from just examining the statement and
|
||||
surrounding code.</li>
|
||||
<li>Explain why certain choices were made and the tradeoffs considered.</li>
|
||||
<li>Explain how things can go wrong, which is a detail often not easily seen just by reading the code.</li>
|
||||
<li>Use good grammar with capital letters and full stops. This gets us in the right frame of mind for writing real
|
||||
explanations of things.</li>
|
||||
</ul>
|
||||
<p>When writing code, imagine that you have an intelligent colleague looking over your shoulder asking you questions
|
||||
as you go. Think about what they might ask, and then put your answers in the code.</p>
|
||||
<p>Don’t be afraid of redundancy, many people will start reading your code in the middle with little or no idea of what
|
||||
it’s about, eg, due to a bug or a need to introduce a new feature. It’s OK to repeat basic facts or descriptions in
|
||||
different places if that increases the chance developers will see something important.</p>
|
||||
<p>API docs: all public methods, constants and classes should have doc comments in either JavaDoc or KDoc. API docs should:</p>
|
||||
<ul class="simple">
|
||||
<li>Explain what the method does in words different to how the code describes it.</li>
|
||||
<li>Always have some text, annotation-only JavaDocs don’t render well. Write “Returns a blah blah blah” rather
|
||||
than “@returns blah blah blah” if that’s the only content (or leave it out if you have nothing more to say than the
|
||||
code already says).</li>
|
||||
<li>Illustrate with examples when you might want to use the method or class. Point the user at alternatives if this code
|
||||
is not always right.</li>
|
||||
<li>Make good use of <a class="reference external" href="mailto:{%40link">{<span>@</span>link</a>} annotations.</li>
|
||||
</ul>
|
||||
<p>Bad JavaDocs look like this:</p>
|
||||
<div class="highlight-java"><div class="highlight"><pre><span class="cm">/** @return the size of the Bloom filter. */</span>
|
||||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getBloomFilterSize</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">block</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Good JavaDocs look like this:</p>
|
||||
<div class="highlight-java"><div class="highlight"><pre><span class="cm">/**</span>
|
||||
<span class="cm"> * Returns the size of the current {@link BloomFilter} in bytes. Larger filters have</span>
|
||||
<span class="cm"> * lower false positive rates for the same number of inserted keys and thus lower privacy,</span>
|
||||
<span class="cm"> * but bandwidth usage is also correspondingly reduced.</span>
|
||||
<span class="cm"> */</span>
|
||||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getBloomFilterSize</span><span class="o">()</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We use C-style (<code class="docutils literal"><span class="pre">/**</span> <span class="pre">*/</span></code>) comments for API docs and we use C++ style comments (<code class="docutils literal"><span class="pre">//</span></code>) for explanations that are
|
||||
only intended to be viewed by people who read the code.</p>
|
||||
</div>
|
||||
<div class="section" id="threading">
|
||||
<h2>3. Threading<a class="headerlink" href="#threading" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Classes that are thread safe should be annotated with the <code class="docutils literal"><span class="pre">@ThreadSafe</span></code> annotation. The class or method comments
|
||||
should describe how threads are expected to interact with your code, unless it’s obvious because the class is
|
||||
(for example) a simple immutable data holder.</p>
|
||||
<p>Code that supports callbacks or event listeners should always accept an <code class="docutils literal"><span class="pre">Executor</span></code> argument that defaults to
|
||||
<code class="docutils literal"><span class="pre">MoreExecutors.directThreadExecutor()</span></code> (i.e. the calling thread) when registering the callback. This makes it easy
|
||||
to integrate the callbacks with whatever threading environment the calling code expects, e.g. serialised onto a single
|
||||
worker thread if necessary, or run directly on the background threads used by the class if the callback is thread safe
|
||||
and doesn’t care in what context it’s invoked.</p>
|
||||
<p>In the prototyping code it’s OK to use synchronised methods i.e. with an exposed lock when the use of locking is quite
|
||||
trivial. If the synchronisation in your code is getting more complex, consider the following:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>Is the complexity necessary? At this early stage, don’t worry too much about performance or scalability, as we’re
|
||||
exploring the design space rather than making an optimal implementation of a design that’s already nailed down.</li>
|
||||
<li>Could you simplify it by making the data be owned by a dedicated, encapsulated worker thread? If so, remember to
|
||||
think about flow control and what happens if a work queue fills up: the actor model can often be useful but be aware
|
||||
of the downsides and try to avoid explicitly defining messages, prefer to send closures onto the worker thread
|
||||
instead.</li>
|
||||
<li>If you use an explicit lock and the locking gets complex, and <em>always</em> if the class supports callbacks, use the
|
||||
cycle detecting locks from the Guava library.</li>
|
||||
<li>Can you simplify some things by using thread-safe collections like <code class="docutils literal"><span class="pre">CopyOnWriteArrayList</span></code> or <code class="docutils literal"><span class="pre">ConcurrentHashMap</span></code>?
|
||||
These data structures are more expensive than their non-thread-safe equivalents but can be worth it if it lets us
|
||||
simplify the code.</li>
|
||||
</ol>
|
||||
<p>Immutable data structures can be very useful for making it easier to reason about multi-threaded code. Kotlin makes it
|
||||
easy to define these via the “data” attribute, which auto-generates a copy() method. That lets you create clones of
|
||||
an immutable object with arbitrary fields adjusted in the clone. But if you can’t use the data attribute for some
|
||||
reason, for instance, you are working in Java or because you need an inheritance heirarchy, then consider that making
|
||||
a class fully immutable may result in very awkward code if there’s ever a need to make complex changes to it. If in
|
||||
doubt, ask. Remember, never apply any design pattern religiously.</p>
|
||||
</div>
|
||||
<div class="section" id="assertions-and-errors">
|
||||
<h2>4. Assertions and errors<a class="headerlink" href="#assertions-and-errors" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We use them liberally and we use them at runtime, in production. That means we avoid the “assert” keyword in Java,
|
||||
and instead prefer to use the <code class="docutils literal"><span class="pre">check()</span></code> or <code class="docutils literal"><span class="pre">require()</span></code> functions in Kotlin (for an <code class="docutils literal"><span class="pre">IllegalStateException</span></code> or
|
||||
<code class="docutils literal"><span class="pre">IllegalArgumentException</span></code> respectively), or the Guava <code class="docutils literal"><span class="pre">Preconditions.check</span></code> method from Java.</p>
|
||||
<p>We define new exception types liberally. We prefer not to provide English language error messages in exceptions at
|
||||
the throw site, instead we define new types with any useful information as fields, with a toString() method if
|
||||
really necessary. In other words, don’t do this:</p>
|
||||
<div class="highlight-java"><div class="highlight"><pre><span class="k">throw</span> <span class="k">new</span> <span class="n">Exception</span><span class="o">(</span><span class="s">"The foo broke"</span><span class="o">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>instead do this</p>
|
||||
<div class="highlight-java"><div class="highlight"><pre><span class="kd">class</span> <span class="nc">FooBrokenException</span> <span class="kd">extends</span> <span class="n">Exception</span> <span class="o">{}</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="n">FooBrokenException</span><span class="o">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The latter is easier to catch and handle if later necessary, and the type name should explain what went wrong.</p>
|
||||
<p>Note that Kotlin does not require exception types to be declared in method prototypes like Java does.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
|
||||
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
||||
|
||||
|
||||
<a href="roadmap.html" class="btn btn-neutral" title="Roadmap" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<hr/>
|
||||
|
||||
<div role="contentinfo">
|
||||
<p>
|
||||
© Copyright 2015, R3 CEV.
|
||||
|
||||
</p>
|
||||
</div>
|
||||
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
||||
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT:'./',
|
||||
VERSION:'0.1',
|
||||
COLLAPSE_INDEX:false,
|
||||
FILE_SUFFIX:'.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript" src="_static/js/theme.js"></script>
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
jQuery(function () {
|
||||
SphinxRtdTheme.StickyNav.enable();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
1
docs/build/html/data-model.html
vendored
1
docs/build/html/data-model.html
vendored
@ -102,6 +102,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
1
docs/build/html/genindex.html
vendored
1
docs/build/html/genindex.html
vendored
@ -96,6 +96,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
1
docs/build/html/getting-set-up.html
vendored
1
docs/build/html/getting-set-up.html
vendored
@ -101,6 +101,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
8
docs/build/html/index.html
vendored
8
docs/build/html/index.html
vendored
@ -96,6 +96,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
@ -214,6 +215,13 @@ prove or disprove the following hypothesis:</p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="codestyle.html#general-style">1. General style</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="codestyle.html#comments">2. Comments</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="codestyle.html#threading">3. Threading</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="codestyle.html#assertions-and-errors">4. Assertions and errors</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
1
docs/build/html/inthebox.html
vendored
1
docs/build/html/inthebox.html
vendored
@ -101,6 +101,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
1
docs/build/html/messaging.html
vendored
1
docs/build/html/messaging.html
vendored
@ -102,6 +102,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
5
docs/build/html/protocol-state-machines.html
vendored
5
docs/build/html/protocol-state-machines.html
vendored
@ -106,6 +106,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
@ -275,8 +276,8 @@ each side.</p>
|
||||
<span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">private</span> <span class="k">class</span> <span class="nc">UnacceptablePriceException</span><span class="p">(</span><span class="k">val</span> <span class="py">givenPrice</span><span class="p">:</span> <span class="n">Amount</span><span class="p">)</span> <span class="p">:</span> <span class="n">Exception</span><span class="p">()</span>
|
||||
<span class="k">private</span> <span class="k">class</span> <span class="nc">AssetMismatchException</span><span class="p">(</span><span class="k">val</span> <span class="py">expectedTypeName</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> <span class="k">val</span> <span class="py">typeName</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="p">:</span> <span class="n">Exception</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">class</span> <span class="nc">UnacceptablePriceException</span><span class="p">(</span><span class="k">val</span> <span class="py">givenPrice</span><span class="p">:</span> <span class="n">Amount</span><span class="p">)</span> <span class="p">:</span> <span class="n">Exception</span><span class="p">()</span>
|
||||
<span class="k">class</span> <span class="nc">AssetMismatchException</span><span class="p">(</span><span class="k">val</span> <span class="py">expectedTypeName</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> <span class="k">val</span> <span class="py">typeName</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="p">:</span> <span class="n">Exception</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">override</span> <span class="k">fun</span> <span class="nf">toString</span><span class="p">()</span> <span class="p">=</span> <span class="s">"The submitted asset didn't match the expected type: $expectedTypeName vs $typeName"</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
|
4
docs/build/html/roadmap.html
vendored
4
docs/build/html/roadmap.html
vendored
@ -31,6 +31,7 @@
|
||||
|
||||
|
||||
<link rel="top" title="R3 Prototyping 0.1 documentation" href="index.html"/>
|
||||
<link rel="next" title="Code style guide" href="codestyle.html"/>
|
||||
<link rel="prev" title="Using the visualiser" href="visualiser.html"/>
|
||||
|
||||
|
||||
@ -96,6 +97,7 @@
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
@ -184,6 +186,8 @@ Thread.stop() unsafe to use), and to measure and enforce runtime limits to handl
|
||||
|
||||
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
||||
|
||||
<a href="codestyle.html" class="btn btn-neutral float-right" title="Code style guide" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
|
||||
|
||||
|
||||
<a href="visualiser.html" class="btn btn-neutral" title="Using the visualiser" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
||||
|
||||
|
1
docs/build/html/search.html
vendored
1
docs/build/html/search.html
vendored
@ -95,6 +95,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
2
docs/build/html/searchindex.js
vendored
2
docs/build/html/searchindex.js
vendored
File diff suppressed because one or more lines are too long
5
docs/build/html/tutorial.html
vendored
5
docs/build/html/tutorial.html
vendored
@ -108,6 +108,7 @@
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
@ -202,7 +203,7 @@ piece of issued paper.</p>
|
||||
<h2>States<a class="headerlink" href="#states" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A state is a class that stores data that is checked by the contract.</p>
|
||||
<div class="codeset container">
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="n">data</span> <span class="k">class</span> <span class="nc">State</span><span class="p">(</span>
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="k">data</span> <span class="k">class</span> <span class="nc">State</span><span class="p">(</span>
|
||||
<span class="k">val</span> <span class="py">issuance</span><span class="p">:</span> <span class="n">InstitutionReference</span><span class="p">,</span>
|
||||
<span class="k">val</span> <span class="py">owner</span><span class="p">:</span> <span class="n">PublicKey</span><span class="p">,</span>
|
||||
<span class="k">val</span> <span class="py">faceValue</span><span class="p">:</span> <span class="n">Amount</span><span class="p">,</span>
|
||||
@ -316,7 +317,7 @@ checked, so from the contract code’s perspective, a command is simply a da
|
||||
public keys. Each key had a signature proving that the corresponding private key was used to sign.</p>
|
||||
<p>Let’s define a few commands now:</p>
|
||||
<div class="codeset container">
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="n">interface</span> <span class="n">Commands</span> <span class="p">:</span> <span class="n">Command</span> <span class="p">{</span>
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="k">interface</span> <span class="nc">Commands</span> <span class="p">:</span> <span class="n">Command</span> <span class="p">{</span>
|
||||
<span class="k">object</span> <span class="nc">Move</span> <span class="p">:</span> <span class="n">Commands</span>
|
||||
<span class="k">object</span> <span class="nc">Redeem</span> <span class="p">:</span> <span class="n">Commands</span>
|
||||
<span class="k">object</span> <span class="nc">Issue</span> <span class="p">:</span> <span class="n">Commands</span>
|
||||
|
1
docs/build/html/visualiser.html
vendored
1
docs/build/html/visualiser.html
vendored
@ -97,6 +97,7 @@
|
||||
<ul class="current">
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="">Using the visualiser</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
162
docs/source/codestyle.rst
Normal file
162
docs/source/codestyle.rst
Normal file
@ -0,0 +1,162 @@
|
||||
Code style guide
|
||||
================
|
||||
|
||||
This document explains the coding style used in the R3 prototyping repository. You will be expected to follow these
|
||||
recommendations when submitting patches for review. Please take the time to read them and internalise them, to save
|
||||
time during code review.
|
||||
|
||||
What follows are *recommendations* and not *rules*. They are in places intentionally vague, so use your good judgement
|
||||
when interpreting them.
|
||||
|
||||
.. note:: Parts of the codebase may not follow this style guide yet. If you see a place that doesn't, please fix it!
|
||||
|
||||
1. General style
|
||||
################
|
||||
|
||||
We use the standard Java coding style from Sun, adapted for Kotlin in ways that should be fairly intuitive.
|
||||
|
||||
We aim for line widths of no more than 120 characters. That is wide enough to avoid lots of pointless wrapping but
|
||||
narrow enough that with a widescreen monitor and a 12 point fixed width font (like Menlo) you can fit two files
|
||||
next to each other. This is not a rigidly enforced rule and if wrapping a line would be excessively awkward, let it
|
||||
overflow. Overflow of a few characters here and there isn't a big deal: the goal is general convenience.
|
||||
|
||||
Code is vertically dense, blank lines in methods are used sparingly. This is so more code can fit on screen at once.
|
||||
|
||||
Each file has a copyright notice at the top. Copy it from the existing files if you create a new one. We do not mark
|
||||
classes with @author Javadoc annotations.
|
||||
|
||||
In Kotlin code, KDoc is used rather than JavaDoc. It's very similar except it uses Markdown for formatting instead
|
||||
of HTML tags.
|
||||
|
||||
We target Java 8 and use the latest Java APIs whenever convenient. We use ``java.time.Instant`` to represent timestamps
|
||||
and ``java.nio.file.Path`` to represent file paths.
|
||||
|
||||
We use spaces and not tabs.
|
||||
|
||||
Never apply any design pattern religiously. There are no silver bullets in programming and if something is fashionable,
|
||||
that doesn't mean it's always better. In particular:
|
||||
|
||||
* Use functional programming patterns like map, filter, fold only where it's genuinely more convenient. Never be afraid
|
||||
to use a simple imperative construct like a for loop or a mutable counter if that results in more direct, English-like
|
||||
code.
|
||||
* Use immutability when you don't anticipate very rapid or complex changes to the content. Immutability can help avoid
|
||||
bugs, but over-used it can make code that has to adjust fields of an immutable object (in a clone) hard to read and
|
||||
stress the garbage collector. When such code becomes a widespread pattern it can lead to code that is just generically
|
||||
slow but without hotspots.
|
||||
* The tradeoffs between various thread safety techniques are complex, subtle, and no technique is always superior to
|
||||
the others. Our code uses a mix of locks, worker threads and messaging depending on the situation.
|
||||
|
||||
2. Comments
|
||||
###########
|
||||
|
||||
We like them as long as they add detail that is missing from the code. Comments that simply repeat the story already
|
||||
told by the code are best deleted. Comments should:
|
||||
|
||||
* Explain what the code is doing at a higher level than is obtainable from just examining the statement and
|
||||
surrounding code.
|
||||
* Explain why certain choices were made and the tradeoffs considered.
|
||||
* Explain how things can go wrong, which is a detail often not easily seen just by reading the code.
|
||||
* Use good grammar with capital letters and full stops. This gets us in the right frame of mind for writing real
|
||||
explanations of things.
|
||||
|
||||
When writing code, imagine that you have an intelligent colleague looking over your shoulder asking you questions
|
||||
as you go. Think about what they might ask, and then put your answers in the code.
|
||||
|
||||
Don’t be afraid of redundancy, many people will start reading your code in the middle with little or no idea of what
|
||||
it’s about, eg, due to a bug or a need to introduce a new feature. It’s OK to repeat basic facts or descriptions in
|
||||
different places if that increases the chance developers will see something important.
|
||||
|
||||
API docs: all public methods, constants and classes should have doc comments in either JavaDoc or KDoc. API docs should:
|
||||
|
||||
* Explain what the method does in words different to how the code describes it.
|
||||
* Always have some text, annotation-only JavaDocs don’t render well. Write “Returns a blah blah blah” rather
|
||||
than “@returns blah blah blah” if that's the only content (or leave it out if you have nothing more to say than the
|
||||
code already says).
|
||||
* Illustrate with examples when you might want to use the method or class. Point the user at alternatives if this code
|
||||
is not always right.
|
||||
* Make good use of {@link} annotations.
|
||||
|
||||
Bad JavaDocs look like this:
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
/** @return the size of the Bloom filter. */
|
||||
public int getBloomFilterSize() {
|
||||
return block;
|
||||
}
|
||||
|
||||
Good JavaDocs look like this:
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
/**
|
||||
* Returns the size of the current {@link BloomFilter} in bytes. Larger filters have
|
||||
* lower false positive rates for the same number of inserted keys and thus lower privacy,
|
||||
* but bandwidth usage is also correspondingly reduced.
|
||||
*/
|
||||
public int getBloomFilterSize() { ... }
|
||||
|
||||
We use C-style (``/** */``) comments for API docs and we use C++ style comments (``//``) for explanations that are
|
||||
only intended to be viewed by people who read the code.
|
||||
|
||||
3. Threading
|
||||
############
|
||||
|
||||
Classes that are thread safe should be annotated with the ``@ThreadSafe`` annotation. The class or method comments
|
||||
should describe how threads are expected to interact with your code, unless it's obvious because the class is
|
||||
(for example) a simple immutable data holder.
|
||||
|
||||
Code that supports callbacks or event listeners should always accept an ``Executor`` argument that defaults to
|
||||
``MoreExecutors.directThreadExecutor()`` (i.e. the calling thread) when registering the callback. This makes it easy
|
||||
to integrate the callbacks with whatever threading environment the calling code expects, e.g. serialised onto a single
|
||||
worker thread if necessary, or run directly on the background threads used by the class if the callback is thread safe
|
||||
and doesn't care in what context it's invoked.
|
||||
|
||||
In the prototyping code it's OK to use synchronised methods i.e. with an exposed lock when the use of locking is quite
|
||||
trivial. If the synchronisation in your code is getting more complex, consider the following:
|
||||
|
||||
1. Is the complexity necessary? At this early stage, don't worry too much about performance or scalability, as we're
|
||||
exploring the design space rather than making an optimal implementation of a design that's already nailed down.
|
||||
2. Could you simplify it by making the data be owned by a dedicated, encapsulated worker thread? If so, remember to
|
||||
think about flow control and what happens if a work queue fills up: the actor model can often be useful but be aware
|
||||
of the downsides and try to avoid explicitly defining messages, prefer to send closures onto the worker thread
|
||||
instead.
|
||||
3. If you use an explicit lock and the locking gets complex, and *always* if the class supports callbacks, use the
|
||||
cycle detecting locks from the Guava library.
|
||||
4. Can you simplify some things by using thread-safe collections like ``CopyOnWriteArrayList`` or ``ConcurrentHashMap``?
|
||||
These data structures are more expensive than their non-thread-safe equivalents but can be worth it if it lets us
|
||||
simplify the code.
|
||||
|
||||
Immutable data structures can be very useful for making it easier to reason about multi-threaded code. Kotlin makes it
|
||||
easy to define these via the "data" attribute, which auto-generates a copy() method. That lets you create clones of
|
||||
an immutable object with arbitrary fields adjusted in the clone. But if you can't use the data attribute for some
|
||||
reason, for instance, you are working in Java or because you need an inheritance heirarchy, then consider that making
|
||||
a class fully immutable may result in very awkward code if there's ever a need to make complex changes to it. If in
|
||||
doubt, ask. Remember, never apply any design pattern religiously.
|
||||
|
||||
4. Assertions and errors
|
||||
########################
|
||||
|
||||
We use them liberally and we use them at runtime, in production. That means we avoid the "assert" keyword in Java,
|
||||
and instead prefer to use the ``check()`` or ``require()`` functions in Kotlin (for an ``IllegalStateException`` or
|
||||
``IllegalArgumentException`` respectively), or the Guava ``Preconditions.check`` method from Java.
|
||||
|
||||
We define new exception types liberally. We prefer not to provide English language error messages in exceptions at
|
||||
the throw site, instead we define new types with any useful information as fields, with a toString() method if
|
||||
really necessary. In other words, don't do this:
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
throw new Exception("The foo broke")
|
||||
|
||||
instead do this
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
class FooBrokenException extends Exception {}
|
||||
throw new FooBrokenException()
|
||||
|
||||
The latter is easier to catch and handle if later necessary, and the type name should explain what went wrong.
|
||||
|
||||
Note that Kotlin does not require exception types to be declared in method prototypes like Java does.
|
||||
|
@ -41,4 +41,5 @@ Read on to learn:
|
||||
|
||||
visualiser
|
||||
roadmap
|
||||
codestyle
|
||||
|
||||
|
@ -105,7 +105,8 @@ fun Iterable<Amount>.sumOrZero(currency: Currency) = if (iterator().hasNext()) s
|
||||
//// Authenticated commands ///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Filters the command list by type, party and public key all at once. */
|
||||
inline fun <reified T : CommandData> List<AuthenticatedObject<CommandData>>.select(signer: PublicKey? = null, party: Party? = null) =
|
||||
inline fun <reified T : CommandData> List<AuthenticatedObject<CommandData>>.select(signer: PublicKey? = null,
|
||||
party: Party? = null) =
|
||||
filter { it.value is T }.
|
||||
filter { if (signer == null) true else it.signers.contains(signer) }.
|
||||
filter { if (party == null) true else it.signingParties.contains(party) }.
|
||||
@ -118,7 +119,8 @@ inline fun <reified T : CommandData> List<AuthenticatedObject<CommandData>>.requ
|
||||
}
|
||||
|
||||
// For Java
|
||||
fun List<AuthenticatedObject<CommandData>>.requireSingleCommand(klass: Class<out CommandData>) = filter { klass.isInstance(it) }.single()
|
||||
fun List<AuthenticatedObject<CommandData>>.requireSingleCommand(klass: Class<out CommandData>) =
|
||||
filter { klass.isInstance(it) }.single()
|
||||
|
||||
/** Returns a timestamp that was signed by the given authority, or returns null if missing. */
|
||||
fun List<AuthenticatedObject<CommandData>>.getTimestampBy(timestampingAuthority: Party): TimestampCommand? {
|
||||
|
@ -142,7 +142,8 @@ public class InMemoryNetwork {
|
||||
* An instance can be obtained by creating a builder and then using the start method.
|
||||
*/
|
||||
inner class Node(private val manuallyPumped: Boolean, private val handle: Handle): MessagingService {
|
||||
inner class Handler(val executor: Executor?, val topic: String, val callback: (Message, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration
|
||||
inner class Handler(val executor: Executor?, val topic: String,
|
||||
val callback: (Message, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration
|
||||
@GuardedBy("this")
|
||||
protected val handlers: MutableList<Handler> = ArrayList()
|
||||
@GuardedBy("this")
|
||||
@ -156,16 +157,17 @@ public class InMemoryNetwork {
|
||||
override val timestampingNodes = if (timestampingAdvert != null) listOf(timestampingAdvert!!) else emptyList()
|
||||
}
|
||||
|
||||
protected val backgroundThread = if (manuallyPumped) null else thread(isDaemon = true, name = "In-memory message dispatcher ") {
|
||||
while (!currentThread.isInterrupted) {
|
||||
try {
|
||||
pumpInternal(true)
|
||||
} catch(e: InterruptedException) {
|
||||
if (synchronized(this) { running })
|
||||
throw e
|
||||
protected val backgroundThread = if (manuallyPumped) null else
|
||||
thread(isDaemon = true, name = "In-memory message dispatcher ") {
|
||||
while (!currentThread.isInterrupted) {
|
||||
try {
|
||||
pumpInternal(true)
|
||||
} catch(e: InterruptedException) {
|
||||
if (synchronized(this) { running })
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun addMessageHandler(topic: String, executor: Executor?, callback: (Message, MessageHandlerRegistration) -> Unit): MessageHandlerRegistration {
|
||||
@ -264,4 +266,4 @@ public class InMemoryNetwork {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,8 +72,12 @@ class SerializedBytes<T : Any>(bits: ByteArray) : OpaqueBytes(bits) {
|
||||
}
|
||||
|
||||
// Some extension functions that make deserialisation convenient and provide auto-casting of the result.
|
||||
inline fun <reified T : Any> ByteArray.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get()): T = kryo.readObject(Input(this), T::class.java)
|
||||
inline fun <reified T : Any> OpaqueBytes.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get()): T = kryo.readObject(Input(this.bits), T::class.java)
|
||||
inline fun <reified T : Any> ByteArray.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get()): T {
|
||||
return kryo.readObject(Input(this), T::class.java)
|
||||
}
|
||||
inline fun <reified T : Any> OpaqueBytes.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get()): T {
|
||||
return kryo.readObject(Input(this.bits), T::class.java)
|
||||
}
|
||||
inline fun <reified T : Any> SerializedBytes<T>.deserialize(): T = bits.deserialize()
|
||||
|
||||
/**
|
||||
@ -132,7 +136,8 @@ class ImmutableClassSerializer<T : Any>(val klass: KClass<T>) : Serializer<T>()
|
||||
// A few quick checks for data evolution. Note that this is not guaranteed to catch every problem! But it's
|
||||
// good enough for a prototype.
|
||||
if (numFields != constructor.parameters.size)
|
||||
throw KryoException("Mismatch between number of constructor parameters and number of serialised fields for ${klass.qualifiedName} ($numFields vs ${constructor.parameters.size})")
|
||||
throw KryoException("Mismatch between number of constructor parameters and number of serialised fields " +
|
||||
"for ${klass.qualifiedName} ($numFields vs ${constructor.parameters.size})")
|
||||
if (fieldTypeHash != constructor.parameters.hashCode())
|
||||
throw KryoException("Hashcode mismatch for parameter types for ${klass.qualifiedName}: unsupported type evolution has happened.")
|
||||
|
||||
@ -195,4 +200,4 @@ fun createKryo(k: Kryo = Kryo()): Kryo {
|
||||
register(it.java, ImmutableClassSerializer(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user