Hacker News new | ask | show | jobs
by mlthoughts2018 2917 days ago
> “That does not sound like bad software to me at all. It is quite a stretch to say that types changing during the course of software development implies the software is badly designed. This sound very backwards.”

But nobody said that. The parent comment said the system has a requirement to deal with changing types. OK. Sure. Happens all the time.

Solving it by using auto all over and rotating header files, now that is the part that is simply indefensibly bad. It leaves a codebase where nobody can reason locally about any types, because they would be compile-time dependent on which headers you choose, which is insane. Accidentally make one local variable non-auto by annotating a specific type, and suddenly it works with one set of headers but fails indecipherably with a different set.

There are many better approaches, like inheritance-based designs for specialized subtypes, or using discriminated union types and multiple dispatch patterns.

You’re acting as if the parent comment was just talking about mundane refactoring of types here or there, or some small changing requirement, but it’s not at all.

It’s talking about some kind of problem where the commenter claims that huge amounts of types tracing throughout the whole project have to change wholesale by rotating in different headers and relying on auto as essentially a kludge version of whole-program polymorphism.

> “On the other hand, I believe a software that is malleable enough to handle changing types easily during the course of software development is good software.”

I believe that too, which is why this kind of system that relies on the whole codebase having no localized type annotations (so you can’t reason locally about code when you go to refactor or change types, etc.), is so egregiously bad. Making it robust to type changes is a property of how well other developers can modify the code itself and reason about it. Using auto dogmatically like that totally strips away someone else’s ability to do that.

2 comments

> Solving it by using auto all over and rotating header files, now that is the part that is simply indefensibly bad. It leaves a codebase where nobody can reason locally about any types, because they would be compile-time dependent on which headers you choose, which is insane.

I feel that you are overreacting a bit. One of my use cases, for instance, is : https://github.com/OSSIA/libossia/blob/master/OSSIA/ossia/de...

The software I work on performs sometimes up to ~25% better with flat_hash_map - some projects I worked on (as an user of the software) would simply not have been feasible without it or a similar container. Would you seriously consider replacing your map implementation with a variant, or worse, inheritance which forces you to heap allocate and have an additional indirection ? That would be literal madness here, where I'm fighting to make a tick function run in 15 microseconds instead of 20.

The theoretically cleanest solution would of course be to make the whole codebase generic on Map_T. I hope that you see why this is not optimal in C++ when you have ~100 unit test executables - each test will literally need to recompile the whole stuff.

> Accidentally make one local variable non-auto by annotating a specific type, and suddenly it works with one set of headers but fails indecipherably with a different set.

Except it does not because the types conform to the same concepts.

> this kind of system that relies on the whole codebase having no localized type annotations (so you can’t reason locally about code when you go to refactor or change types, etc.), is so egregiously bad.

Nobody said that either. The parent comment specifically said that they have alternate types to provide different performance characteristics and behavior. Such code bases do exist contrary to what you believe.

Don't think of it as an Apple type suddenly replaced with an Orange type on one fine day and your head begins to spin when you try to understand what the code does.

Think of it more like int32_t being replaced with int_fast32_t because you realize you want to port the code to a new architecture due to which int_fast32_t makes more sense now. Now the argument should not appear as "egregiously bad" as you make it look like.

The world of software development is far more heterogeneous than what your experience might have led you to believe.

My particular cases are with various implementations of hash maps and ordered maps that I switch, for instance std::{unordered_,}map, boost::flat_map, pubby::flat_map, tsl::hopscotch_map, ska::flat_hash_map, and a few others.
It’s funny to hear someone say it is “very rigid beliefs” to disagree with dogmatically using auto everywhere just to get polymorphism by swapping header files, which is a far more drastic and brittle belief.

I have worked on systems deploying to embedded devices, so I am familiar with e.g. needing to suddenly change a bunch of code to cause some typedef to refer to int16 because a platform doesn’t support int32, and needing the codebase to be robust to the change. Whatever solution you pick, sacrificing localized explicit type info is not a good trade-off, and ability to read code and locally easily reason about types only gets more critical as the application gets more architecture or performance dependent.

Besides, many systems that need to achieve this same effect do so by either using discriminated union (std::variant) and multiple dispatch patterns, or by designing the different specific subtypes to fit into an inheritance hierarchy, so that switching things to use e.g. different integer precisions is a matter of using a different, specialized subtype. Forcing the use of auto everywhere and switching types by header files would be a nuclear option by comparison.

> ability to read code and locally easily reason about types only gets more critical as the application gets more architecture or performance dependent

Exactly! And using auto for variables with very limited scope where the type is obvious effortlessly does not negatively affect the ability to read code and in my opinion improves the ability to read code.