[Style] first draft wrapped up
This commit is contained in:
parent
11a04cd6fa
commit
ad583ff720
9
collects/scribblings/style/acknowledgment.scrbl
Normal file
9
collects/scribblings/style/acknowledgment.scrbl
Normal file
|
@ -0,0 +1,9 @@
|
|||
#lang scribble/base
|
||||
|
||||
@title{Acknowledgment}
|
||||
|
||||
The rules borrow from many sources. While many helped the authors survive
|
||||
their own coding experience, the first author also conducted focus sessions
|
||||
with the members of PLT and these sessions produced many insights about
|
||||
coding style. Jacob Matthews took the time to write up his thoughts on
|
||||
testing, and they are much appreciated.
|
|
@ -39,6 +39,32 @@ racket
|
|||
]
|
||||
]
|
||||
|
||||
@compare[
|
||||
@racketmod[#:file
|
||||
@tt{good}
|
||||
racket
|
||||
|
||||
(define-syntax (increment! stx)
|
||||
(syntax-case stx ()
|
||||
[(_ s sn fn i)
|
||||
(with-syntax ([w (r #'s)])
|
||||
(define g (ff #'sn #'w))
|
||||
...)]))
|
||||
]
|
||||
@; -----------------------------------------------------------------------------
|
||||
@racketmod[#:file
|
||||
@tt{bad}
|
||||
racket
|
||||
|
||||
(define-syntax (increment! stx)
|
||||
(syntax-case stx ()
|
||||
[(_ s sn fn i)
|
||||
(with-syntax ([w (r #'s)])
|
||||
(let ([g (ff #'sn #'w)])
|
||||
...))]))
|
||||
]
|
||||
]
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Conditionals}
|
||||
|
||||
|
@ -81,7 +107,6 @@ Of course you should also favor @scheme[cond] (and its relatives) over
|
|||
|
||||
Keep expressions small. Name intermediate results.
|
||||
|
||||
|
||||
@compare[
|
||||
@racketmod[#:file
|
||||
@tt{good}
|
||||
|
@ -101,3 +126,152 @@ racket
|
|||
(sqr (posn-y p)))))
|
||||
]
|
||||
]
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Structs vs Lists}
|
||||
|
||||
Use @racket[struct]s when you represent a combination of a fixed number of
|
||||
values. Don't use lists.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Lambda vs Define}
|
||||
|
||||
While nobody denies that @racket[lambda] is cute, @racket[define]d
|
||||
functions have names that tell you what they compute and that helps
|
||||
accelerate reading.
|
||||
|
||||
@compare[
|
||||
@racketmod[#:file
|
||||
@tt{good}
|
||||
racket
|
||||
|
||||
(define (process f)
|
||||
(define (complex-step x)
|
||||
... 10 lines ...)
|
||||
(map complext-step
|
||||
(to-list f)))
|
||||
]
|
||||
@; -----------------------------------------------------------------------------
|
||||
@racketmod[#:file
|
||||
@tt{bad}
|
||||
racket
|
||||
|
||||
(define (process f)
|
||||
(map (lambda (x)
|
||||
... 10 lines ...)
|
||||
(to-list f)))
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{List Traversals}
|
||||
|
||||
With the availability of @racket[for/fold], @racket[for/list],
|
||||
@racket[for/vector], and friends, programming with for @racket[for] loops
|
||||
has become just as functional as programming with @racket[map] and
|
||||
@racket[foldr]. With @racket[for*] loops, filter, and termination clauses
|
||||
in the iteration specification, these loops are also far more concise than
|
||||
explicit traversal combinators. And with @racket[for] loops, you can
|
||||
decouple the traversal from lists.
|
||||
|
||||
@compare[
|
||||
@;%
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
[racketmod #:file
|
||||
@tt{good}
|
||||
racket
|
||||
|
||||
;; [Sequence X] -> Number
|
||||
(define (sum-up s)
|
||||
(for/fold ((sum 0)) ((x s))
|
||||
(+ sum x)))
|
||||
|
||||
;; examples:
|
||||
(sum-up '(1 2 3))
|
||||
(sum-up #(1 2 3))
|
||||
(sum-up (open-input-string "1 2 3"))
|
||||
])
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@;%
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
[racketmod #:file
|
||||
@tt{bad}
|
||||
racket
|
||||
|
||||
;; [Listof X] -> Number
|
||||
(define (sum-up s)
|
||||
(for/fold ((sum 0)) ((x s))
|
||||
(+ sum x)))
|
||||
|
||||
;; example:
|
||||
(sum-up '(1 2 3))
|
||||
])
|
||||
]
|
||||
|
||||
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.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Functions vs Macros}
|
||||
|
||||
Use functions when possible; do not introduce macros.
|
||||
|
||||
@compare[
|
||||
@racketmod[#:file
|
||||
@tt{good}
|
||||
racket
|
||||
...
|
||||
;; Message -> String
|
||||
(define (message-name msg)
|
||||
(first (second msg)))
|
||||
]
|
||||
@; -----------------------------------------------------------------------------
|
||||
@racketmod[#:file
|
||||
@tt{bad}
|
||||
racket
|
||||
...
|
||||
;; Message -> String
|
||||
(define-syntax-rule
|
||||
(message-name msg)
|
||||
;; ===>
|
||||
(first (second msg)))
|
||||
]
|
||||
]
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Parameters}
|
||||
|
||||
If you need to set a parameter, use @racket[parameterize]:
|
||||
|
||||
@compare[
|
||||
@racketmod[#:file
|
||||
@tt{good}
|
||||
racket
|
||||
...
|
||||
;; String OutputPort -> Void
|
||||
(define (send-to msg op)
|
||||
(parameterize
|
||||
((current-output-port op))
|
||||
(format-and-display msg))
|
||||
(record-message-in-log msg))
|
||||
]
|
||||
@; -----------------------------------------------------------------------------
|
||||
@racketmod[#:file
|
||||
@tt{bad}
|
||||
racket
|
||||
...
|
||||
;; String OutputPort -> Void
|
||||
(define (send-to msg op)
|
||||
(define cp
|
||||
(current-output-port))
|
||||
(current-output-port op)
|
||||
(format-and-display msg)
|
||||
(current-output-port cp)
|
||||
(record-message-in-log msg))
|
||||
]
|
||||
]
|
||||
|
|
|
@ -59,3 +59,4 @@ Also, we encourage everyone to look over the commit messages. If you see
|
|||
@include-section["constructs.scrbl"]
|
||||
@include-section["textual.scrbl"]
|
||||
@include-section["branch-and-commit.scrbl"]
|
||||
@include-section{acknowledgment.scrbl}
|
||||
|
|
|
@ -220,8 +220,46 @@ These lines help both writers and readers to orient themselves in a file.
|
|||
Use meaningful names. The Lisp convention is to use full English words
|
||||
separated by dashes. Racket code benefits from the same convention.
|
||||
|
||||
@compare[
|
||||
@;%
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
[racketmod #:file
|
||||
@tt{good}
|
||||
racket
|
||||
|
||||
render-game-state
|
||||
|
||||
send-message-to-client
|
||||
|
||||
traverse-forest
|
||||
])
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@;%
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
[racketmod #:file
|
||||
@tt{bad}
|
||||
racket
|
||||
|
||||
rndr-st
|
||||
|
||||
sendMessageToClient
|
||||
|
||||
trvrs-frst
|
||||
])
|
||||
]
|
||||
@;
|
||||
If you cannot give a unit a good name, consider the possibility that it
|
||||
isn't a proper unit of code.
|
||||
|
||||
You may use dots between parts of names, e.g., @racket[p.x] to suggest that
|
||||
field @racket[x] is selected from struct @racket[p].
|
||||
|
||||
In addition to regular alphanumeric characters, Racketeers use a few
|
||||
special characters.
|
||||
special characters by convention, and these characters indicate something
|
||||
about the name:
|
||||
|
||||
@;column-table[ @col[? ! "@" ^ %] @col[1 2 3 4 5] @col[1 2 3 4 5] ]
|
||||
|
||||
|
@ -233,3 +271,7 @@ special characters.
|
|||
@row["@" units a@]
|
||||
@row[^ signatures a^]
|
||||
]
|
||||
|
||||
Some Racketeers use the suffix of the name to suggest type(-like)
|
||||
information, e.g., @racket[body-xexpr] or @racket[body-xml]. For such uses,
|
||||
a colon is commonly found, e.g., @racket[p:posn] or @racket[p:pair-of-numbers].
|
||||
|
|
|
@ -27,14 +27,55 @@ If a unit of code looks incomprehensible, it is probably too large. Break
|
|||
division; consider alternatives.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Module Interfaces}
|
||||
|
||||
The purpose of a module is to provide some services.
|
||||
@section{Modules and their Interfaces}
|
||||
|
||||
The purpose of a module is to provide some services:
|
||||
@;
|
||||
@centerline{Equip a module with a short purpose statement.}
|
||||
@;
|
||||
Often ``short'' means one line; occasionally you may need several lines.
|
||||
|
||||
In order to understand a module's services, organize the module in three
|
||||
sections below the purpose statement: its imports, its exports, and its
|
||||
implementation:
|
||||
@;%
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(racketmod #:file
|
||||
@tt{good}
|
||||
racket/base
|
||||
|
||||
;; the module implements a tv server
|
||||
|
||||
(require 2htdp/universe htdp/image)
|
||||
|
||||
(provide
|
||||
tv-launch
|
||||
tv-client)
|
||||
|
||||
(define (tv-launch)
|
||||
(universe ...))
|
||||
|
||||
(define (tv-client)
|
||||
(big-bang ...))
|
||||
))
|
||||
@;%
|
||||
If you choose to use @racket[provide/contract], define auxiliary concepts
|
||||
related to the contracts between the @racket[require] and the
|
||||
@racket[provide] sections. A test suite section---if located within the
|
||||
module---should come at the every end, including its specific
|
||||
dependencies, i.e., @racket[require] specifications.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@subsection{Require}
|
||||
|
||||
With @racket[require] specifications at the top of the module, you let
|
||||
every reader know what is needed to understand the module. The
|
||||
@racket[require] specification nails down the external dependencies.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@subsection{Provide}
|
||||
|
||||
A module's interface describes the services it provides; its body
|
||||
implements these services. Others have to read the interface if the
|
||||
external documentation doesn't suffice:
|
||||
|
@ -150,12 +191,29 @@ Consider using @scheme[provide/contract] for module interfaces.
|
|||
contracts (constructor predicates that check only a tag); they tend to
|
||||
cost relatively little.
|
||||
|
||||
@subsection{Uniformity of Interface}
|
||||
|
||||
Pick a consistency rule for the names of your functions, classes, and
|
||||
methods. Stick to it. For example, you may wish to prefix all exported
|
||||
names with the same word, say @racket[syntax-local].
|
||||
|
||||
Pick a consistency rule the parameters of your functions and methods. Stick
|
||||
to it. For example, if your module implements an abstract data type (ADT),
|
||||
all functions on the ADT should consume the ADT-argument first or last.
|
||||
|
||||
@subsection{Sections}
|
||||
|
||||
Finally, a module consists of sections. It is good practice to separate the
|
||||
sections with comment lines. You may want to write down purpose statements
|
||||
for sections so that readers can easily understand which part of a module
|
||||
implements which service. Alternatively, consider using the large letter
|
||||
chapter headings in DrRacket to label the sections of a module.
|
||||
|
||||
With @racketmodname[rackunit], test suites can be defined within the
|
||||
module using @racket[define/provide-test-suite]. If you do so, locate the
|
||||
test section at the end of the module and @racket[require] the necessary
|
||||
pieces for testing specifically for the test suites.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Classes & Units}
|
||||
|
||||
|
@ -163,3 +221,5 @@ Finally, a module consists of sections. It is good practice to separate the
|
|||
@section{Functions & Methods}
|
||||
|
||||
|
||||
If your function or method consumers more than two parameters, consider
|
||||
keyword arguments so that call sites can easily be understood.
|
||||
|
|
Loading…
Reference in New Issue
Block a user