In addition to following the design recipe, we would like you to observe basic style guidelines for your programs. Not observing these very basic guidelines leads to unreadable code.
In general, we use the following conventions:
Write a WHERE clause in your purpose statement to document the meaning of names like this, eg.
rectangle-after-tick : Rectangle -> Rectangle GIVEN: A rectangle r RETURNS: The rectangle that should follow the given one after a tick selected-rectangle-after-tick : Rectangle -> Rectangle GIVEN: A rectangle r WHERE: r is selected RETURNS: The rectangle that should follow the given one after a tick
Use help functions to clarify your intentions in a piece of code. That messy junk you just wrote in your function must have had some purpose. Turn it into a help function so you can document its purpose, and give it independent tests.
Short is good. Long is bad. Period.
Here are two radically different versions of the same function.
bad | good |
---|---|
; ball-after-tick : Ball -> Ball (define (ball-after-tick b) (cond [(and (<= YUP (where b) YLO) (or (<= (ball-x b) XWALL (+ (ball-x b) (ball-dx b))) (>= (ball-x b) XWALL (+ (ball-x b) (ball-dx b))))) (make-ball (- (* 2 XWALL) (ball-x (straight b 1.))) (ball-y (straight b 1.)) (- (ball-dx (straight b 1.))) (ball-dy (straight b 1.)))] [else (straight b 1.)])) |
; ball-after-tick : Ball -> Ball (define (ball-after-tick b) (cond [(would-hit-wall? b) (ball-at-wall-reversed b)] [else (ball-after-straight-move b 1.)])) |
Both always return the same answer. But which one do you understand immediately? Which programming style makes sense? Which will drive the TA crazy?
Last modified: Tue Nov 3 16:26:36 Eastern Standard Time 2015