[Style] first round of edits
This commit is contained in:
parent
b14b90655c
commit
11a04cd6fa
|
@ -12,10 +12,10 @@ and readability.
|
|||
@; -----------------------------------------------------------------------------
|
||||
@section{Definitions}
|
||||
|
||||
Here are a few of Racket's definitional constructs: @scheme[let], @scheme[let*],
|
||||
@scheme[letrec], and @scheme[define]. Except for the last one, all others force
|
||||
an increase to the indentation level. We therefore request that you favor
|
||||
@scheme[define] over all other features when feasible.
|
||||
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.
|
||||
|
||||
@compare[
|
||||
@racketmod[#:file
|
||||
|
@ -55,10 +55,10 @@ racket
|
|||
(cond
|
||||
[(empty? l) true]
|
||||
[else
|
||||
(define fst (first l))
|
||||
(define rst (rest l))
|
||||
(and (flat-rate fst)
|
||||
(curved fst (chk rst)))])
|
||||
(define f (fir l))
|
||||
(define r (rest l))
|
||||
(and (flat-rate f)
|
||||
(curved f (chk r)))])
|
||||
]
|
||||
@racketmod[#:file
|
||||
@tt{bad}
|
||||
|
@ -66,12 +66,38 @@ racket
|
|||
|
||||
(if (empty? l)
|
||||
true
|
||||
(let ([fst (first l)]
|
||||
[rst (rest l)])
|
||||
(and (flat-rate fst)
|
||||
(curved fst (chk rst)))))
|
||||
(let ([f (fir l)]
|
||||
[r (rest l)])
|
||||
(and (flat-rate f)
|
||||
(curved f (chk r)))))
|
||||
]
|
||||
]
|
||||
|
||||
Of course you should also favor @scheme[cond] (and its relatives) over
|
||||
@scheme[if] to match the shape of the data definition.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Expressions}
|
||||
|
||||
Keep expressions small. Name intermediate results.
|
||||
|
||||
|
||||
@compare[
|
||||
@racketmod[#:file
|
||||
@tt{good}
|
||||
racket
|
||||
(define (distance0 p)
|
||||
(define x (posn-x p))
|
||||
(define y (posn-y p))
|
||||
(sqrt (+ (sqr x) (sqr y))))
|
||||
]
|
||||
@; -----------------------------------------------------------------------------
|
||||
@racketmod[#:file
|
||||
@tt{bad}
|
||||
racket
|
||||
(define (distance0 p)
|
||||
(sqrt
|
||||
(+ (sqr (posn-x p))
|
||||
(sqr (posn-y p)))))
|
||||
]
|
||||
]
|
||||
|
|
|
@ -122,13 +122,7 @@ Having said that, the production of a system like Racket occasionally
|
|||
@; -----------------------------------------------------------------------------
|
||||
@section{Speed}
|
||||
|
||||
Making code fast is an endless task.
|
||||
|
||||
Making code @emph{reasonably} fast is the goal.
|
||||
|
||||
It is especially the goal for all pieces of the code base that are reused
|
||||
elsewhere. Write them using @rkt/base[] so that they don't affect the
|
||||
load-time for scripts. See the next section.
|
||||
Making code fast is an endless task. Making code @emph{reasonably fast} is the goal.
|
||||
|
||||
As with correctness, performance demands some ``testing.'' At a minimum,
|
||||
exercise your code on some reasonably large inputs. Add a file to the test
|
||||
|
|
|
@ -10,9 +10,9 @@ When you write a module, you first pick a language. In Racket you can
|
|||
choose a lot of languages. The most important choice concerns @rkt/base[]
|
||||
vs @rkt[].
|
||||
|
||||
If you are writing a script, try using @rkt/base[]. The @rkt/base[]
|
||||
language loads significantly faster than the @rkt[] language because it is
|
||||
much smaller than the @rkt[].
|
||||
For scripts, use @rkt/base[]. The @rkt/base[] language loads significantly
|
||||
faster than the @rkt[] language because it is much smaller than the
|
||||
@rkt[].
|
||||
|
||||
If your module is intended as a library, stick to @rkt/base[]. That way
|
||||
script writers can use it without incurring the overhead of loading all of
|
||||
|
@ -21,5 +21,3 @@ If your module is intended as a library, stick to @rkt/base[]. That way
|
|||
Conversely, you should use @rkt[] (or even @rkt/gui[]) when you just want a
|
||||
convenient language to write some program. The @rkt[] language comes with
|
||||
almost all the batteries, and @rkt/gui[] adds the rest of the GUI base.
|
||||
|
||||
|
||||
|
|
|
@ -26,29 +26,25 @@ your code.
|
|||
@racketmod[#:file
|
||||
@tt{good}
|
||||
racket
|
||||
|
||||
@;%
|
||||
(define (conversion f)
|
||||
(* 5/9 (- f 32)))
|
||||
]
|
||||
@racketmod[#:file
|
||||
@tt{really bad}
|
||||
racket
|
||||
|
||||
@filebox[@tt{really bad}
|
||||
@codeblock{#lang racket
|
||||
(define (conversion f)
|
||||
(* 5/9 (- f 32)
|
||||
)
|
||||
)
|
||||
]
|
||||
}]
|
||||
]
|
||||
|
||||
You are allowed to place all closing parenthesis on a line by itself at the
|
||||
end of long sequences, be those definitions or pieces of data.
|
||||
|
||||
@compare[
|
||||
@racketmod[#:file
|
||||
@tt{acceptable}
|
||||
racket
|
||||
|
||||
@filebox[@tt{acceptable}
|
||||
@codeblock{#lang racket
|
||||
(define modes
|
||||
'(edit
|
||||
help
|
||||
|
@ -56,12 +52,10 @@ end of long sequences, be those definitions or pieces of data.
|
|||
test
|
||||
trace
|
||||
step
|
||||
)) ;; <--- bug in scribble: the last two are on their own line
|
||||
]
|
||||
@racketmod[#:file
|
||||
@tt{also acceptable}
|
||||
racket
|
||||
|
||||
))
|
||||
}]
|
||||
@filebox[@tt{also acceptable}
|
||||
@codeblock{#lang racket
|
||||
(define turn%
|
||||
(class object%
|
||||
(init-field state)
|
||||
|
@ -73,8 +67,8 @@ end of long sequences, be those definitions or pieces of data.
|
|||
|
||||
(define/public (is-placable? place)
|
||||
(send state legal? place))
|
||||
)) ;; <--- bug in scribble: the last two are on their own line
|
||||
]
|
||||
))
|
||||
}]
|
||||
]
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
|
@ -85,9 +79,7 @@ on. So use DrRacket's indentation style. Here is what this means.
|
|||
@nested[#:style 'inset]{
|
||||
For every file in the repository, DrRacket's "indent all" functions leaves
|
||||
the file alone.}
|
||||
That's all there is to it. @margin-note{See @secref{correctness}. If you
|
||||
really believe that DrRacket indents some construct improperly, submit a
|
||||
bug report. When the bug report is closed, the discussion is finished.}
|
||||
That's all there is to it.
|
||||
|
||||
If you prefer to use some other editor (emacs, vi/m, etc), program it so
|
||||
that it follows DrRacket's indentation style.
|
||||
|
@ -114,8 +106,6 @@ Examples:
|
|||
]
|
||||
]
|
||||
|
||||
@margin-note{We need more of these rules}
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Line Breaks}
|
||||
|
||||
|
@ -150,8 +140,8 @@ Each definition and each local definition deserves at least one line.
|
|||
racket
|
||||
|
||||
(define (launch x)
|
||||
(define wdt (* 10 x))
|
||||
(define hgt (* 3 x))
|
||||
(define w 9)
|
||||
(define h 33)
|
||||
...)
|
||||
]
|
||||
|
||||
|
@ -160,7 +150,7 @@ racket
|
|||
racket
|
||||
|
||||
(define (launch x)
|
||||
(define wdt (* 10 x)) (define hgt (* 3 x))
|
||||
(define w 9) (define h 33)
|
||||
...)
|
||||
]
|
||||
]
|
||||
|
@ -189,7 +179,7 @@ racket
|
|||
@tt{bad}
|
||||
racket
|
||||
|
||||
(composition ufo-with-flames
|
||||
(composition ufo
|
||||
10 v-delta bg)
|
||||
|
||||
]]
|
||||
|
@ -203,10 +193,8 @@ racket
|
|||
10 10
|
||||
(rectangle 10 100 "solid" "red"))
|
||||
]
|
||||
In this case, the two arguments on line 2 are both short and conceptually
|
||||
related.
|
||||
|
||||
@margin-note{We need more of these rules}
|
||||
In this case, the two arguments on line 2 are both conceptually
|
||||
related and short.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Line Width}
|
||||
|
@ -235,12 +223,10 @@ separated by dashes. Racket code benefits from the same convention.
|
|||
In addition to regular alphanumeric characters, Racketeers use a few
|
||||
special characters.
|
||||
|
||||
@column-table[
|
||||
@col[? ! "@" ^ %]
|
||||
@col[1 2 3 4 5]
|
||||
@col[1 2 3 4 5] ]
|
||||
@;column-table[ @col[? ! "@" ^ %] @col[1 2 3 4 5] @col[1 2 3 4 5] ]
|
||||
|
||||
@row-table[
|
||||
@row[symbol kind example]
|
||||
@row[? predicates boolean?]
|
||||
@row[! setters set!]
|
||||
@row[% classes a%]
|
||||
|
|
|
@ -4,20 +4,44 @@
|
|||
|
||||
@title{Units of Code}
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Size Matters}
|
||||
|
||||
Keep units of code small. Keep modules, classes, functions and methods small.
|
||||
|
||||
A module of 10,000 lines of code is too large. A module of 1,000 lines is
|
||||
tolerable. A module of 500 lines of code has the right size.
|
||||
|
||||
One module should usually a class and its auxiliary functions, which in
|
||||
turn determines the length of a good-sized class.
|
||||
|
||||
And a function (method) of more than 66 lines is barely acceptable. For
|
||||
many years we had a limited syntax transformation language that forced
|
||||
people to create @emph{huge} functions. This is no longer the case, so
|
||||
consider this rule universal.
|
||||
|
||||
If a unit of code looks incomprehensible, it is probably too large. Break
|
||||
it up. To bring across what the pieces compute, implement or serve, use
|
||||
meaningful names; see @secref{names}. If you can't come up with a good
|
||||
name for such pieces, you are probably looking at the wrong kind of
|
||||
division; consider alternatives.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Module Interfaces}
|
||||
|
||||
The purpose of a module is to provide some services. @margin-note{The
|
||||
modules we discuss in this section coincide with files.}
|
||||
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.
|
||||
|
||||
Its interface describes which services it provides, and its body implements
|
||||
the services. At least in principle others shouldn't have to read the
|
||||
implementation ever, but it is quite likely that they have to read the
|
||||
interface.
|
||||
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:
|
||||
|
||||
@centerline{Place the interface at the top of the module.}
|
||||
@;
|
||||
This helps people find the relevant information quickly.
|
||||
|
||||
@compare[
|
||||
@;%
|
||||
|
@ -33,38 +57,27 @@ Its interface describes which services it provides, and its body implements
|
|||
(require "game-basics.rkt")
|
||||
|
||||
(provide
|
||||
;; Strtgy = GameState -> Action
|
||||
;; Stgy = State -> Action
|
||||
|
||||
;; Strtgy
|
||||
;; a person's strategy
|
||||
;; Stgy
|
||||
;; people's strategy
|
||||
human-strategy
|
||||
|
||||
;; Strtgy
|
||||
;; a complete tree traversal
|
||||
ai-1-strategy
|
||||
;; Stgy
|
||||
;; complete tree traversal
|
||||
ai-strategy)
|
||||
|
||||
;; Strtgy
|
||||
;; alpha-beta pruning traversal
|
||||
ai-2-strategy)
|
||||
|
||||
;; ------------------------------------------------------------------
|
||||
(define (general-strategy p)
|
||||
(define (general p)
|
||||
... )
|
||||
|
||||
;; ------------------------------------------------------------------
|
||||
... some 100 lines ...
|
||||
(define human-strategy
|
||||
(general-strategy create-gui))
|
||||
(general create-gui))
|
||||
|
||||
;; ------------------------------------------------------------------
|
||||
... some 100 lines ...
|
||||
(define ai-1-strategy
|
||||
(general-strategy traversal))
|
||||
(define ai-strategy
|
||||
(general traversal))))
|
||||
|
||||
;; ------------------------------------------------------------------
|
||||
... some 100 lines ...
|
||||
(define ai-2-strategy
|
||||
(general-strategy alpha-beta))))
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(racketmod #:file
|
||||
|
@ -76,51 +89,36 @@ Its interface describes which services it provides, and its body implements
|
|||
|
||||
(require "game-basics.rkt")
|
||||
|
||||
;; Strtgy = GameState -> Action
|
||||
;; Stgy = State -> Action
|
||||
|
||||
;; ------------------------------------------------------------------
|
||||
(define (general-strategy p)
|
||||
(define (general p)
|
||||
... )
|
||||
... some 100 lines ...
|
||||
|
||||
;; ------------------------------------------------------------------
|
||||
(provide
|
||||
;; Strtgy
|
||||
;; Stgy
|
||||
;; a person's strategy
|
||||
human-strategy)
|
||||
|
||||
(define human-strategy
|
||||
(general-strategy create-gui))
|
||||
(general create-gui))
|
||||
... some 100 lines ...
|
||||
|
||||
;; ------------------------------------------------------------------
|
||||
(provide
|
||||
;; Strtgy
|
||||
;; Stgy
|
||||
;; a complete tree traversal
|
||||
ai-1-strategy)
|
||||
ai-strategy)
|
||||
|
||||
(define ai-1-strategy
|
||||
(general-strategy traversal))
|
||||
(define ai-strategy
|
||||
(general traversal))
|
||||
... some 100 lines ...
|
||||
|
||||
;; ------------------------------------------------------------------
|
||||
(provide
|
||||
;; Strtgy
|
||||
;; alpha-beta pruning traversal
|
||||
ai-2-strategy)
|
||||
|
||||
(define ai-2-strategy
|
||||
(general-strategy alpha-beta))))
|
||||
))
|
||||
]
|
||||
|
||||
As you can see from this comparison, an interface shouldn't just be a
|
||||
@scheme[provide] with a list of names. Each identifier should come with a
|
||||
purpose statement.
|
||||
|
||||
@bold{Note} Following this documentation guideline is most applicable to
|
||||
modules that are a component of a large application. It is less relevant
|
||||
for a module in the Racket that comes with a full-fledged description in
|
||||
the guide.
|
||||
As you can see from this comparison, an interface shouldn't just
|
||||
@scheme[provide] a list of names. Each identifier should come with a
|
||||
purpose statement. Type-like explanations of data also belong into a
|
||||
@scheme[provide] specification.
|
||||
|
||||
While a one-line purpose statement for a function is usually enough, syntax
|
||||
should come with a description of the grammar clause it introduces
|
||||
|
@ -145,10 +143,12 @@ racket
|
|||
define-strategy)
|
||||
))]
|
||||
|
||||
If the performance of your module doesn't suffer too much from contracts,
|
||||
consider using @scheme[provide/contract]. The use of type-like contracts
|
||||
(constructor predicates that check only a tag) impose a tolerable overhead
|
||||
and still discover simple mistakes.
|
||||
Consider using @scheme[provide/contract] for module interfaces.
|
||||
Although contracts affect the performance of your module's services, they
|
||||
provide a specification and they will help you with the inevitable bug
|
||||
reports you will receive. You should definitely consider type-like
|
||||
contracts (constructor predicates that check only a tag); they tend to
|
||||
cost relatively little.
|
||||
|
||||
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
|
||||
|
@ -157,16 +157,9 @@ Finally, a module consists of sections. It is good practice to separate the
|
|||
chapter headings in DrRacket to label the sections of a module.
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Functions & Methods, Classes & Units}
|
||||
@section{Classes & Units}
|
||||
|
||||
@; -----------------------------------------------------------------------------
|
||||
@section{Size Matters}
|
||||
@section{Functions & Methods}
|
||||
|
||||
Keep functions small. Keep classes small. Keep units small. Keep modules small.
|
||||
|
||||
Anytime a unit of code looks incomprehensible, it is probably too
|
||||
large. Break it up into smaller units. To bring across what these smaller
|
||||
units compute, implement or serve, use meaningful names; see
|
||||
@secref{names}. Conversely, if you can't come up with a good name for such
|
||||
units, you are probably looking at the wrong kind of division; consider
|
||||
alternatives.
|
||||
|
|
Loading…
Reference in New Issue
Block a user