[Style] more revisions

This commit is contained in:
Matthias Felleisen 2011-08-02 18:31:14 -04:00 committed by Eli Barzilay
parent a496213549
commit 38eb1efa91
7 changed files with 178 additions and 71 deletions

View File

@ -6,22 +6,58 @@
@section{Commit}
So what is the major lesson of this section? When you fix a bug, make sure
to commit (1) the code delta, (2) the new test case, and (3) the revised
docs (if applicable) in one batch. If the creation of a single commit is
too complex of if you wish to factor out one of the commits, please push
all pieces at once. That way the code base is always in a state where
code, tests, and documentation are in sync, and readers of commit messages
can evaluate changes completely.
@bold{New feature commit:} Commit the new feature, its tests, and its
documentations as you wish, but please push them together.
@section{No Commit ``Bombs'' Please}
@bold{Bug fix commit:} When you fix a bug, make sure to commit (1) the
code delta, (2) the new test case, and (3) the revised docs (if
applicable) in one batch. If the creation of a single commit is too
complex of if you wish to factor out one of the commits, please push all
pieces at once. That way the code base is always in a state where code,
tests, and documentation are in sync, and readers of commit messages can
evaluate changes completely.
@bold{Style change commit:} Submit changes to the style of a file
separately from changes to its behavior (new features, bugs).
@; -----------------------------------------------------------------------------
@section{No Commit ``Bombs,'' Please}
On occasion, you will find that you are spending a significant amount of
time working with someone else's code. To avoid potentially painful
merges, please (1) inform the author when you create the branch and (2)
set the mail hook @margin-note*{See @hyperlink["http://tmp.barzilay.org/git.txt"]{Eli's write-up} on using git in PLT for
information on the mechanics.} so that git sends a commit message to both
you and the original author. Furthermore, you should test your changes on
the actual code base. In some cases it is acceptable to delay such tests,
e.g., when you will not know for a long time whether the performance
implication allow a commit to the PLT repository.
set the mail hook so that git sends a commit message to both you and the
original author. Furthermore, you should test your changes on the actual
code base. In some cases it is acceptable to delay such tests, e.g., when
you will not know for a long time whether the performance implication
allow a commit to the PLT repository.
@margin-note*{See @hyperlink["http://tmp.barzilay.org/git.txt"]{Eli's
write-up} on using git in PLT for details.}
As a reminder, here are the essential elements of git for working on a
fork:
@itemlist[
@item{setup a fork:
@verbatim{
ssh pltgit fork plt eli/my-plt}
}
@item{setup mail notifications:
@verbatim{
ssh pltgit config set eli/my-plt hooks.counter true
ssh pltgit config set eli/my-plt hooks.mailinglist "eli at barzilay.org, ..."
}}
@item{allow someone else to push commits to my repository:
@verbatim{
ssh pltgit setperms eli/my-plt
RW eli
RW someone-else
^D
}}
]

View File

@ -1,6 +1,6 @@
#lang scribble/base
@(require "shared.rkt")
@(require "shared.rkt" scribble/eval)
@title{Choosing the Right Construct}
@ -9,13 +9,20 @@ Although the Racket designers don't think that there is one right way for
everything, we prefer certain constructs in certain situations for consistency
and readability.
@; -----------------------------------------------------------------------------
@section{Comments}
Following Lisp and Scheme tradition, we use a single semicolon for in-line
comments (to the end of a line) and two semicolons for comments that start
a line. Think of the second semicolon as making an emphatic point.
@; -----------------------------------------------------------------------------
@section{Definitions}
Racket comes with quite a few definitional constructs, including
@scheme[let], @scheme[let*], @scheme[letrec], and @scheme[define]. Except
for the last one, definitional construct increase the indentation level. We
therefore request that you favor @scheme[define] when feasible.
for the last one, definitional construct increase the indentation level.
Therefore, favor @scheme[define] when feasible.
@compare[
@racketmod[#:file
@ -111,27 +118,35 @@ Keep expressions small. Name intermediate results.
@racketmod[#:file
@tt{good}
racket
(define (distance0 p)
(define x (posn-x p))
(define y (posn-y p))
(sqrt (+ (sqr x) (sqr y))))
(define (next-month date)
(define day (first date))
(define month (second date))
(define year (third date))
(if (= month 12)
`(,(+ day 1) 1 ,year)
`(,day ,(+ month 1) ,year)))
]
@; -----------------------------------------------------------------------------
@racketmod[#:file
@tt{bad}
racket
(define (distance0 p)
(sqrt
(+ (sqr (posn-x p))
(sqr (posn-y p)))))
(define (next-month d)
(if (= (cadr d) 12)
`(,(+ (car d) 1) 1 ,(caddr d))
`(,(car d)
,(+ (cadr d) 1)
,(caddr d))))
]
]
(It is difficult to illustrate this point with a small example. Please
give intermediate names a try.)
@; -----------------------------------------------------------------------------
@section{Structs vs Lists}
Use @racket[struct]s when you represent a combination of a fixed number of
values. Or, don't use lists when structures will do.
Use @racket[struct]s when you represent a combination of a small and fixed
number of values. For fixed length (long) lists, add a comment or even a
contract that states the constraints.
@; -----------------------------------------------------------------------------
@section{Lambda vs Define}
@ -167,7 +182,12 @@ racket
@; -----------------------------------------------------------------------------
@section{Identity Functions}
The identity function is @racket[values]. Try it with @racket[(values 1 2 3)].
The identity function is @racket[values]:
@examples[
(map values '(a b c))
(values 1 2 3)
]
@; -----------------------------------------------------------------------------
@section{List Traversals}
@ -196,7 +216,9 @@ racket
;; examples:
(sum-up '(1 2 3))
(sum-up #(1 2 3))
(sum-up (open-input-string "1 2 3"))
(sum-up
(open-input-string
"1 2 3"))
])
@; -----------------------------------------------------------------------------
@ -216,7 +238,7 @@ racket
])
]
Note: @racket[for] traversals of user-defined sequences tend to be
@bold{Note}: @racket[for] traversals of user-defined sequences tend to be
slow. If performance matters in these cases, you may wish to fall back on
your own traversal functions.
@ -236,18 +258,25 @@ racket
(first (second msg)))
]
@; -----------------------------------------------------------------------------
@racketmod[#:file
@(begin
#reader scribble/comment-reader
[racketmod #:file
@tt{bad}
racket
...
;; Message -> String
(define-syntax-rule
(message-name msg)
;; ===>
;; ==>>
(first (second msg)))
]
)
]
A function is immediately useful in a higher-order context. For a macro,
achieving the same goal takes a lot more work.
@; -----------------------------------------------------------------------------
@section{Parameters}

View File

@ -37,17 +37,23 @@ watching Matthew, Robby, Shriram and others create the original code base}
@nested[#:style 'inset]{@italic{It is the way we choose to fight our bugs that
determines our character, not their presence or absence.} -- Robby, in response}
Complete correctness is a perfectionist goal beyond the reach of PLT. All
Since complete correctness is a perfectionist goal, PLT aims to release
good code and to improve it as soon as possible and necessary. All
software has mistakes. If they are unknown, the software isn't being
used. The goal is, however, to ensure some basic level of correctness
before a feature is released and to ensure that the same mistake isn't
introduced again.
Formulate test suites. Use unit testing. Use random testing. Use fuzz
testing. Test!
Add tests to the appropriate test suites; most are found in
@tt{collects/tests/} in your PLT repository. @margin-note*{Due to
historical reasons, a few collections come with their own local test
suites.} These test suites suggest a culture of testing per tool or
language; follow it. Formulate new test suites in the same collection. Use
unit testing. Use random testing. Use fuzz testing. Test!
Run the test suites before you commit. Read DrDr's emails; don't ignore
them.
Run the test suites before you commit. Read
@hyperlink["http://drdr.racket-lang.org/"]{DrDr}'s emails; do not ignore
them.
When you debug, formulate a test case first. Put it into the test suite for
the component so the mistake will never be accidentally re-introduced.
@ -85,16 +91,12 @@ Editing code without an existing test suite is like flying blind. If there
@; -----------------------------------------------------------------------------
@section{Maintenance}
Comprehensible code is maintainable. Maintainable code must be easily
readable, and the difficulty is that Racket naturally favors the writer,
not the reader. And it is precisely for this reason that we need to obey
rules.
Code is comprehensible when you can understand its external purpose. To
this end, code must come with external documentation. Released code must
have documentation. A change to the external behavior of code must induce
a simultaneous change to its documentation---``simultaneous'' means that the
two changes are in the same commit to the code base.
Comprehensible code is maintainable. Code is comprehensible when you can
understand its external purpose. To this end, code must come with external
documentation. Released code must have documentation. A change to the
external behavior of code must induce a simultaneous change to its
documentation---``simultaneous'' means that the two changes are in the
same ``push'' to the code base.
Without adherence to basic elements of style and some internal
documentation, code comprehension becomes impossible. The rest of this
@ -104,13 +106,14 @@ Without adherence to basic elements of style and some internal
Readability is not the same as code with documentation, but documentation
is a part of it all. For style rules on documenting code, refer to the
@hyperlink["http://docs.racket-lang.org/scribble/how-to-doc.html#%28part._reference-style%29"]{style
guide} in the Scribble manual. Ideally documentation comes in two parts:
a ``Guide'' section, which explains the purpose and suggests use cases, and
a traditional ``Reference'' section, which presents the minutae. Also
consider adding examples for each function and construct in your
``Reference'' section. Finally, ensure you have all the correct
@tt{for-label} @tt{require}s and make use of other useful
cross-references.
guide} in the Scribble manual. Ideally documentation comes in two parts,
possibly located in the same document: a ``Guide'' section, which explains
the purpose and suggests use cases, and a traditional ``Reference''
section, which presents the minutae. The documentation for HtDP/2e
teachpacks is an example where the two parts are collocated. Also consider
adding examples for each function and construct in your ``Reference''
section. Finally, ensure you have all the correct @tt{for-label}
@tt{require}s and make use of other useful cross-references.
Having said that, the production of a system like Racket occasionally

View File

@ -35,11 +35,11 @@ Many pieces of the code base don't live up to the rules yet. Here is how
@emph{Do} run the test suites, and do @emph{not} change the behavior of
the file.
Also, we encourage everyone to look over the commit messages. If you see
problems with the code deltas, let the contributor know. If you see a bug
fix without docs and tests, let the contributor know. Code should be
viewed by more than one person because a second person is likely to catch
logical mistakes, performance problems, and unintended effects.
Also, look over the commit messages. If you see problems with the code
deltas, let the contributor know. If you see a bug fix without docs and
tests, let the contributor know. Code should be viewed by more than one
person because a second person is likely to catch logical mistakes,
performance problems, and unintended effects.
@bold{Request} This document isn't complete and it isn't perfect. Consider
it a call for improvements and suggestions. If you have ideas, contact
@ -53,10 +53,12 @@ Also, we encourage everyone to look over the commit messages. If you see
@; -----------------------------------------------------------------------------
@include-section["correct-maintain-speed.scrbl"]
@include-section["some-performance.scrbl"]
@include-section["unit.scrbl"]
@include-section["constructs.scrbl"]
@include-section["textual.scrbl"]
@include-section["branch-and-commit.scrbl"]
@include-section{correct-maintain-speed.scrbl}
@include-section{some-performance.scrbl}
@include-section{unit.scrbl}
@include-section{constructs.scrbl}
@include-section{textual.scrbl}
@include-section{branch-and-commit.scrbl}
@include-section{acknowledgment.scrbl}
@include-section{todo.scrbl}

View File

@ -260,10 +260,12 @@ rndr-st
sendMessageToClient
trvrs-frst
traverse_forest
])
]
@;
Note that _ (the underline character) is also classified as bad
Racketeering.
Another widely used convention is to @emph{prefix} a function name with the data
type of the main argument. This convention generalizes the selector-style
@ -306,9 +308,27 @@ Finally, in addition to regular alphanumeric characters, Racketeers use a
@row-table[
@row[symbol kind example]
@row[? "predicates and boolean-valued functions" boolean?]
@row[! "setters and field mutators" set!]
@row[% "classes" game-state%]
@row[^ "unit signatures" game-context^]
@row["@" units testing-context@]
@row[? "predicates and boolean-valued functions" boolean?]
@row[! "setters and field mutators" set!]
@row["#:" "keywords" #:dest-dir]
@row[% "classes" game-state%]
@row[<%> "interfaces" dc<%>]
@row[^ "unit signatures" game-context^]
@row["@" "units" testing-context@]
@row["#%" "kernel identifiers" #:app]
]
@; -----------------------------------------------------------------------------
@section{Graphical Syntax}
Do not use graphical syntax (comment boxes, XML boxes, etc).
The use of graphical syntax makes it impossible to read files in
alternative editors. It also messes up some revision control systems.
When we figure out how to save such files in an editor-compatible way, we
may relax this constraint.
@; -----------------------------------------------------------------------------
@section{End of File}
End files with a newline.

View File

@ -0,0 +1,14 @@
#lang scribble/base
@(require "shared.rkt")
@title{Todo List, Call for Contributions}
@itemlist[#:style 'ordered
@item{Write a section on when macros, when functions.}
@item{Write a section on how to design test cases.}
@item{Find and link to good/bad examples in the code base.}
]

View File

@ -290,6 +290,9 @@ With @racketmodname[rackunit], test suites can be defined within the
If your function or method consumers more than two parameters, consider
keyword arguments so that call sites can easily be understood.
Similarly, if your function or method consumers two (or more)
@emph{optional} parameters, keyword arguments are a must.
Please write a purpose statement for your function.
If you can, add an informal type and/or contract statement.