From: Robert Klemme Date: 2012-04-19T18:03:22+09:00 Subject: Re: When are numbers NOT Magic? Example. On Thu, Apr 19, 2012 at 7:30 AM, Greg Willits wrote: > Setup: a bunch of floating point values displayed on a web page. > Essentially a dashboard of a bunch of measured things. Each number has a > distinct engineering-based relevance to the precision which is > displayed. In other words, it's not a repetition of money values where > of course you would create a MONEY_DISPLAY_PRECISION constant for 2 > decimal places to centralize that definition. > > Each value has unique units. > > Each value's precision is uniquely meaningful based on real-world > measurement technology and accuracy. Changing one value's precision > doesn't mean you'd want to change any of the others. > > Each value is displayed in only one place in the application. So there's > no incentive to create a constant to prevent redundant literals. > > The precision is not something the user can choose. The application must > hard code the displayed values, because the precision is meaningful. So > there's no incentive to have a variable. > > The software has a generic method to render a floating point number as a > string with thousands separators and with a specified precision. > > SomeClass#float_as_thousands_with_precision(value, precision) > > Which would get used something like: > >  <%= float_as_thousands_with_precision(volts, 1) -%> > > >  <%= float_as_thousands_with_precision(amps, 2) -%> > > >  <%= float_as_thousands_with_precision(watts, 2) -%> > > > I contend, those are NOT magic numbers. Certainly not. > Using the above definitions (and others I found like them), such numbers > do not need constants because: > -- each number is a single instance (no redundancy) > -- each number is independent from the other (no shared cause & effect > on precision) > -- each number's purpose is very clear from from both the  function name > and argument name (no need to clarify purpose) But a constant's name goes a long way in documenting the meaning. > I know somone out there will say, "well, why not make a constant for > them? What does it hurt?" > > I say, why do it? It's more code to maintain with no benefit. Oh, you do get benefits: - documentation - error checking (using a wrong value will show) They are not magic numbers, by no means. Do they require constants? It may turn out there are better solutions around. For example: MeasurementValue = Struct.new :val, :precision do def to_s float_as_thousands_with_precision(val, precision) end end The place in code which creates the value is certainly the one which knows what type the data really is. By bundling information at that place it cannot get lost. But now we have bundled display semantics with a data type. It's probably better to separate things. MeasurementValue = Struct.new :val, :kind ... FORMATS = { :velocity => "%4.2f", :speed => "%10.1f", } def FORMATS.show(mv) sprintf self[mv.kind], mv.val end <%= FORMATS.show(volts) -%> Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/