4 ms·
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, o
by tom_ 4y ago
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 (distance, money, etc. - you'd probably want to be cleverer about money if you deal with multiple currencies though), and ensure that values of that type can be converted to and from numbers only when the units are explicitly specified.
So then you end up with functions that consume a distance looking something like this:
void launch_rocket(Distance distance) {
call_ancient_fortran_routine(get_miles_from_distance(distance));
}
And functions that create distances looking something like this:
launch_rocket(create_distance_from_km(100));
What you now can't do is create a value that's of one unit, and pass it to something that expects another unit - the issue doesn't really arise, as Distance values themselves don't have specific units. They are a black box that somehow encodes a distance, and you specify the units used explicitly when initializing and you specify the units desired explicitly if retriving an actual number.
(Turning a distance into a number would ideally be a rare case, though sometimes you'd need it. You'd provide maths functions for all operations required, so you'd hopefully rarely need the number for calculation purposes. For displaying in any UI, there'd be a function to convert it to a string that respects the user's locale and distance unit preferences. And so on.)
- JohnBooty 4y agoWhat 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 around instead of complex types. In those cases, adding units/types to identifiers offers an awful lot of value for close to zero effort. 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. I've never seen it, but that's probably because in my 25 years of writing code I have rarely seen the convention followed in the first place because coders tend to be aggressively disinterested in writing maintainable code. But seriously, if `launch_rocket(distance_km: distance_miles)` eludes the original coder and the code reviewers and future coders working with that code and it eludes your test suite... damn. You've got big problems.
- nyanpasu64 4y agoI 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.