Live data from Hacker News

Twenty five thousand dollars of funny money

rachelbythebay.com

131–140 of 175 posts

Re: Twenty five thousand dollars of funny money

#131
post #41

Had exactly that bug in production, was using ruby on rails & active merchant, and some version change in ActiveMerchant switched from cents to dollars for one of the integrations. Our test harness didn't catch it (weird combination of reasons, too long ago for me to remember the details) & it rolled out. Shortly thereafter I get an anxious customer call that we'd charged their debit card $2500.00 instead of $25.00 a…

Frankly, the ActiveMerchant team broke your trust. There's two things you can do with people you don't trust. Either cut them out of your life, or start verifying everything they tell you. I've dumped libraries with this sort of chaotic 'refactoring' (or not picked them because I could see they had made such poor initial choices that it was inevitable). I've also written unit, integration, or smoke tests for third party code with a high Precautionary Principle quotient, sometimes with its own separate build pipeline that takes green versions of our code to run them against latest of theirs. And for any code we got from a customer or business partner? This is practically a requirement for my sanity. They think that because money is changing hands they can do whatever they want and we just have to eat it. We don't have to eat anything.

That doesn't catch the problem the moment it happens, but most times that's sufficient to catch it before anything hits production.

Re: Twenty five thousand dollars of funny money

#132
post #79

Reminds me of in C# how you can pass either an integer for time (usually in milliseconds) or pass in a TimeSpan object. I always use TimeSpan instead of an integer for exactly this reason.

Similarly, C++11 added a chrono::duration type. It's a massive improvement over the mess of C APIs which might expect anything from nanoseconds to whole seconds.

Re: Twenty five thousand dollars of funny money

#133

I understand this whole scenario is simplified for story's sake but, if there's old_func and new_func, and the new_func call in the else was added that morning, why would the same error of new_func getting the wrong amount of arguments happen weeks before?

This blogger occasionally seems to throw in stories that are made up for the sake of making a point; this is likely one of them, given the inconsistencies.

Re: Twenty five thousand dollars of funny money

#134

I encountered a similar bug at the same company with far worse results. Won't say any specifics about the product impact, but our backend passed around two different kinds of user IDs. Each user had two different IDs, and the ID spaces overlapped. User Alice could have an ID in space 1 that is the same as Bob's ID in space 2. At some point, at least one function expected a "space 1" ID but was being passed a "space 2…

Similar kind of thing, one company I worked for we had two smart-card/badges, I can't remember why. It may have been nothing more unusual than one was the building card, one was the company one.

They had an overlapping ID space. Swipe the wrong one on the printer and you got someone else's print job. In my case I accidentally caused a Senior Director's print job to be printed, and luckily it wasn't anything sensitive.

I had no end of trouble trying to get IT to accept that this was actually a problem.

Re: Twenty five thousand dollars of funny money

#135

Earlier quoted context omitted.

You can have a single type for “money” (or maybe just “us_money”) with separate cents/dollars/mills factories and accessors, and no access to a numeric value except through the accessors. You can do similar things with other dimensions like “length”. Or you can go whole hog, and have a single “type” for unit-aware values from which you can only successfully extract a unitless number by specifying a unit which is dime…

In physics, dimensionality makes sense. How would one handle money? Can it be represented the same way? A new dimension, next to length, time etc? It would allow to express money per time, eg dollars per second, for example.

> How would one handle money? Can it be represented the same way?

Any particular currency can be modelled simply as a single dimension; “money” more generally is more complex. You can either use a single currency of account, track exchange rates for other currencies with it over time, and convert other currencies into it based on the time applicable to the event, or you can track each currency as a separate domain and convert based on the applicable exchange rate for a particular purpose ad hoc based on the specific situation. (There’s probably other approaches that work, but those seem to be, in outline, the most obvious.)

Re: Twenty five thousand dollars of funny money

#136

Just to say it, for measurements that take a unit I am hardcore that you should include the unit in the variable time: `timeSeconds` `distanceMeters` `amountDollars` Have unit tests and everything, but also write your code so that when someone reads it they know as precisely as possible what's going on without other documentation.

Agreed, but I can’t help but think that this is just a poor man’s typings for languages that don’t directly provide them.

Re: Twenty five thousand dollars of funny money

#137

One of the first programming languages I learned was TI BASIC on the TI-89. It had an excellent units (refinement types) system: you could define an expression as a "unit" by prefixing a variable with an underscore, and it came with a bunch of built-in units. A unit expression could thereby automatically convert between types as needed, outputing the base unit. E.g. `5_dollars + 8_cents` would output `508_cents`. The…

I think TI probably copied that from the HP 48, which used more or less the same syntax. The only difference is that the calculation you show would not have been automatically reduced to _N, but you could use the CONVERT or UFACT commands to get Newtons from kg*m/s^2.

In practice, HP's UI made it a lot easier to manipulate quantities tagged with units: hitting the softkey for a unit would multiply the current value by that unit, and using the two shift keys you could either divide by that unit or convert to that unit. If you made a custom menu to put the handful of units relevant to your current problem domain all close at hand, you would need very few extra keystrokes compared with calculating without using the units system. That ease of use is vital; opt-in type safety should be as easy to use as possible, so that users aren't tempted to fall back to the simpler, less safe method.

Re: Twenty five thousand dollars of funny money

#138

Just to say it, for measurements that take a unit I am hardcore that you should include the unit in the variable time: `timeSeconds` `distanceMeters` `amountDollars` Have unit tests and everything, but also write your code so that when someone reads it they know as precisely as possible what's going on without other documentation.

Would you also add other type-related aspects into variable names? `firstNameString`, `ratioFloat`, `colorEnum`? These things should be types, not easy-to-ignore type-encodings into variable names..

Re: Twenty five thousand dollars of funny money

#139

One of the things I really like about f# is thar you can tag even raw numbers with types. And even multiply/divide on those types. https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...

Kotlin has type aliases. This means you can write something like:

  typealias Cent = Int
and then use a type Cent just like you can an Int, with multiplication and everything else. More info: https://kotlinlang.org/docs/type-aliases.html

Re: Twenty five thousand dollars of funny money

#140

One of the things I really like about f# is thar you can tag even raw numbers with types. And even multiply/divide on those types. https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...

Kotlin has type aliases. This means you can write something like: typealias Cent = Int and then use a type Cent just like you can an Int, with multiplication and everything else. More info: https://kotlinlang.org/docs/type-aliases.html

Yes, you can, but you shouldn’t to solve this problem, because typealiases aren’t new types, just–as the name suggests–aliases, so anything aliased to Int is interchangeable with Int and everything else aliased that way, so you still have exactly the same problem.

Also, cents * cents shouldn’t be cents (though cents * unitless ints should be).

Post reply on HN