I work at Google. This video barely scratches the surface of Google's C++ style guide. IMHO, the style guide is a wonderful thing, and makes C++ a pleasure to work with at Google. Although your preferences may not agree with every little detail, the consistent application of the style guide across a massive codebase is highly valuable to everyone that will ever lay eyes on your code. There could easily be hundreds or thousands of engineers that interact with your code - interfacing with its API, extending it's functionality, debugging it, improving it's performance, etc. Every decision made by the style guide is one less thing all those engineers have to consider.
Agreed, google C++ is the really nice to work with. I also really love the absl and base libraries. I was intimidated at first by how large the codebase was but the consistency and cleanliness of the code helped a lot
just the no exception rule is so nice. I hate exceptions in C++. It's not like in Java where you can declare "throws". You have to understand all the callers. And you have to trust that someone doesn't add an exception in the future and breaks your code.
I like reading 90s C++ projects, they released the source code for 3D Movie Maker recently and been reading through that. It delves you into another time, a 'simpler' time.
One of my favorite videos on UA-cam, I never even thought of looking at style guides. With a good amount of C++ under my belt I can totally see these guides being useful
You would figure everyone would know by now that most inheritance is shit but I guess there's still people out there crafting the most illegible polymorphisms possible.
"OOP vs _" is a dumb conversation most of the time, just use the best tool for the work, while taking into account the conditions and project you currently are in.
@@prumchhangsreng979 Inheritance is useful for interfaces. A Base class defines the interface, and then Derived1 provides the implementation. You can create Derived2 and Derived3 with different implementations of the same interface. It's very useful. People get stuck by putting implementation details in the base class and then trying to change or get around it in the derived classes. Wrong. Factor it out and include it as necessary in derived classes. The classic example is vector. Nobody extends from vector, they include it as needed.
My absolute favourite is working on a code base where a class inherits class templates that inherit other templates that inherit an interface. That's the ultimate in "FU figure this out" coding..
I never write any comments on YT but I really feel like doing it this time. I'm a C++ developer and it's my first job ever (same thing for my teammates), so we struggle with many of these details every day because I think it's quite hard to decide on your own which is the best practice. It's nice to know it's not only me and that it's a real deal out there to write good code in C++ (I also thought those many details of the language make it very powerful but difficult to manage correctly, but I thought it was just me being an inexperienced engineer). I really enjoyed this video, I would also like to see more C++ guidelines and stuff (obviously). Keep up the good work!
In C++, having an explicit style-guide that is enforced in code-reviews (and preferably by some automatic linters too) is absolutely essential. C++ is just too bloated with 40 years worth of legacy features that often interact with each other in weird ways. You have to pick some subset of C++ that all of you understand and use only that subset. Many such style guides are publicly available. You can copy them or take inspiration and make your own.
@@KohuGaly Thank you! We try to use C++ 11, which we found quite readable, but tbh we don't strictly follow any standard. Most of the code that we inherited was programmed in a C style (but with classes) instead of C++ with a standard, so that poses a problem.
@@ToCarlosHuevos I know exactly what you mean :-D I recently got a job as a embedded automotive C/C++ developer. The standard used there is MISRA C++. The oldest parts of the code base pre-date the standard and are literally written in C. "Fun" fact: MISRA C++ forbids all forms of pointer arithmetic except indexing into fixed-sized arrays. If you read the last two sentences and have basic experience in C and C++, you know exactly why "Fun" is in quotes. 😀
@@KohuGaly Hi, I'm sharan. I'm working in a startup called Yali Mobility. We are making electric three wheeler for wheelchair users. I'm just a year old experienced programmer. Currently I'm the only person who programs the vehicle. So I'm struggling alot, kindly help me in some way like standardization of the code etc. This may help us to make the work flow and performance of the code much better. Thank you
@@sharana.p5921 Hi Sharan. Unfortunately, you are probably more skilled in C++ than I am. I was just lucky to land a job in a large corporate, with a lot of pre-existing expertise and know-how to learn from. Not gonna lie, writing software for a road vehicle, as a 1-year-of-experience solo developer... that sounds like a pretty reliable way to kill someone by software bug.
Great video! A few things, from a Google engineer (not speaking for the whole company, of course). 1. We absolutely have tech debt. These things help reduce certain kinds of tech debt, but it still exists all over the place. We're not magical; we make bad choices which we're then stuck with. 2. The lexical code style goes beyond just tabs vs spaces. Our code review system will yell at you if the code isn't formatted according to whatever clang-format would produce. Our style guide for indentation, line breaks, etc, is just "run clang-format and use that". I don't always like the choices which clang-format makes, but it's infinitely better for everyone to use the same standard than for me to use a standard I like more, but for diffs to be larger due to whitespace changes. 3. An important part of the style guide boils down to "don't get clever with template metaprogramming." I've been writing C++ for about 3 years now, and as soon as things get beyond the most basic template usage, I'm lost. If you're relying on SFINAE, you should probably reach for a different solution. Same thing once you start dealing with rvalues and lvalues. There are some places where those features really do make sense, but for things like "call this service. If foo is greater than 25, set bar to true", you probably don't need that stuff.
@@TheOnlyAndreySotnikov Dude, do you work with someone else code beyond your own? Templates can get really confusing. It's all abstraction so there is certain difficulty to comprehend someone else idea in form of code, specially if it doesn't read well. I spent many hours trying to decipher what author had in mind while creating his solution to problem so speaking from experience (just lately I had to decouple 3000 lines long class implementation written and edited by different people). It included weird lambda expressions and templates.
@@anonimowelwiatko9811 Dude yourself. The most frequent source of complaints about templates is a lack of education. Software engineering is a unique field. In any other area, you can't say: "or, integrals is a too complicated abstraction for me," and claim you know calculus. Not only that but in software engineering, you can also force all your colleagues to dumb down to your level and never use integrals in 𝘵𝘩𝘦𝘪𝘳 work. In any other profession, you just shut up and learn. In software engineering, you complain. Meanwhile, not "professional" programmers successfully learn, write, and maintain huge packages written in TeX, which is way more complicated to comprehend than C++ templates. So, 𝘥𝘶𝘥𝘦, learn and practice.
instead of SFINAE you should use more modern features like concepts and if constexpr from c++17 many things that are written in older versions of c++ can be written more clearly and using less "magic syntax" in the latest versions of the language (c++20/23)
The multiple inheritance example is bad imo, because in that case you should actually let "Child" inherit from "Person", and not "Mother" and "Father". Inheritance is usually used to generalize something and abstract it away, like a "Table" is a type of "Furniture", but not a child is a mother and a father.
Definitely agree, he could have used a better example there. To expand on your furniture idea, you could have something like a "convertible sofa" that inherits both from "bed" and "couch," which are themselves inheriting from "furniture."
Mother and Father are Persons after all, so I see no issue here. Child referes to them being child classes, but that doesn't mean the example is incorrect. As you said, inheritance is there to generalize something and Person is more general then Mother and Father, they are something more specific.
@@2JulioHD I think @ruarq1510's broader point here is that the Child/Mother/Father example is confusing because it conflates biological "inheritance" between children and their parents with class "inheritance" between a subclass and its base class. It reinforces a metaphor that is not particularly good to begin with.
@@2JulioHD Yeah, but you usually say „a mother is a type of Person“ or „a father is a type of person“, that’s how inheritance works. In the example it doesn’t make sense to let „Child“ in inherit from „Mother“ and „Father“, since a child is a person and not a mother or a father. Instead, the Child class should have the mother and father class as an attribute. In the real world, yes, a child inherits the genes from their parents, but genetic inheritance is not the same as inheritance in programming, it’s a completely different thing. You also can’t generalize a child to be a mother or a father, but that’s what polymorphism does.
@@2JulioHD Inheritance should be logical. Is a ? And this should follow through the inheritance structure. In this case, mother and father are both people. Child is a person. But child is not a mother nor a father, and especially can't be both at the same time.
4 spaces has always been the standard for tabs. see ansi for the real world proper use of tabs. google has retards running the show and the two tab mandate has already hurt their developers immensely. but they would never tell the truth.
The worst Java code I've ever seen was part of (Googles) easier mediapipe API. They had DEEP Inheritance, manually written getters and setters which contained a few surprises (like giving back properties that already had their own getters), made intensive use of method overloading and inherited methods including methods, and these methods often took parameters that were named in a way to imply they had a certain function, only to be thrown away/used in a different way, or they were actually set, but that didn't matter as at a later point in the lifecycle these values would be overwritten before doing anything. Combine that with the need to also use the not easy and not well documented camera2 API (which they combined with some parts of CameraX) and that under all that Spagetti mess they used JNI to call C++ code that also wasn't particularly well documented, and I got nowhere but sure wasted a lot of time thinking I finally got to the target. Honestly, while we're at this, LARGE swaths of the Android API require you to use implementation Inheritance, so thanks for forcing me to do the things you forbid your engineers to do Google. Sorry for the rant, I'm still super salty from that experience. What they archived with mediapipe is remarkable, and it's nice they made it open source. But mediapipe did not keep it's promises (real time body tracking on IOT, pretty much every mobile - top models released after mediapipe - we tried didn't get over sustained 10 FPS, while being at best at a mean of 18 FPS), and the API was a nightmare and not at all flexible enough for our needs.
Google has tens of thousands of engineers working across hundreds of projects. Whoever developed this style guide probably doesn’t even touch Java code in his day-to-day.
Android was a purchase for Google, had nothing to do with it in the core. So no wonder its code does not follow Google’s guidelines. Besides, those guidelines changed a lot from the 1990s to 2000s, then to the 2010s, and then to the 2020s, so Google’s catalogue of code is a huge nasty mess. Probably only MS is worse than Google.
Great video and all... just please don't build an inheritance relationship Child -> Mother, Father -> Person. Even with inheritance as a concept, that does not make sense. But especially in C++, inheritance means "is-a" and a Child is not always a Mother. Everything that would apply to Mother, would also be applicable to Child under C++.
1:26 Yeah, that's the point of tab. That everyone who reads the code can configure it the way they want to be. That way no matter who looks at the code, it will always be with the indentation the person feels comfortable with. Especially 2 spaces are very little and becomes over the course of a work day quite eye straining (which btw is the reason why the Linux kernel defines 8 spaces..., tabs would still be better tho). This is quite frankly the type of rule where I would configure my setup to convert 2 spaces into a tab when opening the file and on save convert a tab into 2 spaces...
while i am not even close to a kernel dev, looking through the code, they seem to be using tabs, and the top-level .clang-format has the config "UseTab: Always" enabled
I'm advocate of using tabs over spaces too, due to the feature of being able to change the tab size in every editor (it visually replaces tabs with spaces, but the text data is just tabs). Not only it saves more memory, it makes it also more portable.
@@m4rch3n1ng Kernel style guide does say to use tabs, but also defines tabs as being 8 spaces. IIRC, there is also a column-width limit of 80 characters, which means the size of the tabs needs to be defined. Which kinda nullifies the point of tabs doesn't it, since someone that likes tabs as 4 spaces will potentially be formatting their line-wraps incorrectly lol
@@spfy oh that makes a lot of sense in that context then, i didn't even think about column-width - i just thought it was a visual thing (that you should be able to override in your editor)
It is true that in large projects using exceptions might be difficult to maintain, especially when there are many developers working on the same piece of code, however, they are good to have in situations where we receive completely unexpected data, corrupted data, or for validation reasons to bullet proof complex data pipelines.
Google doesnt allow exceptions because that is what they happened to pick years ago. They have debated enabling exceptions (they are generally more performant on the happy case for example), but mixing error returning code and exception code is a bad idea. They say that if they were to start from scratch today, they probably would use exceptions instead of error returns.
@@amrojjeh my first reply doesn't seem to have gone through since I put a link in it... Anyway, two sources: 1. It mentions in the style guide under the exception section > Things would probably be different if we had to do it all over again from scratch. 2. Reading an internal email chain about them.
@@brendanhansknecht4650 Thanks! That's quite interesting. I personally find exceptions to be really strange. I've found that code is much more readable whenever the error is embedded within the type itself. I suppose though that's not really an option in C++
@@amrojjeh I started out as a self taught C programmer designing and writing all the code, so I know you can write good code without exceptions. Everything you can do in C, you can do in C++. The only issue I ever had with exceptions in some languages is that some programmers use them to be lazy, instead of preventing possible exceptions from occurring in the first place. An exception should be an exceptional case (memory or similar issue), not a go to solution.
@@johnshaw6702 I personally still find it difficult to assess what should be a typical failure and what's an exception. Would you have any resources to recommend on that?
finally. a standard/convention you can point to. i will go through this guide when i have sometime. but the two spaces is pretty rough. you can barely tell if its two spaces or not when you are looking at it unless its super zoomed in. code just looks weirdly off and you can't tell if its because of the font or if its the editor.
People still complain at me a bit sometimes because I use 2 spaces as code indentation... although I know they'll complain no matter what I use, so I just try to get past it.
It may work for Google but some of this wouldn't work for me; and I've been a successful C++ programmer for 30 years now. Part of that is because Google has thousands of programmers, and to an extent the convoy has to travel at the speed of the slowest ship, but there are other foot-shooting rules like not using exceptions. If the overall project doesn't use exceptions, the way to add an exception-using module is for the module to expose an API that doesn't use exceptions, but to use them inside the module. Each API function can easily trap exceptions and convert them into error codes or whatever. I use this technique myself.
I don't agree with 100% of the guide (e.g. I can't have that 2-space indentation haha), but I loved the fact the video is about C++❤️ Please keep it up. Greetings from Germany.
People often role their eyes at style guides, or having their PRs blocked because it doesn't follow a certain style rule. They don't understand how easy it makes for third parties looking at your code.
In the Inheritance example, the problem with the Mother-Father-Child structure isn't inherently an issue of Inheritance, instead it is just really bad design. One shouldn't use composition just to avoid inheritance, but use it where it makes sense (like in the example).
Well that isnt the only issue present with Inheritance. Other nice situations are long Inheritance chains, especially if combined with overloads and stuff like specialization. Inheritance chains can already make it difficult to track down where a method is coming from, but with specialization of overloaded functions, or the overwrite of methods that get called by overloaded methods in ancestors, things can get super nasty, and quick at that. After experiencing the lack of inheritance in Rust I don't want it back.
inheritance doesn't work very well in the real world. obviously, as you stated, one shouldn't use composition *just* to avoid inheritance, but 1. in most cases it makes much more sense to use composition, and 2. it is generally better to avoid inheritance at all costs. now from what i see in the recent years, programmers gradually move away from OOP (and there are good reasons for that), and even hardcore OOP users avoid using some of its features. generally, i think it's a good thing, because we all know what overuse of OOP features of the 90s and early 00s resulted in. obviously, if you suck at code it doesn't matter what paradigm you use (and vice versa), but again, there are reasons to avoid OOP anyway.
One should always use composition. Inheritance brings ambiguity by definition and hides the implementation details from the person who's working inside the class code. You can still have dynamic dispatch and all benefits of polymorphism without classic inheritance, even in C++ though it's not enforced by the compiler. It is enforced in Rust.
About inheritance issue with diamond example I recently found great workaround which is class Bar : virtual public Foo {} which makes Foo class only being inherited once no matter how many classes its derived by. Its really awesome and powerful.
Tabs vs spaces is a non-fight. Use tabs with the correct indentation(read the project guidelines), let your IDE replace them with spaces. Do no check in tabs in your files and amend the commit if you did.
The fact code looks different on different editors with the tab character is the benefit of tabs in my opinion. It allows personal preference to apply to something universal. The individual programmer can choose if they prefer the tab to look like 2 or 4 spaces or whatever else. It's technically also one byte less than two space characters but that hardly matters today
I honestly think large part of this debate is really caused by Python and its inability to deal with mixed tabs and spaces. I also had issues with editing YAML files in the past for the same reason. I actually abandoned tabs for whitespaces because I was just sick of having random syntax errors showing up at runtime just because I used a \t in a sea of whitespaces in my editor.
Yeah I never understood why people are so adamant to make indentation look the same on both machines. If you need to align something visually, use spaces sure, but indentation is there to represent scopes, not for alignment. Removing tabs also hurts developers who use large or small tabs for accessibility or because it helps them be more productive.
I think the issue is that allowing tabs can result in the use of both tabs and spaces for vertical alignment. If the tab stop locations are changed, it gets messed up.
@@brandyballoon trust your programmers to use tabs for indentation and spaces for alignment? There's so many tools to detect tabs and spaces. Most editors let you visualise tabs and spaces.
I should probably read that style guide because a lot of these things I already do in my own code. Two spaces for each indentation level and I've set my tab key to insert four. Plus, since vim has dedicated keys for it I can increase or decrease indentation levels with ease. Need to push right 3 levels, 3> and done. Anyone that thinks tabs are superior should read that guide.
Very informative video. I wasn't sure what to expect, but I'm glad I clicked. The tab/space debate will rage on, but I like Google's take on it. That's not one I've heard before because, well, I've never been on a giant team like that where consistency is the key to not losing millions in a day. That's a fun example you chose for the classes (Mother, Father, child), but in my experience, it's best to avoid the noun/verb model and just do what works best. Trying to line up everything philosophically as classes just introduces logical issues like this. In that example, you'd probably be better off defining Person, Parent, Child, and Family classes. Since children in real life don't inherit everything evenly and directly from both parents, it doesn't make any sense to define their classes like that. Rather you should define a Person that Parent and Child will inherit from, and then you can define a Family which takes two parents and a list of children as arguments. If you really wanna get inclusive, just take in a list of parents and children lol. But your point is valid, inheritance can be non-intuitive and should be handled with caution.
Or, alternatively: all people are people. You don't need a 'mother' and 'father' class, or a 'child' class. This kind of metadata belongs to a family; a family is not a person, but a lot of people in a specific hierarchy of parent -> child. That sounds like a data structure to me.
I tend to use spaces out of habit, but tabs are better for accessibility (blind programmers often use braille displays, which only offer 40 characters per line), and with the exception of alignment, it doesn't really matter if the code looks identical. In the case of alignment, you just use spaces after the tabs. 2 spaces is probably better for alignment than 4 in the case of braille displays (though a tab is still better as it's one character vs two), but then people with poor vision due to age or the like may find that such narrow indentation is difficult to read by sight. In such a case, the fact that tabs are of inconsistent width is actually a positive.
6:40 --> An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier (= 0) in the declaration of a virtual member function in the class declaration.
2:29 If the type is not "Widget" then the function is wrong, not the convention. Also, just hover over the variable name to see the type in most editors. 3:52 If the class/function needs to *take over* the ownership then pass a smart pointer. Otherwise, just .get() a regular pointer from the smart pointer. Regular pointers are not evil, they are just not good at owing stuff. 4:56 That example only leaks memory because it's not using RAII, not due to exceptions. I'm sure that Google has good reasons to avoid exceptions, but this one ain't it. 6:17 Completely agree, avoid inheritance like the plague. As for interface inheritance, C++20 arguably has an even better option: concepts. Concepts can only restrict an interface and never the implementation, and unlike inheritance-based interfaces, concepts do not have a runtime impact. (The trade-off is that they do trap you in template-land).
can you also make a vid on AUTOSAR? i think it's a pretty interesting case study of a more modern approach on safe use of c++ in a critical infrastructure development
Autosar is trash. Same with Rational Rhapsody and all those similarly horrible tools the Germans like to torture themselves with. It’s a utopian approach that ends up giving you a bad product that took 2-5x as long.
1:20 That's actually the prime argument in favor of tabs. They use different tabs because they have different setups. I believe in Tabs for indentation, Spaces for alignment, i.e. anything after the initial tabs on a line should automatically expand into spaces. All editors should support this (but most don't)
The diamond problem in Inheritance, Can be solved in C++. Because there is the concept of virtual ness which deals with that problem and prevent the base class to inherit multiple times
If you can configure your editor to write 2 spaces when you press tab, surely you can also configure how wide actual HORIZONTAL TABULATION characters are.
The whole point of tabs is that you can configure how far the indentation is for yourself and that someone else DOES NOT get to dictate how it looks for you.
yeah, that's what people arguing for tabs say. I also prefer tabs. But you also gotta see the point of consistency that spaces have. If you're using tabs and have them configured to be as wide as 4 spaces e.g. you might add more of them to make the code look good on your end. But then someone else who has the width of tab (character) configured as 2 spaces has a completely different looking piece of code. For normal indentation that might be fine but if you have a long function signature e.g. that you wanna break down to multiple lines, you might wanna line it up with the opening parentheses and where those are differs depending on your tabs setting. say you have this function: int doSomeStuff(int (*callback)(int*, int*), int* a, int* b){ // do something... return callback(a, b); } might not be the best way to format your code but in that case the width of your tabs matters. With spaces the two lines of your function signature will always be lining up.
@@vaijns I won't do that tho. When I go a level deeper in indentation I push tab once and only once. The argument list already has its own brackets; It doesn't need to be aligned.
@@vaijns Honestly I don't think it matters. The issues of both can be solved by defining code formatting for the project. You just have to choose one and stick with it. For example for functions with a lot of parameters you define going down a line and tabbing once.
If I were writing this guide, I would say "use exceptions for all error conditions," "write exception safe code," "generally do not catch exceptions other than when you could conceivably recover," and "use RAII to avoid needing to catch exceptions." It's a shame IMHO that exceptions seem to be losing favor industry-wide, as they really _can_ make error handling easier and less error-prone. :sigh:
I found always one problem: How 'problematic' a problem must be to switch from status code, etc. to exceptions? For me, it was always unrecoverability. So while exceptions seems cool, there should be no more than 2-3 try-catches per entire humonguous project.
@@mastermati773 I agree that there should almost never be a try/catch. Basically, _main_ or _http/thread entrypoint_, only. I think it's not so much a matter of "switching from status code" to exceptions as deciding at the onset of a project that you're going to automate as much error handling as possible and use them from the start. If you're knee-deep in a project that uses error codes, switching to exceptions is probably not a great idea, and certainly a huge effort.
How to write future-proof C++ for Win32: compile with Digital Mars to support Windows 95-11, by the time x86 emulation becomes popular, users will be able to emulate Windows 95 or Windows NT 4.0 without taking excessive resources to emulate newer versions!
As others have already said, the "Mother-Father-Child" example is very misleading, and imo so is the "Car-Engine" one. A car is something that "has" an engine (association), not something that "is" an engine (inheritance). Thus nobody would have wanted to make Car a subclass of Engine to begin with. This is actually the same problem as the "Mother-Father-Child" example, it's just less noticeable cause the implementation we're shown is the correct one.
tabs vs spaces should focus on one thing, and one thing only: accessibilty. using spaces (especially small amounts of spaces like 2) over tabs forces people with vision impairment that need a larger tab-width to properly be able to code, to either reformat the entire code that they are working on (twice), not contribute to that project at all or just live with it and suffer, which i think is unacceptable.
@@heavymetalmixer91 yeah but what if someone needs to use 8 space width to properly code? or someone has a text size so large they have to use 2 spaces because otherwise the code won't fit in the width? if you use tabs and set your editor to display the tabs as 4 spaces, then these two can set their own editor to display 8 spaces or 2 spaces respectively, and all of you can code with your own preferences. it's like forcing someone to use a specific font: don't
@@m4rch3n1ng hit the tab to insert 4 spaces. That's what he said, as much as I understood. Tabs are not allowed in many places. A code formatter will solve the problem you mentioned. Tabs characters will be converted to spaces, anyways.
@@PinakiGupta82Appu yes but you should hit the tab key to insert a tab character, so other people can configure how code looks to them. i know about the convenience, but forcing someone else to change your formatter and reformat your code, or worse, manually format your code (as is the case in the majority of javascript repos) to be able to code for literally no benefit (other than the benefit of forcing your style preferences on someone else) is extremely unnecessary and inaccessible for people who need it edit for clarity: this is specifically about open source projects or other types of projects where multiple people work on the same code. i don't care what you do on your own disk, but you should at least think about other people when opening up your code for everyone else, especially if you are a company that tries to pride itself on "inclusivity"
@@m4rch3n1ng They will probably give you an Artistic Styler or a Clang-Format script. You'll have to run it to comply with the standard before committing the changes to git, even if the code looks bad according to someone else's preferences. Different people may have different preferences. It's not always possible to force them to accept what I want. Tabs are not allowed in many places, even if it solves the readability problem.
My opinions: Tabs vs spaces: Disagree, it is just as easy to configure tab size in your editor. (also I find code with only 2 spaces hard to read) Type deduction: Agree Ownership: Mostly agree, depends on the kind of project Exceptions: Somewhat disagree, exceptions are fine if they are documented and used only in exceptional cases Inheritance: Disagree, diamond problem is not a real problem since virtual inheritance exists
but why would you consider "it will look the same in different editors" to be a plus? Main reason for tabs is exactly that - it allows devs to view the indentation to way they prefer it. Someone likes small indentation, someone needs large one.
Ever initialized a large struct array with data of varrying sizes, and wanted it to look like a table of rows and columns? Your tabs may make it look nice on your screen, but for someone with a different tab size, it will look awful. With spaces it looks identical to each editor. That goes for any code that you wish to line up, such as when you have a function with many params that you wish to line up on a newline.
@@RigelOrionBeta well in these corner cases, nothing is stopping me from using spaces whenever "lining up" is my goal.. It's not argument for universal space usage for indentation.
At a large company where potentially a hundred people might look at the same code, it’s helpful to ensure they look at the EXACT same code. You’re right, it limits freedom and might make some developers slightly less happy, but it removes the possibility of bugs due to visual differences between developers.
@@tidepool5400 tabs are more accessible for people with vision problems. Great minds can be left out just because they were unfortunate to have really bad vision.
for inhiretance problem it called the daimond problem , and u can fix it easily by adding virtual key word , like ( class mother: virtual parent | class father: virtual parent )
Every course I've done uses the classic animals or shapes example to teach inheritance, but none of them demonstrated a real world use case for inheritance. So the result of that is that I understand the principle of inheritance, but I have no idea when it might be appropriate to actually use it.
i suggest you find a good read on OOP principles. I have one but it's in Korean and there is no English translation afaik. The book is '객체지향의 사실과 오해' (truth and misconception about oop) I'm reading it now so I can't summarize the key points for you either.
I think tabs are better than spaces due to one specific reason only: accessibility. People with problems with their vision usually have different ways to make code readable. Some people would blow up the font size and reduce tab width, some people would increase tab width instead. If spaces were used instead of tabs, those people would have to manually convert the spaces to tabs so they can customise the tab width, then change the tabs back to spaces afterwards.
I think it's getting better over time. Older generation is still using some weird *notepad like* IDEs because of habit. But in my circle young devs are working with more modern tools like VSC.
I'm not sure how you derived "avoid using OOP" from that video. Composition with objects and interface inheritance for different classes are OOP techniques.
The inheritance guide makes a lot of sense. I've seen crazy recursive or tangled object creation and method calls before, which is a pain to debug and extend further.
You can still write a spaghetti code by using composition. I've had to work with the other's code, where each next class contained one and only instance of a previous one as a private field, and not much beyond that.
@@bestnocture I'm afraid don't fully get the wording. Did I understand you correctly, that any good guideline can be abused - intentionally or not - in such a way that it's gonna lead to a spaghetti code?
I completely agree with Exceptions, they should only be used in extreme rare exceptions and never replace an error handling. When an exception gets through then you as a developer have made a very bad design.
Container.GetElementByID. What do you reasonably return when the container does not contain a matching element? Null -> null pointer access (exception). Default element - what should that even be? A tuple (success, element)? Callers will forget to evaluate success and element still needs to be a nullable pointer. Unions are the only thing that comes to mind. But then the interface of the method MUST list all possible result type and the error cases (which are an implementation detail) get exposed. This will hinder changing the internal implementation. Exception decouple the implementation details from the caller. A call must expect the unexpected. It get's even worth for Class.DoSomething(); A call expects something to be done But what to do when it simply can't be done? What if DoSomething() has to call other methods and those fail? Simply go back to learning exceptions...
Container.GetElementByID is a textbook example of when *not* to use exceptions. The function itself has no possible way of controlling what ID is passed into it. By definition, an element with an arbitrary ID not being found is not exceptional (you could argue that for the set of all possible IDs, only a tiny percentage are probably in the container). So yes, return some value (tuple, union, end()) for element not found and then slap your clients for not checking the return value. That said, imagine your container is somehow broken. Let’s say it wraps an array pointer or a linked list. If the internal state of the container is invalid, THAT is an exceptional circumstance.
I agree on all these things, inheritance thought I feel that it really depends on what your making. In a video game or a GUI framework there is a naturally occurring hierarchical relationship. So I believe in the "is a, has a, and uses a" rules. Also a huge fan of the Gof book. Great video! If you really want safe code, you need to use a FP language like F#.
Even in game development composition is better than inheritance. GUIs can also be done by composition. I follow the rule that if your class has more than 1 layer of inheritance, you are doing it wrong.
@@nankininkThat is a good rule to follow as guideline. The benefit and danger of inheritance is that you can modify millions of classes by just modifying the parent class. So for instance if you want to change the default speed for enemies or default size for a window you can do that in just one place. Also imagine having a biology simulator and this program having perhaps over 10,000 different species or more then you can save an enormous amount of code by using inheritance, if you have many types that differs slightly from each other. I don't use inheritance much myself but it certainly has it's niche use cases.
I would generally prefer composition in the case of a game or a GUI whenever possible. Create "foundational" classes that compose the entire structure. Keep inheritance as shallow as possible and prefer abstract classes.
I think that if you don't use RAII and exceptions, you shouldn't bother with C++ at all. Just use modern C. Yes, that requires writing wrapper code for all incorrectly (that is, without RAII and exceptions) written C++ code.
Each environment has its requirements, and with that, opinions on how to write code are different as well. I think it's a good idea not to get wrapped up too much into any one of them, lest one becomes prone to shoehorning paradigms into environments where they're not a good fit.
Many thanks for the video. I was educated in the 1980’s in Taiwan with Pascal and 1990’s in the US. As an engineering manager for most of my career, I’ve navigated through the minefields with engineers on (2) spaces vs tab and much more on exception. Can you make this a series?
Why is it considered good when the indention is using spaces to force the same width on every developers editor? The important thing about indention is the *level* of it to convey the depth of a line in a code strcuture. A tab perfectly matches that. One tab = one level. And the width of the code is configurable to individual preferences without interfering with other developers. Depending on the monitor a dev uses (or when having a visual impairment) you might want to have a visually easier to distinct indention (like on a high resolution / high dpi one) to see the levels better. Or you want to utilize it to force yourself to write better code by making it painful to deeply nest. I absolutely don't see why on earth using spaces - especially just 2 per level - is a good idea... If you disagree, feel free to throw convincing arguments at me
Consider a function that has a lot of params. What do you do? You put them on the next line. But what if you want to line them up with the previous params? You cant do that with tabs, because tabs are differing in size. Your lined up params may look nice on your screen, but not someone else's who has configured tabs to be different. There are numerous other examples of why tabs are worse than spaces. I used to be a fan of tabs, but once I started working with other developers on large projects, I realized tabs are not a good idea. There are too many formatting problems with them. Instead, your project should agree on an indentation size of spaces, say 2 or 4. Then configure your editor so that hitting the tab key adds 4 spaces instead of a tab. The key thing here is you can get all the functionality of the tab key, without all of the visualization differences that the tab character will create.
@@RigelOrionBeta "But what if you want to line them up with the previous params? You cant do that with tabs" You can use tabs to get to the right indentation level, then line up with spaces.
@@pauldegroot1959 That's pretty error prone. How can you easily tell what white space is a tab or a space? At that point, you're mostly just using spaces anyway for alignment. In fact, if you just configured your tab to put spaces instead, you'd save time tabbing to the alignment point, since it inserts multiple spaces, instead of using spaces. You'd get there 2-4 times faster than if you used spaces. There is really no point. I used to do exactly what you are describing, but you can never be immediately sure that you have tabs and not spaces. Why bother?
@@RigelOrionBeta 1. You can make whitespace visible. 2. Tabs are for indention, spaces are for alignment. 3. You can align like the following: int long_function_name( TypeFoo param1, TypeBar param2, Data ¶m3 ) { .... }
@@anon1963 I don't think that's what the point of the original comment was. I think he was saying that writing code for whatever particular application is designed to be future proof, to last a *long time even into the future*. However, if the project is discontinued, like the original comment said, then it can be said that the code was not future proof since it was cut short by the overall project's discontinuation.
@@Syndiate__ future proofing code = making it fairly easy to make changes and expand on it, cutting projects has NOTHING to do with future proof code. hence my comment
C++20 or C++23 has this new feature called concepts which are essentially better versions of interfaces, especially when traditional c++ interfaces are merely classes with only pure virtual functions.
I would argue they are very different ideas. Concepts are a about controlling the data that goes in and out of objects and functions, and is related to the idea of constraints. Interfaces on the other hand are SUPPOSED to be just abstract clases with pure virtual functions. They are a way to structure the SHAPE of your data so that it can be composed though HAS and IS relationships (The core of OOP) through Interface Inheritance and composition. I don't see concepts as a replacement for interfaces in the OOP sense. But I do like them a lot! And for small snippets of code they might entirely remove the need for OOP in the first place. Which would increase code readability and usability
@@sebastiangudino9377 you are correct, but I see interfaces as being at least somewhat related to having constraints on functions. C++ is very oop, but if we think of the idea of an interface as (a worse version of) typeclasses in haskell or traits in Rust, then the "application" of an interface in a function signature essentially becomes a constraint on the types of such parameters that have that interface. However, I've only superficially looked at concepts in c++ as it's not a language I use much, but that was the impressions that I managed to understand from this new feature.
@@Tomyb15 I see. I think that's a valid way to think about them! But I still think C++ lands itself better to the classical "Control shape of data" rather than the "Control usage of data" that languages like Haskell have. This is specially important for optimization purposes. This is the reason why things like move semantics are something to keep in mind in C++. But that said, rust has showed us how both paradigms can coexist in a pretty elegant way. So I am very open to new ideas in Moden C++
1:26 the difference in tab length is noted as a benefit by tab fans. People have different preferences for indentiation and tabs allow them to use it freely. If tabs are used for indent and spaces for alignment code which should line up does line up. 2:24 a) to be precise, it's a function template, not a function b) it doesn't return Foo but std::unique_ptr 2:50 the auto issue is controversial - a lof of editors will support rich code information and display what auto deduces too. Looking at the committee, opinions differ widely. IMO worth to mention. 4:00 I know it's an artificial example but in an education video you should do some effort and write a standard exception class caught by const reference. 5:00 a) missing semicolon at the end of class definition b) mixed namespace use: std::string but not std::uint32_t Also please note that Google's Style guide has been criticized by C++ creators. A lot of C++ Core Guidelines conflict with Google's guide. Google's guide is aimed mainly at Google's legacy code. Core Guidelines recomment NOT TO use it.
" If tabs are used for indent and spaces for alignment code which should line up does line up." Or, you can just use the one character that will always work and always be correct. I have never seen tabbed code that wasn't messed up. Not once. It's impossible to maintain invisible characters.
so that last part is to follow SOLID design. Each class holds unique concerns, and use composition over inheritance, so that functions and responsibilities stay separated. Inheritance has its place, but is not engineered correctly. With classes that mainly hold data and handle some transformations inheritance is not well suited. For objects that build upon each other like window systems, then behavioral design there says that inheritance is good. With all of this said it is impossible to write debt free code. We are developers. The use of tabs should be encouraged. Set your editors as a preference. We engineer differently and have unique styles. Some solutions are only found when people can be themselves. All of this will lead to debt though in the sees of style. The issue here of debt free code is not the style of coding that one uses. The issue is how to engineer properly. This video touched on using interfaces. Interfaces are really important and needed in all projects. We should be designing for interfaces as that allows for modularity. Need a new way to access data? Not an issue as along as the data access returns all of the correct data sets. Which data sets are there well that is where an interface comes in, as the functions should be set based on the business logic necessary to run the front end. In this way we can reduce debt as we are only changing one concern at a time. Debt is not style, but failings in logic. I also disagree with the non-use of exceptions. Exceptions are not just program breaks, but are failures in design, and should be looked into. Without the exception we have no idea why the program just crashed. What is needed is a better way to handle logging. They will need a standard library for logging exceptions. It is now each concerns responsibility to report the error to the logging and then handle the exception per the concern. In the example in the video the function g handles no exceptions from H or more likely handles errors in H by raising the exception again, which passes it up to F. This is an example of poor design. where is the separation of concern? if function F is the concern and functions G and H only perform data manipulation, then the responsibility for error is at function F. if each function is its own concern, then we need a way to decouple these nested calls.
4:54 The rule I have on Exceptions is. Don't. ever. use. them. -Validate your data, provide return codes accordingly, check return codes from functions you use. Wow, now you don't have to worry about exceptions jumping over your head. Not to mention throwing an exception take the program's execution pointer away from the problem. -Why would you want to do that in the first place.
So you want to pre-allocate a huge gob of memory that might exceed physical AND swap memory combined and kills the program? Well I’m not gonna hire YOU then, am I.
@@smallbluemachine You don't have to allocate huge amounts of memory to run out, do you? Also that was an example. The constructor should always create a valid object. That might fail for lots of reasons: File handle can't be opened, connection times out, etc. The alternative to exceptions is a .valid() method which is very bad style
Really curious to see if Carbon will be designed with a bias towards Google's style guide. Are there C++ features for which they won't build compatible functionality in Carbon, or will they aim to be 100% compatible with the entire C++ language?
It's funny how half of the things are just "do it like in rust" lol (e.g. having only one level of inheritance and only with abstract classes as parents is basically rust traits)
Rust is made with a 40 years of history of writing terrible code in C++. Makes sense they dropped some concepts that have been proven to be extremely bad. You could see the same in earlier languages, for example, C# and Java removed the multiple inheritance and encouraged the use of interfaces. All mainstream languages (incl. C++) play with the functional programming. The most modern languages (Go, Rust, Zig) drop the exceptions in favor of C-style error handling with syntactic sugar. This is basically a trial-and-error on the scale of generations of programmers, and while it's painfully slow, it's a steady progress towards the perfect programming language in which it's harder to write bad code. Because if it's possible to write shit, it will be done, and very fast. Javascript programmers cried in tears with jQuery until came the frameworks that enforce their architecture on you (React, Vue, Express, Nest, etc.)
the spaces over tabs is a serious accessibility issue. Programmers with visual impairment need the ability to customize their tab width. Spaces make that nearly impossible. If you have a codebase in large company and you switch from tabs to spaces, expect 2 phone calls: 1. from the legally blind person who just lost their ability to set tab-width to 1 in his font-size 70 editor. 2. from the dislexic person, who lost the ability to set the tab-width to 8 to make the indentation readable to them. Good luck undressing those 2 problems simultaneously within space-only policy.
"the spaces over tabs is a serious accessibility issue. Programmers with visual impairment need the ability to customize their tab width. Spaces make that nearly impossible." So your solution to the code looking bad for some people is to make it look bad for everyone? Doesn't seem like much of a solution. Just, like, increase the font size. Buy a bigger screen. Using proper code typography is not an accessibility issue at all, let alone a serious one.
1:20 That's the whole point of the TAB character - it lets you adjust the visual amount of indentation to your liking without modifying the code. The fact that the code can look differently when viewed in editors with different configurations is not an issue but a feature. The rest of the rules are perfectly reasonable.
Yeah but that's exactly why the TAB or \t special character is so bad in text editors - it's not monospace. It takes up some unknown integer amount of monospace blocks. The same way you don't want to write code with crazy Unicode characters in naming conventions (and that's if the language even allows them), you don't want TABs themselves. You just want the utility TABs provide, hence the spaces.
@@afelias As you said, tabs take an integer number of monospace positions. Therefore they don't mess up monospace fonts - characters typed after tabs are still aligned to the monospaced grid. I absolutely do want tabs themselfs because they provide better utility than spaces.
Vindication, mine at last. No tabs ever, and two space indent is all you need in life. Lines wrapping unnecessaily due to large indents may be the bane of my existence. Also, begin/end braces should align in the same column 😄 🤜Fight me 🤛
Good old spaces vs tabs. The only situation I dont like spaces is when one arrow key press doesnt move one full indentation or backspace doesnt remove full indentation.
@@nilau8463 that's what I tell everyone who say spaces are annoying... How does that change anything for you when using full word directional arrows movements?
The composition vs inheritance debate was always obvious to me. Inheritance means something "is" that class with extra stuff, composition means a class "has" another class. A car isn't an engine with extra stuff, a car has an engine. A child isn't their mom and dad, a child has mom and dad.
I started my low level journey with Rust, but over the years I’ve found myself favoring C++ more. The flexibility, customizability, and power are intoxicating. I’m glad you’re clarifying Google’s guide to make the language more productive for all. Also, you can see a lot of these design choices actually implemented in Go’s language design.
“Tab width might be different from one editor to another” that’s the point of them!!!! 😭 I hate it when other engineer’s tell me what my indent should be, write better code that doesn’t rely on horizontal alignment to actually read it. Maybe someday source code will just be ASTs and I’ll be able to have the style I actually want.
A good way to make code readable is to line up opening and closing braces. Microsoft does that, but most other companies don't, for reasons of fashion rather than logic. Even better, use Whitesmiths style; but Microsoft style (braces line up and statements are indented relative to them) is okay.
That no exceptions rule sounds strange. I wrote a dice rolling program that takes a RPG-formatted (e.g. d20, 3d8, 2d6+1) string and parses out the number of dice, faces of dice, and modifier. It was much faster to just write "try{std::stoi(s);}catch(...){}" then to for-loop through each string and do an isdigit() check against it, with the added benefit that if the user puts in a number > INT_MAX, it will still handle the exception by printing an error message end exiting with a failure. Trying to do pure input validation seems like it would make for less elegant code for the most part.
Why is there an argument about tabs vs spaces? A tab can be converted to spaces, and it is a single key press. It can be converted in your editor to match any number of spaces. On the other hand, manually pressing the space bar for 2 or 4 spaces has issues if you don't tap the right number of times, it is harder to do and more error prone. And if somebody else sees the code in their editor, they might not be able to change the spacing to match their preferences. I can't believe this argument is still happening. Tabs should win outright with no competition. Oh and also tabs are smaller in file size. Need more persuading?
tabs vs spaces is not about pressing the tab key on your keyboard or the space key (it's always pressing tab). It's just about what is inserted when pressing tab. (mostly) all editors give you an option to define how many spaces should be inserted by the press of tab (or no spaces but stick with tabs). While tabs allow every user to define the width of their indentation themselves, spaces force the width which helps with consistency (depending on how wide your tabs are you might add more or less of them in your code, which could look weird on someone elses device).
Absolute horseshit. No one who uses spaces ever presses the space bar to insert their spaces. They let their editor insert 2-4 spaces when they do their "single key press" of the tab key. You don't have to press it the right number of times. The workflow is exactly the same. The problem is when tab people try to use their damn tab characters in other places than the beginning of the line, they fuck up everyone else's code alignment if the settings are not exactly the same between editors. Tab people end up with alignments like: const int short\t\t\t= 1; const int longvariablename\t= 2; And it aligns perfectly on their tabwidth, so they didn't think that it wouldn't work on anyone else's. If the advantage is that everyone can set their own tabwidth, why do they introduce code that misaligns with different tabwidths? Another example is for function signatures where the parameters are on different lines. Spaces is the only way to align them with the start of the first param. If tab people used editors that could put tabs at the beginning of a line and spaces in the middle, that might be okay, but they never do. They litter the code base with awful tabs in the middle of lines. I can't believe this argument is still happening. Need more persuading?
@@BlueEyedSexyPants I think as long as you're consistent within a codebase both are fine. I for example prefer tabs to have my indentation just the width I want. And I don't use any tabs for aligning assignments and for function signatures I just add one tab to the horizontal position where the signature started (usually the return type). I agree that lining up with tabs doesn't make sense. But it comes down to how you format your code if it is a problem or not. As I said, just keep it consistent within the codebase. If I'm working on someone elses codebase, surely I don't force my tabs but I also try to format my code based on what's already there (like, are function signatures aligned at the same horizontal position or not, ...). A lot of code I'm working with uses 4 spaces and I'm not a huge fan of it as I think that's too wide. But that's not my choice to make if it's not my codebase.
@@vaijns Yeah, if everyone in a codebase is perfectly consistent, that's fine. So if the codebase wants you to set your tabwidth to 8 but you prefer 2, you either need to set it something you don't enjoy, losing the supposed advantage of tabs completely, or you need remember every time you insert your 2-space tab that everyone else will see it 4 times larger. (8 is insane, of course, but just for the purposes of illustration.)
@@BlueEyedSexyPants that is a good argument with mixed usage in situations other than code indenting. Ultimately I've just accepted the situation as is. However sometimes it's very much annoying, eg. when I write documentation with TeX and similar. You can include code directly from the source file, which is my preferred way as it avoids me forgetting to update code after changes. But if you used 4 space indenting (as is the default in most Code bases and also most formatters), this makes most code hard to include, as that quickly gets too long with little indentation. Similar thing when I open some code in a small window /on a small screen.
Google's policy on the use of spaces has been my policy in every language I've coded in since 1976, except for assembler, G-code, and antiquated versions of BASIC.
My code is in no way future-proof, it is overly compact and simultaneously not, it is the embodiment of spaghetti code and I myself have a hard time reading it at times. This is a mistake. Glad Google isn't making it. Edit: dang didn't expect the replies to be an argument on the readability of code relating to how easy or hard the code was to write lmao
@@pierelenigus8598 it should not if it's a finished work. After you wrote a working implementation it is messy indeed, but then you usually can optimize readability by a lot without chaning the logic. The code is finished not when there is nothing to add but when there is nothing to remove.
@@DajesOfficial Well if you're not busy and in demand problem solving solution provider I reckon one would have time for all that. As far as I know the real world a working solution is a completed solution.
I find the rule about auto particularly funny. It completely contradicts python enthusiasts who say that python is easier because you dont have to write types. I completely agree with google here. Types help read the code, it is not a good thing not to have them.
Explicit typing everywhere makes refactoring much harder. In many many cases they're an implementation detail; it's important that they match and I'm grateful that the compiler checks that they match, but what I need to know is the interface being used and behaviors relied on in their current context, not whatever name was given to them elsewhere in the code base.
@@isodoublet i am actually not that familiar with c++, more with java. There it is common to use only interface types where possible. Is that not a thing in C++?
The point of tabs is to look different based each engineer's config. Some people may like 4 spaces, others 8, some 2. You can't have that customization with spaces.
Just a small nit, but in modern C++ there is NEVER a reason to deal in naked malloc s or new s. Just use smart pointers anywhere you might need to malloc or new and you never have to worry about use-after-free or ambiguous ownership. If you need to more directly control memory lifespans, use custom allocators instead. Although I agree with Googles no-exception style requirement, using smart pointers also ducks many of the early-return problems making exceptions somewhat less troublesome for legacy projects.
A fun thing, this is how google does INTERNAL things. Here they care about developers. They FORCE you to break a lot of these if you use their IDE's. Because Google does not care about developers that are not working for them.
spaces are inaccessible. some people's eyes or visual cortex just doesn't read the code easily unless they can set their indentation to something crazy. with tabs, that's trivial, and editor-specific; it doesn't bother other people if my IDE shows indentations at 8 characters. with spaces, google is forcing everyone to have the same experience, whether it accommodates their visual processing abilities or not. not to mention that they mandate TWO spaces, which is bad because it inherently encourages deep nesting.
Yes! "It looks different for different people/editors" THAT'S. THE. FUCKING. POINT. If I want my tabs to be 3.141592653589 spaces wide because [reasons] that's none of your business. What's next? Storing code as PDFs to preserve the company approved font, size and color? I would even say this is straight discrimination of visually impaired people and it's disgusting.
I've worked at companies that used tabs and companies that used spaces. The companies that used tabs gave me a much harder time reading code because I would often have to manually change my tab width to match whatever the original author used. Which is a problem in a file touched by a lot of devs. This is a largely a problem with people not understanding the difference between indentation and alignment.
"some people's eyes or visual cortex just doesn't read the code easily unless they can set their indentation to something crazy." Such strawmen can pick a different career. It doesn't justify having the code formatting suck for everyone, sorry.
All of those seem great ideas - except perhaps about the strict use of auto. Many modern editors can automatically display the type of an auto-variable, so there is no loss of understanding really.
I actually think Google just manually enforcing what the rust compiler is enforcing, but in C++. The model of ownership, standardized linting, error handling, etc
It is true that, at least for the near future, relying on this automatic type information, would lead to some restrictions in which tools people could use when they want to read a lot of code they are not familiar with. But, using 'auto' can also slightly increase the readability of relatively well-known code, because generally the variable name should carry the relevant information, and whether 'nItems' is an int, uint64, or even some custom counting-class with its own ++ operators, is really more of a detail. So, I am not sure, I don't think Googles choice is bad, but there is a tradeoff, and the availability of better tools shifts this tradeoff somewhat.
I work at Google. This video barely scratches the surface of Google's C++ style guide. IMHO, the style guide is a wonderful thing, and makes C++ a pleasure to work with at Google.
Although your preferences may not agree with every little detail, the consistent application of the style guide across a massive codebase is highly valuable to everyone that will ever lay eyes on your code. There could easily be hundreds or thousands of engineers that interact with your code - interfacing with its API, extending it's functionality, debugging it, improving it's performance, etc. Every decision made by the style guide is one less thing all those engineers have to consider.
Wow that’s awesome! Thanks for watching. Yeah there were tons of interesting bits I wanted to go into but wouldn’t make a good video.
Agreed, google C++ is the really nice to work with. I also really love the absl and base libraries. I was intimidated at first by how large the codebase was but the consistency and cleanliness of the code helped a lot
just the no exception rule is so nice. I hate exceptions in C++. It's not like in Java where you can declare "throws". You have to understand all the callers. And you have to trust that someone doesn't add an exception in the future and breaks your code.
Does Google have a linter that can hint to the programmer that they are possibly violating the style guide?
@mipmipmipmipmip Google engineering seems pretty damn good. Their product side seems lacking.
I like reading 90s C++ projects, they released the source code for 3D Movie Maker recently and been reading through that. It delves you into another time, a 'simpler' time.
can i ask you where you can find the 90s C++ projects ? is there a book or website i can read on it ?
One of my favorite videos on UA-cam, I never even thought of looking at style guides. With a good amount of C++ under my belt I can totally see these guides being useful
Glad you enjoyed it!
Composition over inheritance and RAII (smart pointers) are the biggest lessons here. They drastically de-shittify your code.
You would figure everyone would know by now that most inheritance is shit but I guess there's still people out there crafting the most illegible polymorphisms possible.
@@hyde4004 I haven't figured out. Guide me
@@hyde4004does inheritance still have good use cases?
Genuinely asking as a learner
"OOP vs _" is a dumb conversation most of the time, just use the best tool for the work, while taking into account the conditions and project you currently are in.
@@prumchhangsreng979 Inheritance is useful for interfaces. A Base class defines the interface, and then Derived1 provides the implementation. You can create Derived2 and Derived3 with different implementations of the same interface. It's very useful.
People get stuck by putting implementation details in the base class and then trying to change or get around it in the derived classes. Wrong. Factor it out and include it as necessary in derived classes. The classic example is vector. Nobody extends from vector, they include it as needed.
My absolute favourite is working on a code base where a class inherits class templates that inherit other templates that inherit an interface. That's the ultimate in "FU figure this out" coding..
I never write any comments on YT but I really feel like doing it this time. I'm a C++ developer and it's my first job ever (same thing for my teammates), so we struggle with many of these details every day because I think it's quite hard to decide on your own which is the best practice. It's nice to know it's not only me and that it's a real deal out there to write good code in C++ (I also thought those many details of the language make it very powerful but difficult to manage correctly, but I thought it was just me being an inexperienced engineer). I really enjoyed this video, I would also like to see more C++ guidelines and stuff (obviously). Keep up the good work!
In C++, having an explicit style-guide that is enforced in code-reviews (and preferably by some automatic linters too) is absolutely essential. C++ is just too bloated with 40 years worth of legacy features that often interact with each other in weird ways. You have to pick some subset of C++ that all of you understand and use only that subset.
Many such style guides are publicly available. You can copy them or take inspiration and make your own.
@@KohuGaly Thank you! We try to use C++ 11, which we found quite readable, but tbh we don't strictly follow any standard. Most of the code that we inherited was programmed in a C style (but with classes) instead of C++ with a standard, so that poses a problem.
@@ToCarlosHuevos I know exactly what you mean :-D I recently got a job as a embedded automotive C/C++ developer.
The standard used there is MISRA C++. The oldest parts of the code base pre-date the standard and are literally written in C.
"Fun" fact: MISRA C++ forbids all forms of pointer arithmetic except indexing into fixed-sized arrays.
If you read the last two sentences and have basic experience in C and C++, you know exactly why "Fun" is in quotes. 😀
@@KohuGaly Hi, I'm sharan. I'm working in a startup called Yali Mobility. We are making electric three wheeler for wheelchair users. I'm just a year old experienced programmer. Currently I'm the only person who programs the vehicle. So I'm struggling alot, kindly help me in some way like standardization of the code etc. This may help us to make the work flow and performance of the code much better. Thank you
@@sharana.p5921 Hi Sharan. Unfortunately, you are probably more skilled in C++ than I am. I was just lucky to land a job in a large corporate, with a lot of pre-existing expertise and know-how to learn from.
Not gonna lie, writing software for a road vehicle, as a 1-year-of-experience solo developer... that sounds like a pretty reliable way to kill someone by software bug.
Great video!
A few things, from a Google engineer (not speaking for the whole company, of course).
1. We absolutely have tech debt. These things help reduce certain kinds of tech debt, but it still exists all over the place. We're not magical; we make bad choices which we're then stuck with.
2. The lexical code style goes beyond just tabs vs spaces. Our code review system will yell at you if the code isn't formatted according to whatever clang-format would produce. Our style guide for indentation, line breaks, etc, is just "run clang-format and use that". I don't always like the choices which clang-format makes, but it's infinitely better for everyone to use the same standard than for me to use a standard I like more, but for diffs to be larger due to whitespace changes.
3. An important part of the style guide boils down to "don't get clever with template metaprogramming." I've been writing C++ for about 3 years now, and as soon as things get beyond the most basic template usage, I'm lost. If you're relying on SFINAE, you should probably reach for a different solution. Same thing once you start dealing with rvalues and lvalues. There are some places where those features really do make sense, but for things like "call this service. If foo is greater than 25, set bar to true", you probably don't need that stuff.
I appreciate the insight!
Item 3 is a typical complaint of someone who learned 30% of the language but still decided to put it on his resume.
@@TheOnlyAndreySotnikov Dude, do you work with someone else code beyond your own? Templates can get really confusing. It's all abstraction so there is certain difficulty to comprehend someone else idea in form of code, specially if it doesn't read well. I spent many hours trying to decipher what author had in mind while creating his solution to problem so speaking from experience (just lately I had to decouple 3000 lines long class implementation written and edited by different people). It included weird lambda expressions and templates.
@@anonimowelwiatko9811 Dude yourself. The most frequent source of complaints about templates is a lack of education. Software engineering is a unique field. In any other area, you can't say: "or, integrals is a too complicated abstraction for me," and claim you know calculus. Not only that but in software engineering, you can also force all your colleagues to dumb down to your level and never use integrals in 𝘵𝘩𝘦𝘪𝘳 work. In any other profession, you just shut up and learn. In software engineering, you complain. Meanwhile, not "professional" programmers successfully learn, write, and maintain huge packages written in TeX, which is way more complicated to comprehend than C++ templates. So, 𝘥𝘶𝘥𝘦, learn and practice.
instead of SFINAE you should use more modern features like concepts and if constexpr from c++17 many things that are written in older versions of c++ can be written more clearly and using less "magic syntax" in the latest versions of the language (c++20/23)
The multiple inheritance example is bad imo, because in that case you should actually let "Child" inherit from "Person", and not "Mother" and "Father". Inheritance is usually used to generalize something and abstract it away, like a "Table" is a type of "Furniture", but not a child is a mother and a father.
Definitely agree, he could have used a better example there. To expand on your furniture idea, you could have something like a "convertible sofa" that inherits both from "bed" and "couch," which are themselves inheriting from "furniture."
Mother and Father are Persons after all, so I see no issue here. Child referes to them being child classes, but that doesn't mean the example is incorrect. As you said, inheritance is there to generalize something and Person is more general then Mother and Father, they are something more specific.
@@2JulioHD I think @ruarq1510's broader point here is that the Child/Mother/Father example is confusing because it conflates biological "inheritance" between children and their parents with class "inheritance" between a subclass and its base class. It reinforces a metaphor that is not particularly good to begin with.
@@2JulioHD Yeah, but you usually say „a mother is a type of Person“ or „a father is a type of person“, that’s how inheritance works. In the example it doesn’t make sense to let „Child“ in inherit from „Mother“ and „Father“, since a child is a person and not a mother or a father. Instead, the Child class should have the mother and father class as an attribute. In the real world, yes, a child inherits the genes from their parents, but genetic inheritance is not the same as inheritance in programming, it’s a completely different thing. You also can’t generalize a child to be a mother or a father, but that’s what polymorphism does.
@@2JulioHD Inheritance should be logical. Is a ?
And this should follow through the inheritance structure.
In this case, mother and father are both people.
Child is a person.
But child is not a mother nor a father, and especially can't be both at the same time.
Aw man, two spaces??? I’m yet to try looking at code like that, but four has always looked better
4 spaces has always been the standard for tabs. see ansi for the real world proper use of tabs. google has retards running the show and the two tab mandate has already hurt their developers immensely. but they would never tell the truth.
I like two personally, but professionally 4 with a reasonable column limit is better as it dissuades excessive nesting
Two spaces are very hard to see.
IT'S a C++ CODE, NOT HTML!
I'm sure theres a quick way to replace whatever tabs you prefer with two spaces before commiting the code
this quibble is by far the least important thing about writing c++
The worst Java code I've ever seen was part of (Googles) easier mediapipe API.
They had DEEP Inheritance, manually written getters and setters which contained a few surprises (like giving back properties that already had their own getters), made intensive use of method overloading and inherited methods including methods, and these methods often took parameters that were named in a way to imply they had a certain function, only to be thrown away/used in a different way, or they were actually set, but that didn't matter as at a later point in the lifecycle these values would be overwritten before doing anything.
Combine that with the need to also use the not easy and not well documented camera2 API (which they combined with some parts of CameraX) and that under all that Spagetti mess they used JNI to call C++ code that also wasn't particularly well documented, and I got nowhere but sure wasted a lot of time thinking I finally got to the target.
Honestly, while we're at this, LARGE swaths of the Android API require you to use implementation Inheritance, so thanks for forcing me to do the things you forbid your engineers to do Google.
Sorry for the rant, I'm still super salty from that experience. What they archived with mediapipe is remarkable, and it's nice they made it open source. But mediapipe did not keep it's promises (real time body tracking on IOT, pretty much every mobile - top models released after mediapipe - we tried didn't get over sustained 10 FPS, while being at best at a mean of 18 FPS), and the API was a nightmare and not at all flexible enough for our needs.
These are general guidelines. Not all engineers/teams follow them.
@@jordixboy also for c++ lol, not java
Android is a bit separated at Google
Google has tens of thousands of engineers working across hundreds of projects. Whoever developed this style guide probably doesn’t even touch Java code in his day-to-day.
Android was a purchase for Google, had nothing to do with it in the core. So no wonder its code does not follow Google’s guidelines. Besides, those guidelines changed a lot from the 1990s to 2000s, then to the 2010s, and then to the 2020s, so Google’s catalogue of code is a huge nasty mess. Probably only MS is worse than Google.
Great video and all...
just please don't build an inheritance relationship Child -> Mother, Father -> Person. Even with inheritance as a concept, that does not make sense. But especially in C++, inheritance means "is-a" and a Child is not always a Mother. Everything that would apply to Mother, would also be applicable to Child under C++.
1:26 Yeah, that's the point of tab. That everyone who reads the code can configure it the way they want to be.
That way no matter who looks at the code, it will always be with the indentation the person feels comfortable with.
Especially 2 spaces are very little and becomes over the course of a work day quite eye straining (which btw is the reason why the Linux kernel defines 8 spaces..., tabs would still be better tho).
This is quite frankly the type of rule where I would configure my setup to convert 2 spaces into a tab when opening the file and on save convert a tab into 2 spaces...
while i am not even close to a kernel dev, looking through the code, they seem to be using tabs, and the top-level .clang-format has the config "UseTab: Always" enabled
I'm advocate of using tabs over spaces too, due to the feature of being able to change the tab size in every editor (it visually replaces tabs with spaces, but the text data is just tabs). Not only it saves more memory, it makes it also more portable.
@@m4rch3n1ng Kernel style guide does say to use tabs, but also defines tabs as being 8 spaces. IIRC, there is also a column-width limit of 80 characters, which means the size of the tabs needs to be defined. Which kinda nullifies the point of tabs doesn't it, since someone that likes tabs as 4 spaces will potentially be formatting their line-wraps incorrectly lol
Tabs set to 4 ftw and half spaced returns
switch(smt) {
case 0:
do_smth();
break;
case 1:
for (i=0;i
@@spfy oh that makes a lot of sense in that context then, i didn't even think about column-width - i just thought it was a visual thing (that you should be able to override in your editor)
It is true that in large projects using exceptions might be difficult to maintain, especially when there are many developers working on the same piece of code, however, they are good to have in situations where we receive completely unexpected data, corrupted data, or for validation reasons to bullet proof complex data pipelines.
Google doesnt allow exceptions because that is what they happened to pick years ago. They have debated enabling exceptions (they are generally more performant on the happy case for example), but mixing error returning code and exception code is a bad idea.
They say that if they were to start from scratch today, they probably would use exceptions instead of error returns.
Do you have a source?
@@amrojjeh my first reply doesn't seem to have gone through since I put a link in it...
Anyway, two sources:
1. It mentions in the style guide under the exception section
> Things would probably be different if we had to do it all over again from scratch.
2. Reading an internal email chain about them.
@@brendanhansknecht4650 Thanks! That's quite interesting. I personally find exceptions to be really strange. I've found that code is much more readable whenever the error is embedded within the type itself. I suppose though that's not really an option in C++
@@amrojjeh I started out as a self taught C programmer designing and writing all the code, so I know you can write good code without exceptions. Everything you can do in C, you can do in C++. The only issue I ever had with exceptions in some languages is that some programmers use them to be lazy, instead of preventing possible exceptions from occurring in the first place. An exception should be an exceptional case (memory or similar issue), not a go to solution.
@@johnshaw6702 I personally still find it difficult to assess what should be a typical failure and what's an exception. Would you have any resources to recommend on that?
If Google doesn't like using exceptions cause of flow control stuff what do they prefer to use instead
Return values
Yeah, this was just glossed over as if its some minor thing. How do they handle their exceptions and, more importantly, errors then?
probably simple optional or rust like solution `Result`
@@jmickeyd53 Thanks for the info. Makes sense
@@Nape420 They probably collect requirements and validate their input.
finally. a standard/convention you can point to. i will go through this guide when i have sometime.
but the two spaces is pretty rough. you can barely tell if its two spaces or not when you are looking at it unless its super zoomed in. code just looks weirdly off and you can't tell if its because of the font or if its the editor.
The Google C++ style guide was my bible for a long time. It's incredible and makes C++ truly beautiful and easy. I miss my C++ days :)
People still complain at me a bit sometimes because I use 2 spaces as code indentation... although I know they'll complain no matter what I use, so I just try to get past it.
What do you code in now? I’m mostly curious because I started off with Python 2 years ago, and I’m only now getting into C++.
@@mojoloop Haha I fell to the dark side, I do JS/TS for web dev now
@@mojoloop I recommend learning c first, and if your really serious about programming, 6502 assembly. NES hacker has a great crash course on it :)
2:27: make_unique< foo > will return a unique_ptr< foo >, not a foo (assuming the std namespace was dropped)
It may work for Google but some of this wouldn't work for me; and I've been a successful C++ programmer for 30 years now. Part of that is because Google has thousands of programmers, and to an extent the convoy has to travel at the speed of the slowest ship, but there are other foot-shooting rules like not using exceptions. If the overall project doesn't use exceptions, the way to add an exception-using module is for the module to expose an API that doesn't use exceptions, but to use them inside the module. Each API function can easily trap exceptions and convert them into error codes or whatever. I use this technique myself.
I don't agree with 100% of the guide (e.g. I can't have that 2-space indentation haha), but I loved the fact the video is about C++❤️
Please keep it up.
Greetings from Germany.
People often role their eyes at style guides, or having their PRs blocked because it doesn't follow a certain style rule.
They don't understand how easy it makes for third parties looking at your code.
In the Inheritance example, the problem with the Mother-Father-Child structure isn't inherently an issue of Inheritance, instead it is just really bad design. One shouldn't use composition just to avoid inheritance, but use it where it makes sense (like in the example).
Well that isnt the only issue present with Inheritance.
Other nice situations are long Inheritance chains, especially if combined with overloads and stuff like specialization.
Inheritance chains can already make it difficult to track down where a method is coming from, but with specialization of overloaded functions, or the overwrite of methods that get called by overloaded methods in ancestors, things can get super nasty, and quick at that.
After experiencing the lack of inheritance in Rust I don't want it back.
inheritance does more bad than good.
bojler eladó
inheritance doesn't work very well in the real world. obviously, as you stated, one shouldn't use composition *just* to avoid inheritance, but 1. in most cases it makes much more sense to use composition, and 2. it is generally better to avoid inheritance at all costs.
now from what i see in the recent years, programmers gradually move away from OOP (and there are good reasons for that), and even hardcore OOP users avoid using some of its features. generally, i think it's a good thing, because we all know what overuse of OOP features of the 90s and early 00s resulted in. obviously, if you suck at code it doesn't matter what paradigm you use (and vice versa), but again, there are reasons to avoid OOP anyway.
One should always use composition.
Inheritance brings ambiguity by definition and hides the implementation details from the person who's working inside the class code. You can still have dynamic dispatch and all benefits of polymorphism without classic inheritance, even in C++ though it's not enforced by the compiler. It is enforced in Rust.
About inheritance issue with diamond example I recently found great workaround which is class Bar : virtual public Foo {} which makes Foo class only being inherited once no matter how many classes its derived by.
Its really awesome and powerful.
Tabs vs spaces is a non-fight. Use tabs with the correct indentation(read the project guidelines), let your IDE replace them with spaces. Do no check in tabs in your files and amend the commit if you did.
The fact code looks different on different editors with the tab character is the benefit of tabs in my opinion. It allows personal preference to apply to something universal. The individual programmer can choose if they prefer the tab to look like 2 or 4 spaces or whatever else. It's technically also one byte less than two space characters but that hardly matters today
I honestly think large part of this debate is really caused by Python and its inability to deal with mixed tabs and spaces. I also had issues with editing YAML files in the past for the same reason. I actually abandoned tabs for whitespaces because I was just sick of having random syntax errors showing up at runtime just because I used a \t in a sea of whitespaces in my editor.
@@Asto508 I only deal with languages that parse both the same these days.
Yeah I never understood why people are so adamant to make indentation look the same on both machines. If you need to align something visually, use spaces sure, but indentation is there to represent scopes, not for alignment. Removing tabs also hurts developers who use large or small tabs for accessibility or because it helps them be more productive.
I think the issue is that allowing tabs can result in the use of both tabs and spaces for vertical alignment. If the tab stop locations are changed, it gets messed up.
@@brandyballoon trust your programmers to use tabs for indentation and spaces for alignment? There's so many tools to detect tabs and spaces. Most editors let you visualise tabs and spaces.
I should probably read that style guide because a lot of these things I already do in my own code. Two spaces for each indentation level and I've set my tab key to insert four. Plus, since vim has dedicated keys for it I can increase or decrease indentation levels with ease. Need to push right 3 levels, 3> and done. Anyone that thinks tabs are superior should read that guide.
That guide is trash.
Very informative video. I wasn't sure what to expect, but I'm glad I clicked. The tab/space debate will rage on, but I like Google's take on it. That's not one I've heard before because, well, I've never been on a giant team like that where consistency is the key to not losing millions in a day.
That's a fun example you chose for the classes (Mother, Father, child), but in my experience, it's best to avoid the noun/verb model and just do what works best. Trying to line up everything philosophically as classes just introduces logical issues like this. In that example, you'd probably be better off defining Person, Parent, Child, and Family classes. Since children in real life don't inherit everything evenly and directly from both parents, it doesn't make any sense to define their classes like that. Rather you should define a Person that Parent and Child will inherit from, and then you can define a Family which takes two parents and a list of children as arguments. If you really wanna get inclusive, just take in a list of parents and children lol. But your point is valid, inheritance can be non-intuitive and should be handled with caution.
Or, alternatively: all people are people. You don't need a 'mother' and 'father' class, or a 'child' class. This kind of metadata belongs to a family; a family is not a person, but a lot of people in a specific hierarchy of parent -> child. That sounds like a data structure to me.
I tend to use spaces out of habit, but tabs are better for accessibility (blind programmers often use braille displays, which only offer 40 characters per line), and with the exception of alignment, it doesn't really matter if the code looks identical. In the case of alignment, you just use spaces after the tabs. 2 spaces is probably better for alignment than 4 in the case of braille displays (though a tab is still better as it's one character vs two), but then people with poor vision due to age or the like may find that such narrow indentation is difficult to read by sight. In such a case, the fact that tabs are of inconsistent width is actually a positive.
6:40 --> An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier (= 0) in the declaration of a virtual member function in the class declaration.
2:25 Ehm, no, it returns a unique_ptr (a smart pointer) to Foo (and creates a Foo while doing so).
2:29 If the type is not "Widget" then the function is wrong, not the convention. Also, just hover over the variable name to see the type in most editors.
3:52 If the class/function needs to *take over* the ownership then pass a smart pointer. Otherwise, just .get() a regular pointer from the smart pointer. Regular pointers are not evil, they are just not good at owing stuff.
4:56 That example only leaks memory because it's not using RAII, not due to exceptions. I'm sure that Google has good reasons to avoid exceptions, but this one ain't it.
6:17 Completely agree, avoid inheritance like the plague. As for interface inheritance, C++20 arguably has an even better option: concepts. Concepts can only restrict an interface and never the implementation, and unlike inheritance-based interfaces, concepts do not have a runtime impact. (The trade-off is that they do trap you in template-land).
Template-land is inescapable 😔 once trapped, you'll never see the light of explicit types again
can you also make a vid on AUTOSAR? i think it's a pretty interesting case study of a more modern approach on safe use of c++ in a critical infrastructure development
Autosar is trash. Same with Rational Rhapsody and all those similarly horrible tools the Germans like to torture themselves with. It’s a utopian approach that ends up giving you a bad product that took 2-5x as long.
I don't even know C++, but I've used these ideas elsewhere in languages I do know. Thanks for making this video!
1:20 That's actually the prime argument in favor of tabs. They use different tabs because they have different setups.
I believe in Tabs for indentation, Spaces for alignment, i.e. anything after the initial tabs on a line should automatically expand into spaces.
All editors should support this (but most don't)
The diamond problem in Inheritance,
Can be solved in C++. Because there is the concept of virtual ness which deals with that problem and prevent the base class to inherit multiple times
If you can configure your editor to write 2 spaces when you press tab, surely you can also configure how wide actual HORIZONTAL TABULATION characters are.
The whole point of tabs is that you can configure how far the indentation is for yourself and that someone else DOES NOT get to dictate how it looks for you.
yeah, that's what people arguing for tabs say. I also prefer tabs. But you also gotta see the point of consistency that spaces have.
If you're using tabs and have them configured to be as wide as 4 spaces e.g. you might add more of them to make the code look good on your end. But then someone else who has the width of tab (character) configured as 2 spaces has a completely different looking piece of code.
For normal indentation that might be fine but if you have a long function signature e.g. that you wanna break down to multiple lines, you might wanna line it up with the opening parentheses and where those are differs depending on your tabs setting.
say you have this function:
int doSomeStuff(int (*callback)(int*, int*),
int* a, int* b){
// do something...
return callback(a, b);
}
might not be the best way to format your code but in that case the width of your tabs matters. With spaces the two lines of your function signature will always be lining up.
@@vaijns I won't do that tho. When I go a level deeper in indentation I push tab once and only once. The argument list already has its own brackets; It doesn't need to be aligned.
@@AlLiberali So do I. But that's why someone might argue for spaces and why both opinions are valid, depending on how you format your code.
@@vaijns Honestly I don't think it matters. The issues of both can be solved by defining code formatting for the project. You just have to choose one and stick with it.
For example for functions with a lot of parameters you define going down a line and tabbing once.
If I were writing this guide, I would say "use exceptions for all error conditions," "write exception safe code," "generally do not catch exceptions other than when you could conceivably recover," and "use RAII to avoid needing to catch exceptions."
It's a shame IMHO that exceptions seem to be losing favor industry-wide, as they really _can_ make error handling easier and less error-prone. :sigh:
I found always one problem: How 'problematic' a problem must be to switch from status code, etc. to exceptions? For me, it was always unrecoverability. So while exceptions seems cool, there should be no more than 2-3 try-catches per entire humonguous project.
@@mastermati773 I agree that there should almost never be a try/catch. Basically, _main_ or _http/thread entrypoint_, only.
I think it's not so much a matter of "switching from status code" to exceptions as deciding at the onset of a project that you're going to automate as much error handling as possible and use them from the start. If you're knee-deep in a project that uses error codes, switching to exceptions is probably not a great idea, and certainly a huge effort.
How to write future-proof C++ for Win32: compile with Digital Mars to support Windows 95-11, by the time x86 emulation becomes popular, users will be able to emulate Windows 95 or Windows NT 4.0 without taking excessive resources to emulate newer versions!
As others have already said, the "Mother-Father-Child" example is very misleading, and imo so is the "Car-Engine" one. A car is something that "has" an engine (association), not something that "is" an engine (inheritance). Thus nobody would have wanted to make Car a subclass of Engine to begin with. This is actually the same problem as the "Mother-Father-Child" example, it's just less noticeable cause the implementation we're shown is the correct one.
tabs vs spaces should focus on one thing, and one thing only: accessibilty.
using spaces (especially small amounts of spaces like 2) over tabs forces people with vision impairment that need a larger tab-width to properly be able to code, to either reformat the entire code that they are working on (twice), not contribute to that project at all or just live with it and suffer, which i think is unacceptable.
2 spaces has never been enough for me, so I go with 4 instead like in Python, so I set my editor to introduce the 4 spaces everytime I press Tab.
@@heavymetalmixer91 yeah but what if someone needs to use 8 space width to properly code? or someone has a text size so large they have to use 2 spaces because otherwise the code won't fit in the width?
if you use tabs and set your editor to display the tabs as 4 spaces, then these two can set their own editor to display 8 spaces or 2 spaces respectively, and all of you can code with your own preferences.
it's like forcing someone to use a specific font: don't
@@m4rch3n1ng hit the tab to insert 4 spaces. That's what he said, as much as I understood. Tabs are not allowed in many places. A code formatter will solve the problem you mentioned. Tabs characters will be converted to spaces, anyways.
@@PinakiGupta82Appu yes but you should hit the tab key to insert a tab character, so other people can configure how code looks to them.
i know about the convenience, but forcing someone else to change your formatter and reformat your code, or worse, manually format your code (as is the case in the majority of javascript repos) to be able to code for literally no benefit (other than the benefit of forcing your style preferences on someone else) is extremely unnecessary and inaccessible for people who need it
edit for clarity: this is specifically about open source projects or other types of projects where multiple people work on the same code. i don't care what you do on your own disk, but you should at least think about other people when opening up your code for everyone else, especially if you are a company that tries to pride itself on "inclusivity"
@@m4rch3n1ng They will probably give you an Artistic Styler or a Clang-Format script. You'll have to run it to comply with the standard before committing the changes to git, even if the code looks bad according to someone else's preferences. Different people may have different preferences. It's not always possible to force them to accept what I want. Tabs are not allowed in many places, even if it solves the readability problem.
My opinions:
Tabs vs spaces: Disagree, it is just as easy to configure tab size in your editor. (also I find code with only 2 spaces hard to read)
Type deduction: Agree
Ownership: Mostly agree, depends on the kind of project
Exceptions: Somewhat disagree, exceptions are fine if they are documented and used only in exceptional cases
Inheritance: Disagree, diamond problem is not a real problem since virtual inheritance exists
but why would you consider "it will look the same in different editors" to be a plus? Main reason for tabs is exactly that - it allows devs to view the indentation to way they prefer it. Someone likes small indentation, someone needs large one.
Ever initialized a large struct array with data of varrying sizes, and wanted it to look like a table of rows and columns? Your tabs may make it look nice on your screen, but for someone with a different tab size, it will look awful.
With spaces it looks identical to each editor. That goes for any code that you wish to line up, such as when you have a function with many params that you wish to line up on a newline.
@@RigelOrionBeta well in these corner cases, nothing is stopping me from using spaces whenever "lining up" is my goal.. It's not argument for universal space usage for indentation.
At a large company where potentially a hundred people might look at the same code, it’s helpful to ensure they look at the EXACT same code. You’re right, it limits freedom and might make some developers slightly less happy, but it removes the possibility of bugs due to visual differences between developers.
@@RigelOrionBeta That is alignment, not indentation.
@@tidepool5400 tabs are more accessible for people with vision problems. Great minds can be left out just because they were unfortunate to have really bad vision.
for inhiretance problem it called the daimond problem , and u can fix it easily by adding virtual key word , like ( class mother: virtual parent | class father: virtual parent )
Every course I've done uses the classic animals or shapes example to teach inheritance, but none of them demonstrated a real world use case for inheritance. So the result of that is that I understand the principle of inheritance, but I have no idea when it might be appropriate to actually use it.
i suggest you find a good read on OOP principles. I have one but it's in Korean and there is no English translation afaik. The book is '객체지향의 사실과 오해' (truth and misconception about oop)
I'm reading it now so I can't summarize the key points for you either.
read the gang of four book for oop design patterns
@@poleve5409 Thanks for the recommendation
Praise the algorithm. I am going to write coding specification for my project tomorrow and this reminded me of some thing I should probably include.
I think tabs are better than spaces due to one specific reason only: accessibility.
People with problems with their vision usually have different ways to make code readable. Some people would blow up the font size and reduce tab width, some people would increase tab width instead. If spaces were used instead of tabs, those people would have to manually convert the spaces to tabs so they can customise the tab width, then change the tabs back to spaces afterwards.
Yeah, I don't really get this "looks the same" point. Who cares if it looks the same, if it has the same meaning?
Sounds like a job for the editor.
@@gagagero yeah if all code uses tabs everything will look the same according to your settings. Actually most retarded decision by google
I think it's getting better over time. Older generation is still using some weird *notepad like* IDEs because of habit. But in my circle young devs are working with more modern tools like VSC.
@@CosmicRadishes How does that relate to anything?
Why are you so good at explaining? I wish you were my prof.
I love that the solution to OOP's problems always ends up being to avoid using OOP.
No. Interface inheritance is still OOP
I'm not sure how you derived "avoid using OOP" from that video. Composition with objects and interface inheritance for different classes are OOP techniques.
@@officialraylong The "OOP is useless" crowd are not known for their critical thinking skills
@@Liam_The_GreatOOP for me is the best thing since sliced bread.
The capitalization in the title of this video made my OCD twitch but the content was outstanding!
The inheritance guide makes a lot of sense. I've seen crazy recursive or tangled object creation and method calls before, which is a pain to debug and extend further.
You can still write a spaghetti code by using composition. I've had to work with the other's code, where each next class contained one and only instance of a previous one as a private field, and not much beyond that.
It really is impossible to not write spaghetti code no matter what guidelines one uses.
@@bestnocture I'm afraid don't fully get the wording. Did I understand you correctly, that any good guideline can be abused - intentionally or not - in such a way that it's gonna lead to a spaghetti code?
I prefer tabs personally for indentation, but consistency is the more important thing
I completely agree with Exceptions, they should only be used in extreme rare exceptions and never replace an error handling.
When an exception gets through then you as a developer have made a very bad design.
Container.GetElementByID. What do you reasonably return when the container does not contain a matching element? Null -> null pointer access (exception). Default element - what should that even be? A tuple (success, element)? Callers will forget to evaluate success and element still needs to be a nullable pointer. Unions are the only thing that comes to mind. But then the interface of the method MUST list all possible result type and the error cases (which are an implementation detail) get exposed. This will hinder changing the internal implementation. Exception decouple the implementation details from the caller. A call must expect the unexpected. It get's even worth for Class.DoSomething(); A call expects something to be done But what to do when it simply can't be done? What if DoSomething() has to call other methods and those fail? Simply go back to learning exceptions...
Container.GetElementByID is a textbook example of when *not* to use exceptions. The function itself has no possible way of controlling what ID is passed into it.
By definition, an element with an arbitrary ID not being found is not exceptional (you could argue that for the set of all possible IDs, only a tiny percentage are probably in the container).
So yes, return some value (tuple, union, end()) for element not found and then slap your clients for not checking the return value.
That said, imagine your container is somehow broken. Let’s say it wraps an array pointer or a linked list. If the internal state of the container is invalid, THAT is an exceptional circumstance.
If you can configure your editor to insert spaces when a tab is pressed you can also configure how much a tab indents.
I agree on all these things, inheritance thought I feel that it really depends on what your making. In a video game or a GUI framework there is a naturally occurring hierarchical relationship. So I believe in the "is a, has a, and uses a" rules. Also a huge fan of the Gof book. Great video! If you really want safe code, you need to use a FP language like F#.
Even in game development composition is better than inheritance. GUIs can also be done by composition.
I follow the rule that if your class has more than 1 layer of inheritance, you are doing it wrong.
@@nankininkThat is a good rule to follow as guideline. The benefit and danger of inheritance is that you can modify millions of classes by just modifying the parent class. So for instance if you want to change the default speed for enemies or default size for a window you can do that in just one place. Also imagine having a biology simulator and this program having perhaps over 10,000 different species or more then you can save an enormous amount of code by using inheritance, if you have many types that differs slightly from each other. I don't use inheritance much myself but it certainly has it's niche use cases.
I would generally prefer composition in the case of a game or a GUI whenever possible. Create "foundational" classes that compose the entire structure. Keep inheritance as shallow as possible and prefer abstract classes.
@@nick15684 Yeah, if possible then do it!
@@nick15684 An abstract class is still inheritance. Especially if it's not a pure abstract class.
Also semantic issue but abstract class are actually for the sake of implementation inheritance and actual interfaces are for the case of composition
I think that if you don't use RAII and exceptions, you shouldn't bother with C++ at all. Just use modern C. Yes, that requires writing wrapper code for all incorrectly (that is, without RAII and exceptions) written C++ code.
Some of us still enjoy having access to classes, virtual methods, and templates. All of my C++ projects have exception frame generation disabled.
Modern C is an oxymoron.
@@valizeth4073 C23 standard is being specified *this year* - what do you consider "modern"?
Each environment has its requirements, and with that, opinions on how to write code are different as well. I think it's a good idea not to get wrapped up too much into any one of them, lest one becomes prone to shoehorning paradigms into environments where they're not a good fit.
Many thanks for the video. I was educated in the 1980’s in Taiwan with Pascal and 1990’s in the US. As an engineering manager for most of my career, I’ve navigated through the minefields with engineers on (2) spaces vs tab and much more on exception. Can you make this a series?
Why is it considered good when the indention is using spaces to force the same width on every developers editor? The important thing about indention is the *level* of it to convey the depth of a line in a code strcuture. A tab perfectly matches that. One tab = one level. And the width of the code is configurable to individual preferences without interfering with other developers.
Depending on the monitor a dev uses (or when having a visual impairment) you might want to have a visually easier to distinct indention (like on a high resolution / high dpi one) to see the levels better. Or you want to utilize it to force yourself to write better code by making it painful to deeply nest.
I absolutely don't see why on earth using spaces - especially just 2 per level - is a good idea...
If you disagree, feel free to throw convincing arguments at me
Consider a function that has a lot of params. What do you do? You put them on the next line. But what if you want to line them up with the previous params? You cant do that with tabs, because tabs are differing in size. Your lined up params may look nice on your screen, but not someone else's who has configured tabs to be different.
There are numerous other examples of why tabs are worse than spaces. I used to be a fan of tabs, but once I started working with other developers on large projects, I realized tabs are not a good idea. There are too many formatting problems with them.
Instead, your project should agree on an indentation size of spaces, say 2 or 4. Then configure your editor so that hitting the tab key adds 4 spaces instead of a tab.
The key thing here is you can get all the functionality of the tab key, without all of the visualization differences that the tab character will create.
@@RigelOrionBeta "But what if you want to line them up with the previous params? You cant do that with tabs"
You can use tabs to get to the right indentation level, then line up with spaces.
@@pauldegroot1959 That's pretty error prone. How can you easily tell what white space is a tab or a space? At that point, you're mostly just using spaces anyway for alignment. In fact, if you just configured your tab to put spaces instead, you'd save time tabbing to the alignment point, since it inserts multiple spaces, instead of using spaces. You'd get there 2-4 times faster than if you used spaces.
There is really no point. I used to do exactly what you are describing, but you can never be immediately sure that you have tabs and not spaces. Why bother?
@@RigelOrionBeta I didn't have an opinion but I think you've convinced me on spaces.
@@RigelOrionBeta
1. You can make whitespace visible.
2. Tabs are for indention, spaces are for alignment.
3. You can align like the following:
int long_function_name(
TypeFoo param1,
TypeBar param2,
Data ¶m3
) {
....
}
Do more like these. These are great
Ah yes, the Google code, proof even against the future, unless it's the future where they discontinue the project
i don't think they discontinue it because of bad code
Discontinuing projects is necessary sometimes.
Have you ever worked at a company that supported a product for way longer than they should have?
@@anon1963 I don't think that's what the point of the original comment was. I think he was saying that writing code for whatever particular application is designed to be future proof, to last a *long time even into the future*. However, if the project is discontinued, like the original comment said, then it can be said that the code was not future proof since it was cut short by the overall project's discontinuation.
@@Syndiate__ future proofing code = making it fairly easy to make changes and expand on it, cutting projects has NOTHING to do with future proof code. hence my comment
@@anon1963 But that's what the comment might've meant I believe, at least it makes a bit more sense to interpret it that way
C++20 or C++23 has this new feature called concepts which are essentially better versions of interfaces, especially when traditional c++ interfaces are merely classes with only pure virtual functions.
I would argue they are very different ideas. Concepts are a about controlling the data that goes in and out of objects and functions, and is related to the idea of constraints. Interfaces on the other hand are SUPPOSED to be just abstract clases with pure virtual functions. They are a way to structure the SHAPE of your data so that it can be composed though HAS and IS relationships (The core of OOP) through Interface Inheritance and composition.
I don't see concepts as a replacement for interfaces in the OOP sense. But I do like them a lot! And for small snippets of code they might entirely remove the need for OOP in the first place. Which would increase code readability and usability
@@sebastiangudino9377 you are correct, but I see interfaces as being at least somewhat related to having constraints on functions.
C++ is very oop, but if we think of the idea of an interface as (a worse version of) typeclasses in haskell or traits in Rust, then the "application" of an interface in a function signature essentially becomes a constraint on the types of such parameters that have that interface.
However, I've only superficially looked at concepts in c++ as it's not a language I use much, but that was the impressions that I managed to understand from this new feature.
@@Tomyb15 I see. I think that's a valid way to think about them! But I still think C++ lands itself better to the classical "Control shape of data" rather than the "Control usage of data" that languages like Haskell have. This is specially important for optimization purposes. This is the reason why things like move semantics are something to keep in mind in C++.
But that said, rust has showed us how both paradigms can coexist in a pretty elegant way. So I am very open to new ideas in Moden C++
1:26 the difference in tab length is noted as a benefit by tab fans. People have different preferences for indentiation and tabs allow them to use it freely. If tabs are used for indent and spaces for alignment code which should line up does line up.
2:24
a) to be precise, it's a function template, not a function
b) it doesn't return Foo but std::unique_ptr
2:50 the auto issue is controversial - a lof of editors will support rich code information and display what auto deduces too. Looking at the committee, opinions differ widely. IMO worth to mention.
4:00 I know it's an artificial example but in an education video you should do some effort and write a standard exception class caught by const reference.
5:00
a) missing semicolon at the end of class definition
b) mixed namespace use: std::string but not std::uint32_t
Also please note that Google's Style guide has been criticized by C++ creators. A lot of C++ Core Guidelines conflict with Google's guide. Google's guide is aimed mainly at Google's legacy code. Core Guidelines recomment NOT TO use it.
Man, honestly, you catch errors better than my compiler does 😂
@@اشکانمحمدی-ز1ث nah, this channel is simply of low quality
" If tabs are used for indent and spaces for alignment code which should line up does line up."
Or, you can just use the one character that will always work and always be correct. I have never seen tabbed code that wasn't messed up. Not once. It's impossible to maintain invisible characters.
@@isodoublet I frequently see pure-space code that also isn't aligned. Some people will fail at both no matter what.
@@Xeverous Everyone fails at aligning tabs, so that's no excuse
so that last part is to follow SOLID design. Each class holds unique concerns, and use composition over inheritance, so that functions and responsibilities stay separated. Inheritance has its place, but is not engineered correctly. With classes that mainly hold data and handle some transformations inheritance is not well suited. For objects that build upon each other like window systems, then behavioral design there says that inheritance is good.
With all of this said it is impossible to write debt free code. We are developers. The use of tabs should be encouraged. Set your editors as a preference. We engineer differently and have unique styles. Some solutions are only found when people can be themselves. All of this will lead to debt though in the sees of style.
The issue here of debt free code is not the style of coding that one uses. The issue is how to engineer properly. This video touched on using interfaces. Interfaces are really important and needed in all projects. We should be designing for interfaces as that allows for modularity. Need a new way to access data? Not an issue as along as the data access returns all of the correct data sets. Which data sets are there well that is where an interface comes in, as the functions should be set based on the business logic necessary to run the front end. In this way we can reduce debt as we are only changing one concern at a time. Debt is not style, but failings in logic.
I also disagree with the non-use of exceptions. Exceptions are not just program breaks, but are failures in design, and should be looked into. Without the exception we have no idea why the program just crashed. What is needed is a better way to handle logging. They will need a standard library for logging exceptions. It is now each concerns responsibility to report the error to the logging and then handle the exception per the concern. In the example in the video the function g handles no exceptions from H or more likely handles errors in H by raising the exception again, which passes it up to F. This is an example of poor design. where is the separation of concern? if function F is the concern and functions G and H only perform data manipulation, then the responsibility for error is at function F. if each function is its own concern, then we need a way to decouple these nested calls.
Hi
Hello
@@fuery. hello hi
uwu
@@LowLevelTV youtube: yes this perfectly translates to "this", such logic
hi
4:54 The rule I have on Exceptions is. Don't. ever. use. them. -Validate your data, provide return codes accordingly, check return codes from functions you use. Wow, now you don't have to worry about exceptions jumping over your head. Not to mention throwing an exception take the program's execution pointer away from the problem. -Why would you want to do that in the first place.
Good luck dealing with failure in constructors then
@@Henrik0x7F Wow, how did you make constructors fail? You're only defining default content of structures.
@@smallbluemachine Vector's constructor can fail for example. Really not uncommon
So you want to pre-allocate a huge gob of memory that might exceed physical AND swap memory combined and kills the program? Well I’m not gonna hire YOU then, am I.
@@smallbluemachine You don't have to allocate huge amounts of memory to run out, do you? Also that was an example. The constructor should always create a valid object. That might fail for lots of reasons: File handle can't be opened, connection times out, etc. The alternative to exceptions is a .valid() method which is very bad style
Really curious to see if Carbon will be designed with a bias towards Google's style guide. Are there C++ features for which they won't build compatible functionality in Carbon, or will they aim to be 100% compatible with the entire C++ language?
Can we have a video on "How google writes gorgeous java?" , if possible . Love your videos
It's funny how half of the things are just "do it like in rust" lol (e.g. having only one level of inheritance and only with abstract classes as parents is basically rust traits)
Rust is made with a 40 years of history of writing terrible code in C++. Makes sense they dropped some concepts that have been proven to be extremely bad.
You could see the same in earlier languages, for example, C# and Java removed the multiple inheritance and encouraged the use of interfaces. All mainstream languages (incl. C++) play with the functional programming. The most modern languages (Go, Rust, Zig) drop the exceptions in favor of C-style error handling with syntactic sugar. This is basically a trial-and-error on the scale of generations of programmers, and while it's painfully slow, it's a steady progress towards the perfect programming language in which it's harder to write bad code.
Because if it's possible to write shit, it will be done, and very fast. Javascript programmers cried in tears with jQuery until came the frameworks that enforce their architecture on you (React, Vue, Express, Nest, etc.)
@@theultimateevil3430 Yes I totally agree with your analysis
the spaces over tabs is a serious accessibility issue. Programmers with visual impairment need the ability to customize their tab width. Spaces make that nearly impossible.
If you have a codebase in large company and you switch from tabs to spaces, expect 2 phone calls:
1. from the legally blind person who just lost their ability to set tab-width to 1 in his font-size 70 editor.
2. from the dislexic person, who lost the ability to set the tab-width to 8 to make the indentation readable to them. Good luck undressing those 2 problems simultaneously within space-only policy.
"the spaces over tabs is a serious accessibility issue. Programmers with visual impairment need the ability to customize their tab width. Spaces make that nearly impossible."
So your solution to the code looking bad for some people is to make it look bad for everyone? Doesn't seem like much of a solution. Just, like, increase the font size. Buy a bigger screen. Using proper code typography is not an accessibility issue at all, let alone a serious one.
@@isodoublet How do tabs make the code look bad? They are literally just whitespace, just like spaces.
@@KohuGaly Because you'll mess them up, because they look just like spaces. No tabber in the history of the world has ever failed to mess it up.
1:20 That's the whole point of the TAB character - it lets you adjust the visual amount of indentation to your liking without modifying the code. The fact that the code can look differently when viewed in editors with different configurations is not an issue but a feature. The rest of the rules are perfectly reasonable.
Yeah but that's exactly why the TAB or \t special character is so bad in text editors - it's not monospace. It takes up some unknown integer amount of monospace blocks. The same way you don't want to write code with crazy Unicode characters in naming conventions (and that's if the language even allows them), you don't want TABs themselves. You just want the utility TABs provide, hence the spaces.
@@afelias As you said, tabs take an integer number of monospace positions. Therefore they don't mess up monospace fonts - characters typed after tabs are still aligned to the monospaced grid. I absolutely do want tabs themselfs because they provide better utility than spaces.
Vindication, mine at last. No tabs ever, and two space indent is all you need in life. Lines wrapping unnecessaily due to large indents may be the bane of my existence.
Also, begin/end braces should align in the same column 😄 🤜Fight me 🤛
two spaces.. bruh..
I do dat I don't like tabs
@@quezip tabs make your files smaller
@@Lighter7900music and..? I'm not here with like 2 mb of space
@@quezip Same, spaces makes it much more easier and read-able.
🤮
these are good principles which most of experienced developers find and follow by themselves
Good old spaces vs tabs. The only situation I dont like spaces is when one arrow key press doesnt move one full indentation or backspace doesnt remove full indentation.
Just hold ctrl and boom
@@nilau8463 that's what I tell everyone who say spaces are annoying... How does that change anything for you when using full word directional arrows movements?
The composition vs inheritance debate was always obvious to me. Inheritance means something "is" that class with extra stuff, composition means a class "has" another class. A car isn't an engine with extra stuff, a car has an engine. A child isn't their mom and dad, a child has mom and dad.
C++ is plain awesome.
I started my low level journey with Rust, but over the years I’ve found myself favoring C++ more. The flexibility, customizability, and power are intoxicating. I’m glad you’re clarifying Google’s guide to make the language more productive for all.
Also, you can see a lot of these design choices actually implemented in Go’s language design.
“Tab width might be different from one editor to another” that’s the point of them!!!! 😭
I hate it when other engineer’s tell me what my indent should be, write better code that doesn’t rely on horizontal alignment to actually read it. Maybe someday source code will just be ASTs and I’ll be able to have the style I actually want.
A good way to make code readable is to line up opening and closing braces. Microsoft does that, but most other companies don't, for reasons of fashion rather than logic. Even better, use Whitesmiths style; but Microsoft style (braces line up and statements are indented relative to them) is okay.
That no exceptions rule sounds strange. I wrote a dice rolling program that takes a RPG-formatted (e.g. d20, 3d8, 2d6+1) string and parses out the number of dice, faces of dice, and modifier. It was much faster to just write "try{std::stoi(s);}catch(...){}" then to for-loop through each string and do an isdigit() check against it, with the added benefit that if the user puts in a number > INT_MAX, it will still handle the exception by printing an error message end exiting with a failure.
Trying to do pure input validation seems like it would make for less elegant code for the most part.
Why is there an argument about tabs vs spaces? A tab can be converted to spaces, and it is a single key press. It can be converted in your editor to match any number of spaces.
On the other hand, manually pressing the space bar for 2 or 4 spaces has issues if you don't tap the right number of times, it is harder to do and more error prone. And if somebody else sees the code in their editor, they might not be able to change the spacing to match their preferences. I can't believe this argument is still happening. Tabs should win outright with no competition. Oh and also tabs are smaller in file size. Need more persuading?
tabs vs spaces is not about pressing the tab key on your keyboard or the space key (it's always pressing tab). It's just about what is inserted when pressing tab. (mostly) all editors give you an option to define how many spaces should be inserted by the press of tab (or no spaces but stick with tabs).
While tabs allow every user to define the width of their indentation themselves, spaces force the width which helps with consistency (depending on how wide your tabs are you might add more or less of them in your code, which could look weird on someone elses device).
Absolute horseshit. No one who uses spaces ever presses the space bar to insert their spaces. They let their editor insert 2-4 spaces when they do their "single key press" of the tab key. You don't have to press it the right number of times. The workflow is exactly the same.
The problem is when tab people try to use their damn tab characters in other places than the beginning of the line, they fuck up everyone else's code alignment if the settings are not exactly the same between editors. Tab people end up with alignments like:
const int short\t\t\t= 1;
const int longvariablename\t= 2;
And it aligns perfectly on their tabwidth, so they didn't think that it wouldn't work on anyone else's. If the advantage is that everyone can set their own tabwidth, why do they introduce code that misaligns with different tabwidths?
Another example is for function signatures where the parameters are on different lines. Spaces is the only way to align them with the start of the first param.
If tab people used editors that could put tabs at the beginning of a line and spaces in the middle, that might be okay, but they never do. They litter the code base with awful tabs in the middle of lines.
I can't believe this argument is still happening. Need more persuading?
@@BlueEyedSexyPants I think as long as you're consistent within a codebase both are fine. I for example prefer tabs to have my indentation just the width I want. And I don't use any tabs for aligning assignments and for function signatures I just add one tab to the horizontal position where the signature started (usually the return type). I agree that lining up with tabs doesn't make sense. But it comes down to how you format your code if it is a problem or not.
As I said, just keep it consistent within the codebase. If I'm working on someone elses codebase, surely I don't force my tabs but I also try to format my code based on what's already there (like, are function signatures aligned at the same horizontal position or not, ...).
A lot of code I'm working with uses 4 spaces and I'm not a huge fan of it as I think that's too wide. But that's not my choice to make if it's not my codebase.
@@vaijns Yeah, if everyone in a codebase is perfectly consistent, that's fine. So if the codebase wants you to set your tabwidth to 8 but you prefer 2, you either need to set it something you don't enjoy, losing the supposed advantage of tabs completely, or you need remember every time you insert your 2-space tab that everyone else will see it 4 times larger. (8 is insane, of course, but just for the purposes of illustration.)
@@BlueEyedSexyPants that is a good argument with mixed usage in situations other than code indenting.
Ultimately I've just accepted the situation as is. However sometimes it's very much annoying, eg. when I write documentation with TeX and similar. You can include code directly from the source file, which is my preferred way as it avoids me forgetting to update code after changes.
But if you used 4 space indenting (as is the default in most Code bases and also most formatters), this makes most code hard to include, as that quickly gets too long with little indentation.
Similar thing when I open some code in a small window /on a small screen.
Google's policy on the use of spaces has been my policy in every language I've coded in since 1976, except for assembler, G-code, and antiquated versions of BASIC.
My code is in no way future-proof, it is overly compact and simultaneously not, it is the embodiment of spaghetti code and I myself have a hard time reading it at times.
This is a mistake. Glad Google isn't making it.
Edit: dang didn't expect the replies to be an argument on the readability of code relating to how easy or hard the code was to write lmao
If it was hard to write it should be hard to read.
@@pierelenigus8598 I mean you have a point
@@pierelenigus8598 No, not really. Hard ideas can be expressed in a simple way in most cases.
@@pierelenigus8598 it should not if it's a finished work. After you wrote a working implementation it is messy indeed, but then you usually can optimize readability by a lot without chaning the logic. The code is finished not when there is nothing to add but when there is nothing to remove.
@@DajesOfficial Well if you're not busy and in demand problem solving solution provider I reckon one would have time for all that. As far as I know the real world a working solution is a completed solution.
100% agree with the first rule. "Use 2 spaces"
I can begin my weekend now 😎
I find the rule about auto particularly funny. It completely contradicts python enthusiasts who say that python is easier because you dont have to write types.
I completely agree with google here. Types help read the code, it is not a good thing not to have them.
Funnily enough, python is now considered a strongly typed language. How things have changed. ;)
Explicit typing everywhere makes refactoring much harder. In many many cases they're an implementation detail; it's important that they match and I'm grateful that the compiler checks that they match, but what I need to know is the interface being used and behaviors relied on in their current context, not whatever name was given to them elsewhere in the code base.
@@isodoublet i am actually not that familiar with c++, more with java. There it is common to use only interface types where possible. Is that not a thing in C++?
@@christianknuchel By who? People who eat crayons?
The point of tabs is to look different based each engineer's config. Some people may like 4 spaces, others 8, some 2. You can't have that customization with spaces.
I'm not agreed with all the point Google makes in this guideline, but I admit this is a good guideline to learn about good practice in C++.
Tabs > spaces
Just a small nit, but in modern C++ there is NEVER a reason to deal in naked malloc s or new s. Just use smart pointers anywhere you might need to malloc or new and you never have to worry about use-after-free or ambiguous ownership. If you need to more directly control memory lifespans, use custom allocators instead. Although I agree with Googles no-exception style requirement, using smart pointers also ducks many of the early-return problems making exceptions somewhat less troublesome for legacy projects.
A fun thing, this is how google does INTERNAL things. Here they care about developers. They FORCE you to break a lot of these if you use their IDE's. Because Google does not care about developers that are not working for them.
Please do a video about Apple's coding standards/best practices.
There is no such thing as future proof code..
I really liked this summary, well done👍
Actually what Google did is already taught in most University... But I still use 4 spaces indentation. Because I feel the code reads better with 4.
You can configure The Editor to do TRT when you hit tab. Hence not vim or other stuff. 😊
spaces are inaccessible. some people's eyes or visual cortex just doesn't read the code easily unless they can set their indentation to something crazy. with tabs, that's trivial, and editor-specific; it doesn't bother other people if my IDE shows indentations at 8 characters. with spaces, google is forcing everyone to have the same experience, whether it accommodates their visual processing abilities or not. not to mention that they mandate TWO spaces, which is bad because it inherently encourages deep nesting.
Yes! "It looks different for different people/editors" THAT'S. THE. FUCKING. POINT. If I want my tabs to be 3.141592653589 spaces wide because [reasons] that's none of your business. What's next? Storing code as PDFs to preserve the company approved font, size and color?
I would even say this is straight discrimination of visually impaired people and it's disgusting.
Lmfao 🤣
I've worked at companies that used tabs and companies that used spaces. The companies that used tabs gave me a much harder time reading code because I would often have to manually change my tab width to match whatever the original author used. Which is a problem in a file touched by a lot of devs. This is a largely a problem with people not understanding the difference between indentation and alignment.
"some people's eyes or visual cortex just doesn't read the code easily unless they can set their indentation to something crazy."
Such strawmen can pick a different career. It doesn't justify having the code formatting suck for everyone, sorry.
@@igorordecha "THAT'S. THE. POINT. "
Everyone knows what the point is. You're just wrong.
:set expantab, :set tabstop=2, set shift width=2
Basically Rust. Now I get it
"Spaces only, and two spaces per indent. Now, we will be... hey, where are you going?"
All of those seem great ideas - except perhaps about the strict use of auto. Many modern editors can automatically display the type of an auto-variable, so there is no loss of understanding really.
I actually think Google just manually enforcing what the rust compiler is enforcing, but in C++.
The model of ownership, standardized linting, error handling, etc
Do you think using 2 spaces in C++ is a great idea? Really?
If your code is unreadable without a LSP, it's probably not great for collaboration.
How did you know what the type is when reading it outside of an editor? Like when doing code review in github or whatever?
It is true that, at least for the near future, relying on this automatic type information, would lead to some restrictions in which tools people could use when they want to read a lot of code they are not familiar with.
But, using 'auto' can also slightly increase the readability of relatively well-known code, because generally the variable name should carry the relevant information, and whether 'nItems' is an int, uint64, or even some custom counting-class with its own ++ operators, is really more of a detail.
So, I am not sure, I don't think Googles choice is bad, but there is a tradeoff, and the availability of better tools shifts this tradeoff somewhat.