Revision History |
---|
None so far |
For the details of each problem was graded, here's the so-called rubric.
1 Most of the class has excellent tasteTaste in movies: Pan's Labyrinth, A Clockwork Orange, Saving Private Ryan, In Bruges, and others. My own favorite is Twelve Monkeys, a beautifully conceived and executed time-travel movie; and I hate time-travel movies.
2A Here's one way to do it.
object MyWeight { val MIN_WEIGHT: Double = 40 val MAX_WEIGHT: Double = 75 private var weight: Double = 55 def gain(w: Double): Unit = { val okayBefore: Boolean = weight >= MIN_WEIGHT && weight <= MAX_WEIGHT weight += w val okayAfter: Boolean = weight >= MIN_WEIGHT && weight <= MAX_WEIGHT if (okayBefore && !okayAfter) { if (weight < MIN_WEIGHT) throw new Exception("Weight below minimum") else throw new Exception("Maximum weight exceeded") } } def getWeight: Double = weight } object MyWeightApp extends App { // String that represents a Double to 1 decimal digit of accuracy – def doubleApprox(d: Double): String = "%5.1f".format(d).trim // String that represents MyWeight's weight member to within // one decimal digit of accuracy – def getWeightApprox: String = doubleApprox(MyWeight.getWeight) val HOLIDAY_INCREASE: Double = 5 val NEW_YEARS_DECREASE: Double = 4 val MAX_YEARS = 50 println("Start " + getWeightApprox) var i = 1 try { while (i < MAX_YEARS) { print("Year " + i) print(" gain " + doubleApprox(HOLIDAY_INCREASE)) MyWeight.gain(HOLIDAY_INCREASE) println(" lose " + doubleApprox(NEW_YEARS_DECREASE)) MyWeight.gain(-NEW_YEARS_DECREASE) println("At year end: " + getWeightApprox) i += 1 } } catch { case ex: Exception => { println("\n" + ex.getMessage + "; weight = " + getWeightApprox) } } if (i >= MAX_YEARS) println("Maximum time horizon exceeded; weight = " + getWeightApprox) }
2B There are several possible ways of
amending the spec. However, a spec is not the same as an
implementation, and a revised spec is not a recipe for changing the
existing program. So spelling out details of which parts of the
program have to change and how is not allowed. That said, my
original spec already crossed the line into implementation details,
when I gave the name of the private var
used to store
the subject's current weight. If it's private, then the name can't
be used outside the
classprivate
where it's defined and a spec has no business picking a name for it or
even how it's represented. All users of MyWeight
should know is that the current weight (original weight + all
increments) can be retrieve using getWeight
and changed
using gain
. I violated this rule to make the problem easier
to grade. Mea culpa. So I only took 1 point off
if you violated it even more egregiously.
Here is a nice way to reviseRevise the spec so no exception is thrown as long the weight is moving toward the legal zone:Constant names
MyWeight
should be mutable, but
have three constant public members:
MAX_WEIGHT
: The maximum desirable weight in
kilograms (a Double
).
MIN_WEIGHT
: The minimum desirable weight in
kilograms (a Double
).
This must be less than MAX_WEIGHT
.
INITIAL_WEIGHT
: The initial weight of the entity
being weighed (EBW). We require that MIN_WEIGHT ≤
MAX_WEIGHT
but nothing prevents INITIAL_WEIGHT
from being outside this range.
The object should have two public methods with this behavior:
MyWeight.gain(
w)
:
Records a weight gain of w (a Double
).
The argument w may be
negative. The "header" of gain
is
def gain(w: Double): Unit
MyWeight.getWeight
: Returns the current net weight of
the EBW, defined as the INITIAL_WEIGHT
plus all the changes recorded
using gain
.
The "header" of getWeight
is
def getWeight: Double
If the net weight ever falls
below L or rises above H,
gain
should throw an
exception. (You may create one or two new classes of exception, but
you
don't have to. Just
evaluate throw new Exception(
string describing
what happened)
.)
L is defined as the smaller of the EBW's
initial weight and MIN_WEIGHT
; H is defined as
the larger of the EBW's initial weight and MAX_WEIGHT
.
(This idea is due to one of the students. I don't remember which one,
but if it's you and you want to be acknowledged by name let me
know.)
The point is to allow the EBW to fluctuate outside of the
interval [MIN_WEIGHT, MAX_WEIGHT]
so long as they never
go above their highest recorded weight or below their lowest.
MyWeightApp
should have the object MyWeight
fluctuate up and
down in net weight,
gaining 5 kg and losing 4 kg every year. To make the code easier to
revise, these constants should be written in only one place.
It should print out the lines:
Start: 65.0 kg Year 1: gain 5.0 lose 4.0 At year end: 66.0 kg Year 2: gain 5.0 lose 4.0 At year end: 67.0 kg Year 3: ...
until an exception is thrown. Your program should catch it and print:
Maximum weight exceeded; weight = ...
The program should iterate for at most 50 years; after that you can eat whatever you want. If this happens without exceeding the maximum weight, the program prints
Maximum time horizon exceeded; weight = ...
So no matter what it always prints the final value
of weight
.
Note Taste
Meaning I like many of the same movies.[Back]
Note private
Exactly what private
means in Scala is somewhat
under user control, but the default is roughly as in Java: A private
variable can only be accessed in a class.
Normally that means other objects of the same class
as MyWeight
can access it.
Because MyWeight
is defined with object
, there are no
other objects of the same class.
[Back]
Note Revise
I have made changes here and there for other purposes than
improving the object's behavior. The main other purpose is to clean
up infelicities in the original.[Back]
Note Constant names
I should have read the Scala Style Guide more carefully: the
names of constants are capitalized, but the ALL_CAPS_WITH_UNDERSCORES
convention used in Java is not. I will avoid it from now on, but for
consistency will continue its use in my amended spec.
[Back]