Live data from Hacker News

Twenty five thousand dollars of funny money

rachelbythebay.com

161–170 of 175 posts

Re: Twenty five thousand dollars of funny money

#161
post #57

Earlier quoted context omitted.

Seriously, since everything I work in is denoted as "cents" from backend to frontend, I personally had never understood the need This matches my experience. Obviously actual strict typing has its benefits, but as far as developer ergonomics are concerned, IME you can get about 95% of the benefits just by following a convention of including unit names in identifier names. It's easy to see why this Ruby code might fail…

> [follow] a convention of including unit names in identifier names. appending units to identifiers helps, but it relies on a developer's eyeballs to spot any errors. It would be infinitely preferable if the type system would simply enforce this for you and developers not have to expend cycles reasoning about this stuff themselves.

    but it relies on a developer's eyeballs to spot any errors.
I'm assuming a relatively normal/sane environment where code is reviewed at pull request time, and there is a test suite.

    developers not have to expend cycles reasoning about this stuff themselves
It is not my experience that `launch_rocket(distance_km:)` requires any extra cycles whatsoever.

I mean, as a coder, I'm going to have to be cognizant of the type anyway, even if we're doing `launch_rocket(distance:)` in a strongly typed language where `distance` is something of type `RocketLaunchDistance` or whatever.

I'm not arguing against static/strong typing in general or anything. Definitely lots of times when it is the clearly superior choice.

Re: Twenty five thousand dollars of funny money

#162

Earlier quoted context omitted.

Seriously, since everything I work in is denoted as "cents" from backend to frontend, I personally had never understood the need This matches my experience. Obviously actual strict typing has its benefits, but as far as developer ergonomics are concerned, IME you can get about 95% of the benefits just by following a convention of including unit names in identifier names. It's easy to see why this Ruby code might fail…

Nope, this will lead to the same problem that the OP has discovered, viz., that a dependency update creates silent errors. Unless the argument is a keyword, but everyone is too lazy for that.

I mean, if your coders are too lazy to give identifiers meaningful names, you probably have bigger issues. It takes very close to zero effort.

Re: Twenty five thousand dollars of funny money

#163
post #44

Earlier quoted context omitted.

Seriously, since everything I work in is denoted as "cents" from backend to frontend, I personally had never understood the need This matches my experience. Obviously actual strict typing has its benefits, but as far as developer ergonomics are concerned, IME you can get about 95% of the benefits just by following a convention of including unit names in identifier names. It's easy to see why this Ruby code might fail…

Easy! # not happening unless developer consumes a large number # of drugs distance_miles = 42 launch_rocket(distance_km: distance_miles*1.6) Aaaand we're off by 0.3924km. Enough to fit 4 football fields with a few meters left over. Oopsies Units are hard. Never under-estimate the ability of programmers to think they're converting but get it slightly wrong.

I qualified my answer with a "95%" because yeah, I think it's good enough about that often.

If we're launching physical rockets then yeah, I would agree that that is probably not a job for dynamic typing.

Re: Twenty five thousand dollars of funny money

#164
post #88

Earlier quoted context omitted.

> Our test harness didn't catch it (weird combination of reasons, too long ago for me to remember the details) & it rolled out. This is why I'm pretty dogmatic about variable comparison in tests. This is dangerous and stuff like this has caused a lot bugs to slide though in my experience (and maybe ops): expect(account1.balance).to eq account2.balance This is safe and specifc: expect(account1.balance).to eq 2500 expe…

I fend off the "magic numbers" people with a variable with a name that describes what the magic number is for. var expectedAccountBalance = 2500 expect(account1.balance).to eq expectedAccountBalance expect(account1.balance).to eq account2.balance

That's my approach as well. My idea is I can change the numbers, and it still better come out right. It forces you to think through (and code) things more clearly. It's too easy to write a test with hard-coded numbers that "just happens" to come out right.

Re: Twenty five thousand dollars of funny money

#165

I'm gonna be honest, I had never understood the "strict type" argument until right now. Seriously, since everything I work in is denoted as "cents" from backend to frontend, I personally had never understood the need so I'm part of today's lucky 10,000th.

Somewhat in the spirit of that xkcd issue, may I commend you for adapting your opinions in the face of new evidence. It's a great quality to have

Re: Twenty five thousand dollars of funny money

#166
post #77

Earlier quoted context omitted.

The case you claim requires drugs will happen eventually even if everybody is sober. I've seen it many times, and I doubt I'm the only one. Somebody is tired, or they get the computer to perform some bulk change and get it wrong, or they are doing some rote transformation and they miss a case. If you want to do a bit better, a simple way of handling it is to provide a separate type that handles the abstract quantity…

What you're suggesting is obviously more foolproof for sure. However it's definitely my observation that there are lots of times when we're passing numbers around and we don't need something quite as robust. I'm not sure that replacing every number in an application with a custom type is typically the best use of time, and certainly there are performance reasons why we might sometimes want to pass fundamental numbers…

I wish more languages had keyword arguments. In the unfortunate languages I've used without them (C++/Rust), I usually avoid mixing up units/types through naming, but in the rare situations I do find myself confusing similar but distinct dimensions despite clear naming, I selectively opt into custom types where their utility justifies their interoperability/arithmetic/conversion downsides.

Re: Twenty five thousand dollars of funny money

#167

Earlier quoted context omitted.

You should define separate types for “cents” and “dollars”. And, probably operations to convert between the types.

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…

Yes, good point. This in fact what I've done previously in an application that was dealing with monetary values. They were basically fixnums with a unit piggybacked on, plus some money-specific operations.

The money type should be compatible with generic interfaces so existing sorting and aggregation functions, for example, can directly on them.

Re: Twenty five thousand dollars of funny money

#168

Earlier quoted context omitted.

In the mid-2010s I worked at a company that switched from using raw ints to refer to database rows to using (in C# terms) "Id ". Across the entire codebase, we discovered an entire class of bugs that only never cause any issues because all the important rows in all the important tables had Id 1 (e.g. Currency 1 was USD and Country 1 was USA) - so in a few places where the ints got mixed up, the correct row was still…

how did that work out in the end?

I mean, no problem ever occurred. Things just accidentally worked even though they shouldn't, and that isn't a bug.

The introduction of the additional types everywhere did turn into massive headaches based around dependency management and versioning.

So overall, I was personally disappointed in the results, but nevertheless happy to work with less "icky" feeling code.

Re: Twenty five thousand dollars of funny money

#169

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.

At that point, why not have dedicated types and get rid of primitive ones? It shifts all that work to the compiler, whose job it is to excel at this kind of stuff (adding cents to penny types does the right thing automatically etc).

Because you still have to co-exist with other software beyond the type system's boundaries. The amounts are going to be converted to/from JSON, put in and out of databases, show up in logs etc.

When it comes time to invoke Amount.fromCents(..) at the boundary of the system, it's nice if the front-end posts a variable called amountInCents.

Re: Twenty five thousand dollars of funny money

#170

I think I like the duck typing in TypeScript more than I dislike it. But I still wish I could say “this function accepts a type called RobotName. It’s a string, but so is RobotUuid, and we don’t want that. So only accept, strictly, objects typed as RobotName.”

The simplest way I know of to make a discriminated number type in TypeScript is:

    declare const isRobotID: unique symbol;
    type RobotID = number & { [isRobotID]: true };
and now you can cast a number to a RobotID and back.
Post reply on HN