Google's C++ dialect itself calls this out as a bug, not a feature:
"On their face, the benefits of using exceptions outweigh the costs, especially in new projects"
https://google.github.io/styleguide/cppguide.html#Exceptions
EDIT: Personally I like no exceptions normally but there's definitely classes of problems where exceptions are overwhelmingly superior, such as anything hitting files or a wire (eg, IPC). Serialization code is incredibly tedious to do error checking after every read or write call. This is where I think the "throws" proposal strikes the right balance: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p070...
> and, here's the big one, individual teams were expressly forbidden from creating their own templates.
There's no such rule. It just says avoid them if you can, otherwise go for it: https://google.github.io/styleguide/cppguide.html#Template_m...
And if there was such a rule, then Abseil wouldn't exist. You don't end up with your own template library by telling people to never write templates.
For a large number of people, exceptions is essentially interchangeable with "output log message and exit".
> And if there was such a rule, then Abseil wouldn't exist.
You misunderstand me. What I call "leaf nodes" don't (or shouldn't) create their own templates. By "leaf nodes" I mean, say, the payments logging team. They're created by specialists. Specifically, abseil is created from "//base", which is a mature battle-tested set of libraries at this point.
Likewise, anyone can create something in base or just modify something that's there but any such addition or change is going to go through an awful lot of scrutiny and testing.
That's the point.
Just to give an example of someone else advocating for top-down problem solving, Bjarne advocates strongly for designing the libraries that you will need before writing specific code for your problem. He has some example videos where he goes through a code review taking some piece of procedural business code and showing how it should have been written to take advantage of existing libraries and creating new ones before.
When were you at Google? I've been here a lot of years and never ever heard this. My codebase has a fair amount of templated code, including some metaprogramming magic. Nowhere has any tool said "please don't do this", nor do I think it should. Complex template code can be an absolute nightmare to maintain, but there is a group of C++ experts that are available to help if it is indeed the best solution to a problem and you want to devise a maintainable implementation.
The closest in the style guide I can find is "Avoid complicated template programming," which is clarified to include metaprogramming magic. This is very different than what you write and not even "forbidding" it.
Certainly at that time, creating your own templates was explicitly disallowed by the C++ style guide (ie readability requirements). The public style guide mentions template meta-programming specifically [1]:
> The techniques used in template metaprogramming are often obscure to anyone but language experts. Code that uses templates in complicated ways is often unreadable, and is hard to debug or maintain.
This certainly applied to Google3. Non-Google3 C++ code bases could and did have their own standards and style.
General note: templates were created but by library/framework teams who specialized in that. The way I like to put it, creating templates was a job for branch nodes not leaf nodes.
[1]: https://google.github.io/styleguide/cppguide.html#Template_m...
My codebase overlaps with the majority of your tenure at Google. We are in google3.
I do agree with the guidance that things like SFINAE should be avoided in general, but I believe you've way overstated the rigidity of the guidance.
I think creating e.g. template<F> F MyComputation(const F& x) would be allowed e.g. for supporting both float and double. It would also be required when using the Ceres optimization library.
Just want to underscore what others are saying, that this is not true and was not true during the time you claimed to work there. I was at Google 2014-2016 and I'm there now. Templates are common and not banned at all. I committed template-heavy non-metaprogramming code to google3 in 2014 and also throughout this year. I have never had C++ readability.
"Template Metaprogramming" is soft-banned in non-library code, meaning that it is disallowed if the readability reviewer looking at your code decides that what you are doing is "metaprogramming".
There are other style guides that apply to small subsets of google3, some of which forbid certain kinds of template constructions (variadic, SFINAE, etc). Maybe you're thinking of one of those? I'm not aware of any that forbid all templates.
L7’s should write code that only needs L4’s to maintain.
Can I ask if this has a source? From a particular company? Meme? Quote? Paraphrased from something?
Likewise, if you write code that only you and someone smarter than you can understand, you don't understand it.
That does bring a risk though. If you write simple code (e.g. in Go) that does what it does without any trickery, a more inexperienced job interviewer may look at it and scoff because you're OBVIOUSLY not a very good developer if you stick to simple code.
But that's a good litmus test, if they're like that, run away. They don't write code to solve a problem, they write code to flex and impress themselves, or to provide them with job security, or CV boosts.
Not to tangent too much but this is exactly how I see javascript. I learned it one way, some code I need to use learned it a different way, and I have to choose whether to attempt to integrate it as-is, or spend the time to "port" it to my understanding.
Sidenote: The style guide (recently?) removed the ban on non-const references [0]. They are now allowed for non-optional output parameters. Though returning value is generally preferred over output parameters.
[0] https://google.github.io/styleguide/cppguide.html#Inputs_and...
I don't get it? What's wrong with returning a bool?
Contrived example:
bool connectToHost(string hostname, bool useSsl);
First problem: if it fails, why does it fail? Some will be tempted to throw an exception. Better is to return some kind of status.Second problem: you add another version of SSL, now what? If you'd used an enum, it's just another value. If not, you now need to retrofit it.
Better version:
absl::Status connect(string hostname, EncryptionType encType);
People will often make mistakes when a function has 3 or more booleans and put the wrong value in the wrong parameter. With strongly typed arguments, this becomes a compiler error.People will extend booleans to add a third value. In Java, for example:
Optional<Boolean> foo
But it doesn't end there. As I like to say, for when three values for your boolean just aren't enough: @nullable Optional<Boolean> foo
Just start with enums.of anything. This is why non-compatible numeric subtypes are so valuable. Code like "quantity_sold = price" should not compile. You can do the same thing for other types using the same template but IME that's somewhat less common (but does happen: user_name = address!!).
It would be nice to get a variation on std::pair that works in a similar way to Rust's std::result<value, error>, because std::optional is just a dressed up boolean. I did just swipe the std::pair declaration and do that, but having it official would be nice. Especially for the non-throwing version of the standard libraries.
A function with three or more positional parameters in a language that isn’t badly broken (that is, one that supports keyword and/or structured parameters, which pretty much all significant languages do) is, IMO, a code smell. Even if more specific typing and IDE pulling up signatures can makes it less likely to make usage errors, readability is impaired.
This means anytime you operate on a boolean, you must somehow recover its interpretation from somewhere, and the argument is that such recovery is error prone and fragile.
The preferred way, presumably, is then to encode the interpretation directly into the type, so for example you use an enum along with pattern matching, or you write a type that wraps a boolean with some value (like a Maybe/Optional type). In effect anytime you have a boolean, you also carry with it its interpretation side-by-side so you don't need to go figuring out how to recover it.
This article goes into it in more depth:
https://existentialtype.wordpress.com/2011/03/15/boolean-bli...
I personally think it's insightful and useful, but there are also downsides to it as well, for example when you need to operate on multiple booleans, it becomes unergonomic and bloated to deal with pattern matching over multiple enums or having to write out a lot of redundant code instead of operating on boolean operators.
Basically consider these two options:
Option 1: boolean blindness.
bool isEven(int value);
...
if(isEven(x)) {
print("Even");
} else {
print("Odd");
}
Option 2: Enum enum Parity {
EVEN,
ODD
};
Parity getParity(int value);
...
switch(getParity(x)) {
case: Parity::EVEN:
print("Even");
break;
case: Parity::ODD:
print("Odd");
break;
}
You can decide which if the two options above is more appealing to you in terms of reading and writing.Actually, I totally hate the google style guide. The prescriptions about indentation there seem to be optimized to make the code as unreadable as possible. An indentation of only two is already too little and adding that the opening brace is at the end of the line it becomes very difficult to see what block ends where.
So, no-one writes C++ except for some organization that tightly controls their work? :-( And no large organizations allow for some coding autonomy in writing, say, the insides of libraries and components?
> Google's C++ dialect
With changing language versions, dialects change. For example, union types: With C++17 you have variants; which are still a bit painful compared to other languages' union types, but are usually an improvement over just using unions and crossing your fingers you've always been careful with them.
> side note: this was a giant language fail that foo(f) could be a const reference or a non-const reference and there's no way to know without looking at the declaration
C and C++ have a lot of implicit type conversions. It's fair to be against that, but it's not like this specific aspect is a "giant fail" in itself; it makes sense, consistensy-wise.
> Facebook's dialect:
Those aspects you describe are indeed annoying, but, again - are we talking about recent code?
> The depth of knowledge required to create templates that don't behave unexpectedly ... is so large that only specialists should engage in it.
I disagree. If you're not obviously careless, your templated types will be reasonably well-behaved.
What do you mean by this? General template code was forbidden or just templated containers, STL style?
I interview C++ programmers for my day job, and no, this isn't true at all.
I think you're just repeating internet memes.
The parent comment is merely saying, "It's well known that no one really uses all the features of the C++ programming language productively" in a rhetorically interesting manner.
Personally I found Google's C++ dialect to be sane, even pleasant. No exceptions, no mutable reference parameters (side note: this was a giant language fail that foo(f) could be a const reference or a non-const reference and there's no way to know without looking at the declaration), pervasive use of union types (absl::Status/StatusOr are the open source versions) and, here's the big one, individual teams were expressly forbidden from creating their own templates.
Now compare this to Facebook's dialect: exceptions allowed, mutable reference parameters allowed (side note: people weren't strict with const-ifying reference parameters so you actually didn't know if something was actually mutated or not), functions that routinely just return bool (so helpful) and you can create your own templates.
But seeing this post makes me see the wisdom in not only how cut down Google's dialect is but also that stopping teams creating their own templates is the only sane choice.
The depth of knowledge required to create templates that don't behave unexpectedly (eg dangling references, redundant copying, useable with move semantics, etc) is so large that only specialists should engage in it.
There is a certain breed of programmer who will use a feature of a language because it's there. They will view esoteric features, unnecessary complexity and brevity over readability as not only virtues but goals with which they can tell the world how smart they are.
If you write code for you, you're either doing it alone or you're not a team player. You write code for the next person who comes along and has to figure out why it's broken or just how it works, not to be as clever as you would like to think you are.