From 4c57167af78dc63b35ffa4d3dafcea799b45a3d0 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Sun, 27 Feb 2011 17:14:53 -0500 Subject: [PATCH] [Style] modules and tables --- collects/scribblings/style/shared.rkt | 6 + collects/scribblings/style/size.scrbl | 17 --- collects/scribblings/style/style.scrbl | 2 +- collects/scribblings/style/unit.scrbl | 172 +++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 18 deletions(-) delete mode 100644 collects/scribblings/style/size.scrbl create mode 100644 collects/scribblings/style/unit.scrbl diff --git a/collects/scribblings/style/shared.rkt b/collects/scribblings/style/shared.rkt index 1b2e36be8d..0de68749cd 100644 --- a/collects/scribblings/style/shared.rkt +++ b/collects/scribblings/style/shared.rkt @@ -14,6 +14,7 @@ (all-from-out scribble/manual)) (provide + codebox compare ;; create a comparison box for two code snippets ;; good ;; label a code fragment 'good' [doesn't work] ;; bad ;; label a code fragment 'bad' [doesn't work] @@ -30,6 +31,11 @@ (define stuff (list (list stuff1) (list stuff2))) (table (sty 2 500) (apply map (compose make-flow list) stuff))) +;; good: a code snippet in a box +(define (codebox stuff1) + (define stuff (list (list stuff1))) + (table (sty 1 700) (apply map (compose make-flow list) stuff))) + (define-syntax (column-table stx) (syntax-case stx (col) [(_ (col x ...) ...) diff --git a/collects/scribblings/style/size.scrbl b/collects/scribblings/style/size.scrbl deleted file mode 100644 index 0e908947db..0000000000 --- a/collects/scribblings/style/size.scrbl +++ /dev/null @@ -1,17 +0,0 @@ -#lang scribble/base - -@(require "shared.rkt") - -@title{Size Matters} - -@; ----------------------------------------------------------------------------- -@section{Code Units} - -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. diff --git a/collects/scribblings/style/style.scrbl b/collects/scribblings/style/style.scrbl index cd01b02541..94a96b000b 100644 --- a/collects/scribblings/style/style.scrbl +++ b/collects/scribblings/style/style.scrbl @@ -52,6 +52,6 @@ create code for the PLT code base. @include-section["correct-maintain-speed.scrbl"] @include-section["some-performance.scrbl"] -@include-section["size.scrbl"] +@include-section["unit.scrbl"] @include-section["constructs.scrbl"] @include-section["textual.scrbl"] diff --git a/collects/scribblings/style/unit.scrbl b/collects/scribblings/style/unit.scrbl new file mode 100644 index 0000000000..a248fcd4c2 --- /dev/null +++ b/collects/scribblings/style/unit.scrbl @@ -0,0 +1,172 @@ +#lang scribble/base + +@(require "shared.rkt") + +@title{Units of Code} + +@; ----------------------------------------------------------------------------- +@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.} + +@centerline{Equip a module with a short purpose statement.} + +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. + +@centerline{Place the interface at the top of the module.} + +@compare[ +@;% +@(begin +#reader scribble/comment-reader +(racketmod #:file + @tt{good} + racket + + ;; This module implements + ;; several game strategies. + + (require "game-basics.rkt") + + (provide + ;; Strategy = GameState -> Action + + ;; Strategy + ;; a GUI-based plug in for people + human-strategy + + ;; Strategy + ;; a complete tree traversal + ai-1-strategy + + ;; Strategy + ;; alpha-beta pruning traversal + ai-2-strategy) + + ;; ------------------------------------------------------------------------------------------ + (define (general-strategy p) + ... ) + + ;; ------------------------------------------------------------------------------------------ + ... some 100 lines ... + (define human-strategy + (general-strategy create-gui)) + + ;; ------------------------------------------------------------------------------------------ + ... some 100 lines ... + (define ai-1-strategy + (general-strategy traversal)) + + ;; ------------------------------------------------------------------------------------------ + ... some 100 lines ... + (define ai-2-strategy + (general-strategy alpha-beta)))) +@(begin +#reader scribble/comment-reader +(racketmod #:file + @tt{bad} + racket + + ;; This module implements + ;; several game strategies. + + (require "game-basics.rkt") + + ;; Strategy = GameState -> Action + + ;; ------------------------------------------------------------------------------------------ + (define (general-strategy p) + ... ) + ... some 100 lines ... + + ;; ------------------------------------------------------------------------------------------ + (provide + ;; Strategy + ;; a GUI-based plug in for people + human-strategy) + + (define human-strategy + (general-strategy create-gui)) + ... some 100 lines ... + + ;; ------------------------------------------------------------------------------------------ + (provide + ;; Strategy + ;; a complete tree traversal + ai-1-strategy) + + (define ai-1-strategy + (general-strategy traversal)) + ... some 100 lines ... + + ;; ------------------------------------------------------------------------------------------ + (provide + ;; Strategy + ;; 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. + +While a one-line purpose statement for a function is usually enough, syntax +should come with a description of the grammar clause it introduces +@emph{and} its meaning. + +@codebox[ +@(begin +#reader scribble/comment-reader +(racketmod #:file +@tt{good} +racket + +(provide + ;; (define-strategy (s:id a:id b:id c:id d:id) + ;; action:definition-or-expression) + ;; + ;; (define-strategy (s board tiles available score) ...) + ;; defines a function from an instance of player to a placement + ;; The four identifier denote the state of the board, + ;; the player's hand, the places where a tile can be + ;; placed, and the player's current score. + 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. + +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. + +@; ----------------------------------------------------------------------------- +@section{Functions & Methods, Classes & Units} + +@; ----------------------------------------------------------------------------- +@section{Size Matters} + +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.