Comments by "MrAbrazildo" (@MrAbrazildo) on "The Beauty Of Doom 3 Source Code" video.

  1. 1:38, I used to dislike #ifdefs. Nowadays, I think they are quite nice, because they help to debug. For instance, if a block of code won't be used in some compilation, that code won't actually exist, even raising a compile error in case some piece is missing. So this is already a check, a confrontation vs what the coder is thinking. And it's possible to keep switching the switches, getting a quick statistic effect about any bug. Codeblocks IDE can "blur" blocks not targeted to compile, a pretty nice visual effect. 4:19, I agree with you, because people use to think that Single Responsibility Principle is technically only 1 thing, but I think it may be semantically, instead of technically. So a f() may do several small/tiny technical things, to achieve 1 goal. This way, outside the f(), the rest of the project can look at that f(), thinking about that goal only. It's already an isolated functionality, despite the fact it takes more actions internally. 4:31, I completely disagree here. I already wrote tons of words in a video of his, uploaded by other channel. If someone is interested, I may write some words here too. 6:28, sorry, dude, we are waiting for Carbon. If only it changes that bad syntax... 14:35, I think this is much more important than it looks. I can't prove it, but I feel like spending more energy when travelling vertically. So this should be avoided, whenever convenient. 18:02, I personally omit { }, because I love compact code. But I wouldn't argue vs this standard. I would put them on the same line, though. 18:21, in C/C++ the if isn't ruined by comment, even without { }.
    1
  2. 29:24, I agree, but I would never rewrite STL because of that. My f()s and classes use to not be generic, whenever possible. For things coming from STL, I use typedefs. 30:15, this is a Java thing. Well coded C++ use friend keyword, to allow just a few f()s to access nonpublic data. 31:43, std::stringstream is just a higher level scanf. And faster, according to a measure I took. I would only argue against it if performance was at stake on it: pointer, for instance, is much faster. It's syntax is not ugly to me. And std::to_string does the trick, if this is the only reason of using this stream. 32:25, 1 line f() could fit inside the class definition. And using std::clog, to not be generic, would dismiss receiving ostream and another class too. Result: auto show_val ( ) {return std::clog << val;} Plus, even using the overload, it could be made via: std::clog << "blablabla" << object.get_val(); I think the code in the video is beautiful, if 1 desires what it offers: throw strictly the object (not 1 of its members) to an object that is or inherited a std::ostream. What is stupid and ugly is to write a f() like that (in the video), when 1 would be satisfied with the already existing 'std::ostream::operator << (int)'. And printf is better only when several values are being read at once - otherwise it's less productive, due to type specifying ( + warnings) and demanding more typing on keyboard. So their thesis of condemning streams fell flat. 35:25, I have a tolerance about 1 line f() definition (below its header) inside class definition, because I can still put { } on the same line. For more than this, if { } is used normally, it starts to push the code downwards, looking noisy to me. I also try to align returns, f() names, 'this' specifier, and f() definition, whenever they are "attached" (1 right below the other). Of course, I don't put these many stupid unnecessary spaces between the "fields". (35:39, giggles) About the horizontal look, it's ideal for eyes, since they are widescreen. Code is ideally meant to be looked by eyes, not with help of hands, unnecessarily travelling vertically.
    1
  3. 1
  4. 22:36, C++11 also had for range loops: for (myType &value: vector_of_type). But I kept using the old for, through a macro like: myfor (it, vector_of_type), because I felt counter-productive to have to specify the type used by the container. I only embraced for range loops in C++14: for (auto &value: vector_of_type), using auto to kill that faulty feature. 25:02, I disagree, because these things are keeping themselves generic enough to work with any type. And everything is separated by scopes, that's why so many :: operators. C++ even has a kind of dry syntax, compared to how many things it's handling on those libs. 1 has to compare beauty to what it's trying to achieve. 27:00, macro can clean this code. While the lib has it in its generic form, to hold all possible user configs (and I think it's beautiful, because it achieves that, with likely minimal syntax) , the user don't need to do that. If it happens to has several arguments, just make a macro or typedef about its meaning: #define ParamsForHashDecl typename KeyType, typename ValType, // ... the rest. #define ParamsForHash KeyType, ValType, // ... all the rest. using ProjectsOnlyHash = HashTable <ParamsForHash>; // Alias. Since this is made only 1x, similar f()s headers would be like: template <ParamsForHashDecl> const ValType &ProjectsOnlyHash::getValue (const KeyType key) const; getValue is a function from the class 'ProjectsOnlyHash' (1 doesn't even need to read its template args) , that receives a KeyType (that can't be changed) and returns a reference of some ValType, which can't be changed either. The f() also can't modify data from the ProjectsOnlyHash class, except those declared as 'mutable'. At any time throughout the project, if the user wants to remember what is ProjectsOnlyHash, or its template parameters, just leave the mouse over the respective word.
    1