Changes between Version 16 and Version 17 of CodingStandards


Ignore:
Timestamp:
2011-09-26T22:44:01Z (9 years ago)
Author:
davidsarah
Comment:

move "assertion policy" section to a more relevant place

Legend:

Unmodified
Added
Removed
Modified
  • CodingStandards

    v16 v17  
    9797Now 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.
    9898
    99 * 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
     99* 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
     100
     101==== assertion policy ====
     102
     103One axis of interest is how time-consuming the checks are. Many precondition
     104checks can cause typical runtime to explode to O(n^2^) or O(n^3^), for example
     105{{{SortedList.__contains__}}} called {{{_assert_invariants}}} which took
     106O(n log n) each time, when {{{__contains__}}} ought to be O(log n). A caller who
     107was expecting {{{if b in list}}} to take O(log n) could easily wind up turning
     108their O(n log n) routine into O(n^2^) or worse.
     109
     110Another axis is "who could cause it to fail": some checks are looking only at
     111internal state. For example, if {{{SortedList._assert_invariants}}} fails, it
     112indicates a problem in some {{{SortedList}}} method. Other checks are
     113enforcing the external API, like those which do typechecks on input
     114arguments. Even after the {{{SortedList}}} developer has gained confidence in
     115the code and decides that internal checks are no longer necessary, it may be
     116useful to retain the external checks to isolate usage problems that exist in
     117callers.
     118
     119 * The general rule is that nodes must be functional for light traffic even
     120   when the assertions are turned on. When assertions are turned off (-O),
     121   nodes must be functional for heavy traffic.
     122
     123 * Time-consuming internal checks: once the code is working properly,
     124   consider removing them, but they may be left in place as long as they
     125   use {{{assert}}} (the form which gets turned off when -O is used).
     126
     127 * Cheap internal checks: once the code is working properly, consider
     128   removing them, but it is less of a concern than the time-consuming ones.
     129   If they really are cheap, use {{{_assert}}} (the unconditional form
     130   that gets used even with -O).
     131
     132 * Time-consuming external checks: maybe leave them in place, but always
     133   use {{{assert}}} so they will not be used with -O.
     134
     135 * Cheap external checks: leave them in place, using the unconditional
     136   {{{_assert}}}
     137
     138 * Production grids could run with -O (in practice, the allmydata.com production grid runs without -O, because there are no expensive checks in the current codebase).
     139
     140 * Testing grids might run without -O in order to detect more bugs.
     141
     142 * Local developer tests will probably not use -O, and developers should be
     143   prepared to experience the same CPU load problems if they subject their
     144   nodes to real traffic levels. Developers can use -O to turn off everyone
     145   else's checks, use {{{_assert}}} on their own code to enable their own
     146   assertions, and then subject their nodes to heavy traffic, as long as they
     147   are sure to change their checks to use {{{assert}}} (or remove them
     148   altogether) before committing.
     149
    100150
    101151=== configuration ===
     
    135185
    136186
    137 ==== assertion policy ====
    138 
    139 One axis of interest is how time-consuming the checks are. Many precondition
    140 checks can cause typical runtime to explode to O(n^2^) or O(n^3^), for example
    141 {{{SortedList.__contains__}}} called {{{_assert_invariants}}} which took
    142 O(n log n) each time, when {{{__contains__}}} ought to be O(log n). A caller who
    143 was expecting {{{if b in list}}} to take O(log n) could easily wind up turning
    144 their O(n log n) routine into O(n^2^) or worse.
    145 
    146 Another axis is "who could cause it to fail": some checks are looking only at
    147 internal state. For example, if {{{SortedList._assert_invariants}}} fails, it
    148 indicates a problem in some {{{SortedList}}} method. Other checks are
    149 enforcing the external API, like those which do typechecks on input
    150 arguments. Even after the {{{SortedList}}} developer has gained confidence in
    151 the code and decides that internal checks are no longer necessary, it may be
    152 useful to retain the external checks to isolate usage problems that exist in
    153 callers.
    154 
    155  * The general rule is that nodes must be functional for light traffic even
    156    when the assertions are turned on. When assertions are turned off (-O),
    157    nodes must be functional for heavy traffic.
    158 
    159  * Time-consuming internal checks: once the code is working properly,
    160    consider removing them, but they may be left in place as long as they
    161    use {{{assert}}} (the form which gets turned off when -O is used).
    162 
    163  * Cheap internal checks: once the code is working properly, consider
    164    removing them, but it is less of a concern than the time-consuming ones.
    165    If they really are cheap, use {{{_assert}}} (the unconditional form
    166    that gets used even with -O).
    167 
    168  * Time-consuming external checks: maybe leave them in place, but always
    169    use {{{assert}}} so they will not be used with -O.
    170 
    171  * Cheap external checks: leave them in place, using the unconditional
    172    {{{_assert}}}
    173 
    174  * Production grids could run with -O (in practice, the allmydata.com production grid runs without -O, because there are no expensive checks in the current codebase).
    175 
    176  * Testing grids might run without -O in order to detect more bugs.
    177 
    178  * Local developer tests will probably not use -O, and developers should be
    179    prepared to experience the same CPU load problems if they subject their
    180    nodes to real traffic levels. Developers can use -O to turn off everyone
    181    else's checks, use {{{_assert}}} on their own code to enable their own
    182    assertions, and then subject their nodes to heavy traffic, as long as they
    183    are sure to change their checks to use {{{assert}}} (or remove them
    184    altogether) before committing.
    185 
    186 
    187187== official Python standards ==
    188188