From ab1a5dd059af7b3e7a7210e56db18d16c8922707 Mon Sep 17 00:00:00 2001 From: davidsarah <> Date: Mon, 26 Sep 2011 22:44:01 +0000 Subject: [PATCH] move "assertion policy" section to a more relevant place [Imported from Trac: page CodingStandards, version 17] --- CodingStandards.md | 76 +++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/CodingStandards.md b/CodingStandards.md index f32571c..0e0dd74 100644 --- a/CodingStandards.md +++ b/CodingStandards.md @@ -96,45 +96,9 @@ def _assert_invariants(self): Now you can put `assert self._assert_invariants()` everywhere in your class where the class ought to be in an internally consistent state. For example, at the beginning of every externally-callable method. This technique can be very valuable in developing a complex class -- it catches bugs early, it isolates bugs into specific code paths, and it clarifies the internal structure of the class so that other developers can hack on it without subtle misunderstandings. -* we actually appear to only have one instance of this pattern in Tahoe at time of writing, in `allmydata.util.dictutil`. It has the disadvantage of cluttering up the logic with calls to `_assert_invariants`, and should probably be used sparingly. -- DavidSarah +* we actually appear to only have one instance of this pattern in Tahoe at time of writing, in `allmydata.util.dictutil`. It has the disadvantage of cluttering up the logic with calls to `_assert_invariants`, and should probably be used sparingly. -- David-Sarah -=== configuration === - -==== minimizing configuration ==== - - * Do not implement configuration files for modules or libraries -- code that is going to be used by other code. Only applications -- code that is going to be used by humans -- have configuration files. Modules and libraries get "configured" by the code that calls them, for example by passing arguments to their constructors. - * If there are constant values which end-users do not need to modify, then do not make them configurable, but put them in all-caps variables at the beginning of the Python file in which they are used. - * Design algorithms so that they have as few "voodoo constants" and "tweakable parameters" as possible. - -==== how to implement configuration ==== - -Whether in application code or in library code, never pass configuration values via a configuration object. Instead use Python parameters. For example -- here's another real-life example -- do not write - -``` -class BlockStore: - def __init__(self, confdict={}, recoverdb=True, name='*unnamed*'): - if confdict.has_key('MAX_MEGABYTES'): - self.maxspace = (2**20) * int(confdict.get('MAX_MEGABYTES')) - else: - self.maxspace = None - self.basepath = os.path.abspath(confdict.get("PATH", "")) - self.maintainertype = confdict.get("MAINTAINER", "rnd").lower() - self.backendtype = confdict.get("BACKEND", "flat").lower() -``` - -, but instead write - -``` -class BlockStore: - def __init__(self, maxspace=None, path="", maintainertype="rnd", backendtype="flat", recoverdb=True, name='*unnamed*'): - self.basepath = os.path.abspath(path) - self.maintainertype = maintainertype - self.backendtype = backendtype -``` -. - - -#### assertion policy +==== assertion policy ==== One axis of interest is how time-consuming the checks are. Many precondition checks can cause typical runtime to explode to O(n^2^) or O(n^3^), for example @@ -184,6 +148,42 @@ callers. altogether) before committing. +### configuration + +#### minimizing configuration + + * Do not implement configuration files for modules or libraries -- code that is going to be used by other code. Only applications -- code that is going to be used by humans -- have configuration files. Modules and libraries get "configured" by the code that calls them, for example by passing arguments to their constructors. + * If there are constant values which end-users do not need to modify, then do not make them configurable, but put them in all-caps variables at the beginning of the Python file in which they are used. + * Design algorithms so that they have as few "voodoo constants" and "tweakable parameters" as possible. + +#### how to implement configuration + +Whether in application code or in library code, never pass configuration values via a configuration object. Instead use Python parameters. For example -- here's another real-life example -- do not write + +``` +class BlockStore: + def __init__(self, confdict={}, recoverdb=True, name='*unnamed*'): + if confdict.has_key('MAX_MEGABYTES'): + self.maxspace = (2**20) * int(confdict.get('MAX_MEGABYTES')) + else: + self.maxspace = None + self.basepath = os.path.abspath(confdict.get("PATH", "")) + self.maintainertype = confdict.get("MAINTAINER", "rnd").lower() + self.backendtype = confdict.get("BACKEND", "flat").lower() +``` + +, but instead write + +``` +class BlockStore: + def __init__(self, maxspace=None, path="", maintainertype="rnd", backendtype="flat", recoverdb=True, name='*unnamed*'): + self.basepath = os.path.abspath(path) + self.maintainertype = maintainertype + self.backendtype = backendtype +``` +. + + ## official Python standards These are listed in decreasing order of priority, so if a point in one of the latter guidelines contradicts a point in one of the earlier ones, then go with the earlier. The Tahoe-LAFS-specific guidelines above override all else, of course.