The document specifies how code in the Cardano SL git repository should be organised. Consistent module naming schemes and file locations make the code relatively uniform so that it is easier for developers (internal and external), engineers working on formal specifications and auditors (internal and external) to navigate the code base.
Currently, the code base does not conform to these guidelines but it is hoped that over time it can move from non-conforming to conforming. Making code conform to these guidelines in one big pull request or one long lived refactoring branch would be a huge amount of work and/or cause a lot of disruption to the regular flow of development. Instead, these guidelines should be applied as a series of small easy-to-review commits that can be merged relatively quickly.
-
All library code for a Haskell package should be in the
src
directory of that package. Currently some packages usesrc
and others usePos
. For example thelib
package currently has testing related code in thesrc/Test
directory that should be be moved to thetest
directory. -
The
cardano-sl
git repository includes a number of distinct Haskell packages likecore
,util
,explorer
,networking
and so on. All Haskell modules within each of these packages should be given a unique name prefix. All modules withincore
would have a prefixPos.Core
, modules withinutil
would have a name prefixPos.Util
, modules withinnetworking
might have a prefix ofPos.Network
and so on. This means that when looking at the imports for a module, it is immediately obvious which package each import comes from. As an example of a file that needs to be renamed/moved the filecore/Pos/Aeson/Core.hs
should be renamed tocore/src/Pos/Core/Aeson.hs
so that if it is imported in another module its namePos.Core.Aeson
would immediately suggest its location in the source tree. -
Tests for a Haskell package should always be a part of the same package as the implementation of the code it is testing. Test code should not be included in the library that a package provides. All test code for a Haskell package should be in the
test
directory of that package and modules with testing related code should have module names staring withTest
and then reflecting the Haskell package which the code is testing, so test code for thecore
package would have all its test module names begin withTest.Pos.Core
. An example of where the current code base contravenes these guidelines is thatcore
andtxp
currently don't define any tests, but at least some of the functionality in these two modules are tested inlib
package. -
Arbitrary instances for testing should never be in the library source tree and should not be compiled into the library defined by the package. Instead, Arbitrary instances should be under the
test
directory as per the previous point. When Arbitrary instances or other testing helper functionality needs to be used by other packages, a test specific package should be created. For instance, thecore
package may haveArbitrary
instances that are need for tests in thetxp
package. In this case, there will be a cabal filecore/test/cardano-sl-core-test.cabal
which exports the required modules, all of which would have aTest.Pos.Core
name prefix. PR #2588 is an example of doing this for thecrypto
package. -
The library that a Haskell package provides should never include or export any code that is not part of the API the library provides to clients of the library. It is however valid for a library to provide interface functions to its internals that are required for testing or benchmarking, thus becoming part of the library's API.
-
Benchmarking code should be in a separate tree under the
bench
directory of the haskell package it is benchmarking. Modules that are solely required for benchmarking should be in thebench
sub directory and have module names beginning withBench
and something related to the package they are a part of. For instance, benchmarking code in thecore
package should have names that start withBench.Core
. An example of code that contravenes part of this is thenetworking
package which provides the moduleBench.Network.Commons
that is only used by the benchmarking target in thesrc
tree and is also included as an exposed module in thelibrary
section of the cabal file. -
Example code should also be in a separate tree under the
example
directory of the current package. An example of code that contravenes this is thenetworking
package which providesNTP.Example
.