I'd be more than annoyed if I saw someone name a function "xxInteger()" because it returns an integer.
I don't actually think the first example was that bad, modulo some context. Sometimes even knowing the type for this kind of thing isn't super important to understand what the code is doing; ala opaque types.
Coming from the Apple ecosystem, descriptive names are par for the course. Most code I end up with is written by autocomplete anyways, so writability is less relevant to me. However, when I go back and read the code later, I want to know as much of the intent of the piece as possible.
Generally, I'd name this method according to the role of the result, and not it's type. While "xxInteger()" isn't good, "numberOfXX()" returning an integer type does improve readability and would still be understandable assigned into an auto.
Remember, you're not writing code for you, you're writing code for future you. Or worse, for the next guy who comes into the codebase. They should be able to derive your intent without having to figure out what each method signature is, and reading all the API docs due to lack of code readability.
I agree. When the return type changes now you'd have to change every spot it's called regardless if the return value is used or not. This would be very annoying if you don't have a refactor function in your IDE or if the ammount of changes crosses a company policy trigering a full program test taking days of your time, etc.
The original function name was named poorly however.
I agree. More so in that example where the explicit int return type was used.
One can certainly argue that the original function name isn't good enough, but I would hate to see "type names" being appended to functions (reminds me of the old hungarian programming notation for variables).
I always want my variable names to be as long and descriptive as possible. We're no longer in the teletype era and our monitors are huge. With autocomplete there is no reason to keep variable names short
Thats the only acceptable way to write code, but it doesn't mean that names can't be too expressive, for example I wouldn't accept nameing like this:
> RandomizeArrayPositionUsingFisherYatesShuffle
Since the algorithm detail is something I don't want to think about when I use it and something that the implementer should be able to change without changing the contract.
The problem here is actually is an old one of failing to separate a getter from a command.
It looks like ConjureMagic is causing side effects and modifying the state of whatever class it belongs to.
This is also the reason one can't answer the question "what the heck is a?". If the "ConjureMagic" is only a getter and does not modify class state, it may probably need a better name, like "GetMaxMagicPossible". That renders an auto no longer confusing, because this name explains more than the return type. If, on the other hand this is just a command to conjure the magic and we are getting the remaining amount only to immediately pass it to the member "SetMagic" function, then there was no point in returning this value - it could be done inside the "ConjureMagic" itself.
Having Getters for each member variable always seems fine and reasonable. It's when you have getters that do "magic" that I feel a little.. unsure. Like if it's taking a member and returning it in a different unit that seems kosher... But there is a fuzzy line where at some point the Getter is doing too much work to genuinely be a getter. It gives a false impression for the internal structure of the program. But conveying the const'ness is important as you describe (or semi-constness if you have caching)
I'm of the somewhat unpopular opinion that "getters for everything!" is a philosophy that sounds good on paper, but results in writing a lot of getter and setter functions and feeling safe, while ignoring these sorts of traps cropping up everywhere.
Member variables are easy to reason about; they behave exactly like the type they are, and in the case of built in types, have extremely consistent behavior. Getters / setters are a black box of mystery; I like to reserve that pattern for when there's going to be extra work to retrieve some value, so my call site knows it needs to tip-toe around possible failures. While I can see the value in using getters/setters for everything in something like an API or framework, I don't see the value in trying to use them all the time, "just in case."
In Herb Sutter's words, avoiding auto since it makes the code "unreadable":
...reflects a bias to code against implementations, not interfaces. Overcommitting to explicit types makes code less generic and more interdependent, and therefore more brittle and limited. It runs counter to the excellent reasons to “write code against interfaces, not implementations”
The "unreadable" or "annoying" example from the article is only unreadable and annoying because the programmer was new to the project when he read the two offending lines of code.
I believe Stroustrup is correct that we're all beginners at some point, but we quickly move up. It makes more sense to optimize for "proficient, but not expert" than to optimize for "beginner," because more people are at the proficient level, and they stay there longer.
I agree that code shouldn't be unnecessarily complex. But I would quit any project that constantly brought up "but what if a programmer were brand new when they looked at this code?" in reviews. Then again, if other programmers have the same reaction, perhaps the project really would be full of nothing but beginners.
Why this dismissive comment? auto is definately overused in ways that are unreadable, exactly like the blog author says.
Marking the type explicitely may be less generic in a way, but it helps readability so much by providing redundancy.
The author only gives two problematic usage examples, the first of which (ConjureMagic) nercury correctly addressed earlier as a symptom of poor OO design (related to the 'code to implementations' quote above).
The second issue (async) is quite similar in my opinion, and in practice your async handler will be explicitly decoupled and strongly typed at some point for reasons of testability so the example is describing also an OO design issue and not an issue with auto.
There may be real problems with auto but this article did not provide any compelling evidence of them.
auto, the new range for and lambdas are my most used C++11 features. Also make_shared/make_unique.
auto ptr = make_shared<T>()
Reads very nicely so I agree that if the type should be somewhere in the auto expression. That is, use auto to remove redundancy. I just wish they would have extended type deduction to lambda arguments so I could do:
auto with lambdas can be quite dangerous if you are adding different types inside their bodies. Type promotion rules should be well understood. During code reviews we spotted several overflow bugs when using ints because the dev were thinking auto as a sort of very powerful resource.
Explicit casting if often required to make sure subtle bugs won't show up in production.
Unfortunately all the ides I tried make it non trivial to write extensions. I program nearly 9 hours a day and using a tool that prevents automation of common tasks is suboptimal.
To clarify, with plugins such as ctags, rtags and YouCompleteMe. I would never be able to write large C++ programs in vanilla vim. Maaaybe plain C, but definitely not C++.
Somewhat related, C++14 gets 'auto' for function return types, which really makes me nervous (C++11 has a form of this, but not as powerful).The D programming language uses 'auto' as the return type for many of the functions in the standard library and this makes it, IMO, somewhat cumbersome to use.
In general, I don't think C++ (or D) devs should be using deduced return types in the public interface, if at all possible.
So auto allows you to deal more easily with c++ crap, especially STL.
My first thing to do in all my c++ project is to import my in-house STL wrapper, which makes STL usable for me.
I never understood how people can work with raw STL. I don't like at all working with templates and i am using it only in internal class implementations.
C++ without templates is so much more beautiful.
std::unordered_map<std::string, SomeClassName>::iterator it = hashmap.begin();
vs
auto it = hashmap.begin();
I find auto useful for cutting down some of the verbosity of templates STL containers, but I can see how over use can lead to code requiring much more referencing if maintaining code that rarely defines types.
I think one of the key things that makes 'auto' much more painful than 'var' is that in Visual Studio, the intellisense in C# is much more reliable than C++. Any ambiguous statement like the first example is quickly and resolved in C# with a quick F12. In C++, this doesn't always work especially when you're using any kind of cobbled together or hybrid build system.
A lot of times, the type is unimportant but when it is, this kind of usage can bloat a simple task into 5 to 15 minutes of hunting through headers or grepping.
It's strange to think of an IDE feature so impacting a language feature. The stack is not supposed to affect in that direction but this is one case where it really does.
The example at the start would be equally mildly confusing if it was written as SetMagic(ConjureMagic());. The problem is not the auto. It's a normal case of non-ideal function names.
I don't actually think the first example was that bad, modulo some context. Sometimes even knowing the type for this kind of thing isn't super important to understand what the code is doing; ala opaque types.