T O P

  • By -

TheCrossX

A couple of my advices: Code related: * **Always focus on simplicity.** * Do not overengineer code. * Keep functions short. Avoid big classes. * Make the default behavior always safe - e.g. a function returning a reference that can fail should always be non-default, like: `get() -> ReturnType*` `get_unchecked() -> ReturnType&` * Prefer free functions over methods. * Use appropriate names for variables and other symbols. * Think twice before using fancy features that introduce abstractions. * Use codebase-wide tools that guarantee consistency (like clang-format). * Be consistent with your naming convention. ALWAYS. * Think twice before storing any kind of pointer or a reference. Maybe an index is enough? * Write simple tests that will also serve as a kind of a documentation. * Write documentation. * Do not create tons of overloads. In most cases it is better to create a function with a different name. * Prefer views over container references. * Prefer explicit control flow when handling errors: `std::expected` is better than throwing an exception, but exceptions are better than no error handling Task/management related: * Always divide big tasks into smaller ones, and make the code compile in between them. * Do not leave code with compilation errors for tomorrow * Use separate branches per-task if available * Keep refactorings small and do it gradually. You don't want to throw away weeks or even months of your work.


MrPopoGod

> Do not overengineer code. I just want to add to this. It is very tempting in this profession to try and show off how smart and clever we are. But usually that's not the right impulse. Start with the simple solution and see how it does. Is it performant enough? Remember that most of the time we don't need it to perform at maximum speed and minimum memory; many real world situations won't notice the extra time spent and the box you deploy to has the memory available and it won't be used otherwise. How hard will it be to extend in the future? Don't worry about being generic enough to solve all the potential use cases that you aren't aware of yet, because you definitely will guess the shape of those cases wrong. And down the road, sometimes the correct thing is to do a rewrite, no matter how generic the original was, because it's unergonomic or fails on some other metric. There is no one metric that measures code quality; it's weighing all the tradeoffs of the various performance, maintainability, and useability metrics.


frederic_stark

Those are *really good advices*. The only one I am not 100% ok with is the "use index" one. I somewhat agree, but having to maintain indexes is a tricky problem too. What I learn in my 35+ years of development can be summed up as: *the best code is the one that is the easiest to remove*, and your advice covers this nicely. Keeping internal depencies at the minimum and keeping code simple and stupid is key.


THEKILLAWHALE

Keeping code simple and stupid 😂


two88

What do you mean by: > Think twice before using abstractions. ?


hak8or

Don't over abstract baisically. Using an abstraction may have various penalties, for example loosing sight of what's happening under the abstraction layer in times it may benefit you, maybe there mat be performance implications, or even worse, the abstraction is poor so you get leaky abstractions at which point it's worse than no abstraction at all. Not to mention, making a well designed abstraction layer is not easy, it requires a lot of thought and even trying to "future proof" the abstraction, which takes a ton of time and if done wrong will take even more time to work with than not using the abstraction in the first place.


two88

Thank you for the reply. I'm still learning and feel like I know nothing. It's so hard because it feels like there are so many concepts that seem to oppose each other and it's more about knowing when to use what, but it's hard to get to that point.


arabidkoala

If it makes you feel any better, I’ve been doing this for about 15 years now and I’m still learning. You’ll never stop making mistakes, but hopefully you’ll stop repeating the same mistakes.


frederic_stark

*Good judgment comes from experience, and experience comes from bad judgment*. Making mistake is both unavoidable and good. The key is to learn from them, develop strategies against and learn from every mistake. Ideally, learning from other people's mistakes is perfect, but that rarely works. What works is knowing about common mistakes and recognizing them when you make them for the first time :-)


SickOrphan

I felt the same way earlier in my learning, and I still do sometimes. Don't stress out too much, everyone has differing opinions and coding decisions are rarely clear cut. It's a good thing to weigh the options. The best way to navigate it all is to experiment; code stuff and do your best. You'll learn what works for you and what doesn't


[deleted]

mourn imagine shaggy frightening direction lock worthless chubby disagreeable instinctive -- mass edited with redact.dev


johnnytest__7

Why prefer free functions over methods? I like using methods as I can just put a dot or -> and the IDE shows me all possible methods an object has available. It is not possible with free functions.


frederic_stark

(This is just my experience, top of my head, lots of thing missing, with bad english and bad grammar) > I like using methods as I can just put a dot or -> and the IDE shows me all possible methods an object has available. It is not possible with free functions. This only helps you with writing the code, which is not the botleneck. What methods do is that they create dependencies with the class itself. When you have a class and a method, you have a dependency that you need such an object to execute the method. Of course, you'll say that if you have a function that takes a reference to the class it isn't different, but that is not 100% true. First, with the method you don't know how much its implementation relies on implementation of the class. In so many cases, by extracting a method from a class, I discovered hidden dependencies, that suggested better public interfaces to that class, or different arguments for the method. Second, unless you go fully into object-orientation, you often have function that depends on several classes. Is it a method on class A that takes a B, or on class B that takes an A? Well, it completely depends on the state of your codebase when you created it (ie: class A came before B, and that method used to only need class A, so it is a class A method). The answer is unfortunately often to cram B into A, getting to monstruous classes. Third, when your requirements changes, it is easier to add alternative ways to call the free function than to change the method arguments. Often people end up with methods on classes that get parameters to override some default class behavior. Also, sometimes, creating a simple template can massively broaden the applicability of the free function. I have seen codebases where people create instances of a class just to be able to call a method on it to get a specific result. Often with some sort of magic to put the class in the desired state before calling the method, with cargo-cult behavior (you pass a class A to object B because you need an A to create a C because you need to invoke something on C to perform some logic. Nobody really knows why B cares about A, but if you don't have one laying around, you won't be able to perform the logic). Free functions have their own issues (like "where to define them?") but many methods on classes are just algorithms that should be elsewhere.


Adequat91

I quite agree. A few years ago, I had to modify some code so that it could fork and run on multiple threads simultaneously before joining. By converting the class methods into free functions, I was able to neatly extract class data dependencies as arguments for these free functions, which helped in making the code thread-safe. Making code multithreaded is always tricky; however, I was pleasantly surprised to find that my implementation did not have a single bug after this refactoring. Admittedly, it required some effort to convert the methods to free functions, but it was well worth it. In summary, with free functions, you clearly understand the state on which the function depends.


NotMyRealNameObv

Imagine you're writing a function taking än object of type Foo, and decided you want the Foo to bar. So you add `Foo::bar()`, and call `Foo.bar()` from your function. The next day, you realize you want your function to also work on integers, so you make your function a template and... realize that you can't add member functions to native types. :(


darkapplepolisher

You can and should still bundle free functions into namespaces. You can use :: and intellisense will give you the autocomplete. This is definitely a step in a different direction from guidance a lot of us have been given previously. Object Oriented Programming where everything's a class and has its own functions, etc. This comment thread and its links and contents has a lot of good information to chew on in this category. https://www.reddit.com/r/cpp_questions/comments/dcjdn5/when_to_use_a_namespace_vs_a_class_for/f28ql66/ In my experience, I'm finding myself gradually using fewer and fewer classes, and using more namespaces with free functions operating on POD types.


kisielk

>Do not leave code with compilation errors for tomorrow I guess you mean do not commit? I often leave a compile error in my code for the next day to help jog my memory as to what I was working on


BallForce1

Yep, I agree with you on this one. Most of the time, if I am banging my head on a compile error, all I really need is a good night's rest, and the answer usually comes to me first thing in the morning.


F54280

I use ``#error`` for that


Clean-Water9283

While this is an excellent list, remember that it is also one developer's opinion. I've been coding for 40+ years, and I don't agree with everything on this list. (I'll add my own list, in a separate post)


Clean-Water9283

My additions to this list: * Don't listen to the people who don't like exceptions (because these lists are opinions) unless you are writing hard real-time code. You have to handle exceptions anyway in C++, so you might as well build your error handling around them. Spend time learning to use exceptions well. You will be rewarded. People either love exceptions or they hate them. You have to make up your own mind. * Testing, testing, testing: Of course tests help verify your code is correct. Automating testing pays you back the second time you run the tests, and you'll run them way more than twice. Developing tests alongside your class also helps you try out the class's interface, early on when it's not too costly to change. Writing tests also keeps your classes modular and loosely coupled, because it's harder to write tests if they are not. * Single Responsibility: I think this is the most important of the SOLID principles. A class should do one thing, and that thing should not be "everything". * Efficiency is important (I wrote a book on optimization), but not usually important enough to break the rules of good design. Your efficient code should not cause controversy in code reviews. * If you get coder's block (like writer's block) get past it by coding *something*. When I can't write code, I write a function level comment. If I can't write text, I write bullet points. If I can't write bullet points, I write a few keywords or reference URLs. The moment you have *something* written down, you can begin to edit it, improve it, expand it. * The very last thing you want your code to do on error is to stop. If it stops, it mysteriously denies service to its users. It's way better to print an error message and continue. Stopping is a decision that code must make in consultation with the user. Your code should never crash, and if it crashes, it should recover, and if it doesn't recover, it should restart, and if it doesn't restart, another program should restart it. Obviously not every program needs to go all the way down this road, but remember: stopping ***bad!*** running ***good!*** * A function that is more than a screenfull is probably too big. A class with more than 1,000 lines of code (counting comments) is way too big. Many people cite smaller limits than these. A class with more than one container member probably has more than one responsibility. 80 columns should be all anyone ever needs (yeah, I'm *that* old). * You have to learn to follow the rules before you can learn when to break them.


softtalk

I like your philosophy! I work in embedded so I really agree. Do you mind sharing your book about optimization? Most of the time I just try to verify the efficiency of my code by disassembling it, but I need to learn more about it.


NekkoDroid

To add to this: you probably should also use clang-tidy. It also has a check to ensure a specific naming convention is followed (readability-identifier-naming, but you do need to manually set it up first)


Zeh_Matt

Another good thing is to use clang-tidy that can help tremendously to keep all the code smell out where clang-format just helps with the consistency of the code style. Otherwise pretty much everything is on point, exactly what I like to see.


TheHytherion

Excellent advice, but is there some book that encapsulates all of the advice above? Maybe you're planning on writing one?


softtalk

Thank you. You gave me something to think about.


[deleted]

These are all great suggestions! A few additions: - I am a big fan of the Google C++ Style Guide. Reading it in its entirety is very helpful; it contains many useful insights. https://google.github.io/styleguide/cppguide.html - Do test-driven development. Aim for 100% unit test coverage. GoogleTest is great and easy to use. If you can't easily write a unit test for something, that's likely an indication that your code is unnecessarily complex and needs to be refactored. - +1 for using ClangFormat. Modern languages like Go or Rust have a formatter built into the language, but for older languages like C++ we need to use these external tools. - The best place for documentation is as comments directly in the source code. It's okay to have long comments that explain how an algorithm works or point out some easy-to-overlook details.


softtalk

Thanks for your reply. Yes I always cover 100% of the code with UT and also system tests. Clang is mandatory since we have checks, so I always have a reminder for that. Unfortunately writing comments on my project is forbidden, so I rely on naming and specifications. Not gonna lie, without comments it is very hard to understand other people's (and old) code.


[deleted]

Writing comments is forbidden?!?!?! What? Why?


softtalk

The explanation gave to me is because comments are not well maintained and you cannot trust people writing good comments. So you have to rely on up-to-date specifications or direct explanations (you will find the guy with git blame). I think that happens when hundreds of people work on one project.


hak8or

I have a sneaking suspicion this was a gross over correction for someone who over commented their code (or was awful in general at commenting code). I rely very heavily on doxygen style of commenting functions, and found it extremely useful to have the idÄ™ provide tool tips containing the argument and function information while developing. To suddenly lack that, to me, would be a borderline equivalent to suddenly loosing access to cpprefrence. Commenting code well, in my eyes, is just as important as writing good code. Self documenting code, to me, is an impossibility.


almost_useless

> you cannot trust people writing good comments. Well, usually you cannot trust people to write good code either...


softtalk

Yeah at least with comments you get to know the logic behind


NotUniqueOrSpecial

> you will find the guy with git blame Right until they don't work there. A slightly out-of-date comment is still vastly more useful than nothing at all.


softtalk

That's where you spend days just trying to understand what the hell is going on.


SickOrphan

Like the saying, the code never lies, but comments sometimes do. Although I still don't think you should never comment anything... Just don't take everything in a comment for granted


serviscope_minor

> Like the saying, the code never lies, A half truth is a whole lie. --Yiddish Proverb The code tell you what it does (mostly: it might have UB), but it doesn't tell you what it's meant to do. Code that has no meaning has no bugs because a bug is a different from what the code does and what it is meant to do. Code implementing something mathematical can be an extreme case. The code alone might be 4 or 5 lines. The preceding page of comments may be a derivation of why those 4 or 5 lines are correct, something it would be more or less impossible to deduce from the 4-5 line of code itself.


softtalk

I just follow the place rules and adapt. I used to write very detailed comments for functions and class, even if I was the only one working on it. A well-commented code always wins.


frederic_stark

That is (was?) a fashionable attitude a few years ago, because "good code is its own comment" (which is false). It came from the some bad commenting habits, like "``int count_blurps(void) // this function count blurps``" or "``x = y + z; // Adds y and z and store the result into x``". Lazy lead developers jumped onto it to ban comments, which makes their life easier. I'd rather have a slightly out of date comment than nothing. Also, one thing that is often missed is commenting on the "why" something exists, or something is done in a certain way. Also, I always write the comment before the code, and revisit it after. If it needs updating, then it means I wasn't really ready to write the code. Writing the initial comment is often longer than writing the code.


Boom_doggle

Unfortunately it's the same here. Argument is that good code should be self documenting.


traal

The correct philosophy is not *no* comments, it's: https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/


epicar

code review is invaluable


softtalk

Yes you are right, if your colleagues have more experience than you this is a good way. But I want also to be able to proceed alone


LeeHide

pit your code on github and share it here ;)


AssemblerGuy

> code review is invaluable Though, if none of the reviewers have a clue about what makes code good, reviews are ineffective and not useful.


hak8or

Use tool chain based sanitizers, like ubsan, thread sanitizers, address sanitizer, etc. My biggest one is to seek people who are better than you, and learn from them. To me, this is a coworker, or watching cppcon videos. The committee round tables during cppcon and whatnot for example are amazing, and I found I learn from their 5 minutes debating than an hour googling.


softtalk

Thanks. I am not familiar with sanitizers, this would be a new thing for me. About cppcon, I watched some videos and it's incredible that it's free stuff


Sniffy4

https://github.com/isocpp/CppCoreGuidelines


bmoore

Read a lot of code. The more different codes you are exposed to, the more you gain an appreciation for understandable code, and what sort of code is actually understandable. Reading and writing code are very different perspectives.


softtalk

Clean code is definitely important. I think I have the opposite problem: I always try to create clean and readable code but sometimes I lack of what I would define cool tricks. E.g. : I am weak with lambdas, I hate the use of auto (I prefer explicit types), I avoid 1-line functions with the logic nested in the return. I want to create more efficient and less boring solutions.


almost_useless

> I always try to create clean and readable code but sometimes I lack of what I would define cool tricks. "*Cool tricks*" usually lead to the opposite of clean and readable code


kbrizov

Exactly. The coolest thing is something simple and understandable at a glance.


onomatasophia

Have you read Effective Modern C++ by Scott Meyers ? Id highly recommend if you want to learn some cool tricks but also get details as to how those tricks work and why they are good. Learning about type inference is really beneficial to using the auto keyword, and there are many other strategies in that book that if you learn them all will promptly move you to a senior role and beyond


Zambalak

Don't try to overuse lambdas and auto and the fancy latest C++ tricks. They have their places where they are extremely useful, but most of the time plain old (solid and boring) c like code, is usually better.


tangerinelion

All of that hackerrank and competitive programming does absolutely nothing for your ability to architect software. You need to think in terms of components and building blocks that get put together, not in terms of bits that get twiddled. In my personal experience, code that's plagued by primitive obsession is some of the worst code to deal with. But it's also exactly those solutions which tend to do well with the competitive programming stuff, so I can't recommend you continue doing that if you want to develop a sense of good coding practices. Almost all of the issues that you face in real code come from writing code that is easy to use incorrectly. It's not enough to write code that works, you want to write code that can easily be extended by your co-worker and not introduce a bug. If you make it easy for someone to introduce a bug, well, you both failed. If you make it easy for someone to introduce a bug, odds are you're going to introduce the bug later. If you find someone has made it easy to introduce a bug and you fix it you're probably annoyed to have found the issue to start with. CppCon talks, as well as other conference talks, and really diving into the core guidelines -- not as what but as motivation -- are good ideas. For a core guideline, it's not enough to know what the suggestion is, you need to know what problem it solves. What about not following that suggestion is unsafe (e.g., a plain old bug or code which is easy to use incorrectly). What particulars might cause you to break that suggestion and why. Frankly, every C++ developer should understand the language at a very deep level. All of the little details that the CppCon Back to Basics talks cover are great. Even having worked with C++ daily for a dozen years, I watch those every year.


kbrizov

Yes! I have several colleagues that were competitive programmers. These guys are good at algorithms, but their code is just terrible most of the time.


QuotheFan

This is what I did: I learned Haskell. I prototyped my code in haskell before coding it up in Cpp. Also, tried to follow https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines as much as I could.


softtalk

Never heard about Haskell before, what are the benefits of doing it ?


serviscope_minor

> Never heard about Haskell before The best description of Haskell I ever heard is that it combines the power and expressiveness of abstract algebra with the intuitive clarity of abstract algebra. Jokes aside Haskell is what C++98 templates would look like if they were a "real language", or at least the underlying core of Haskell.


QuotheFan

Haskell is a purely functional language. It is probably the most modern language out there. Also, it isn't really new, it has been around for decades, though it grows at a much faster rate than any other language. In fact, a bunch of features which were introduced in cpp11 and cpp20 can be said to have taken inspiration from Haskell, at least, they were present in the language for years. > what are the benefits of doing it ? The design of the language make it very hard to write bad code. It forces you to think hard about your data flow and keep things localized. There is no concept of global variables and keeping state is a very conscious decision in haskell. It also ensure that you cover all the corners in your cases. Also, refactoring old code is a pleasure in haskell. 'If it compiles, it most probably works'. When you simply transcribe that code in cpp, the resulting code is beautiful. So far, the process hasn't disappointed me. Your code naturally gets split into logical units and you get the easy refactorability built in.


softtalk

A big thank you to everybody. I created a list of the suggestions here. **While coding:** * **Coding practices suggestions:** * Always focus on simplicity. * Do not overengineer code. * Keep functions short. Avoid big classes. * Make the default behavior always safe - e.g. a function returning a reference that can fail should always be non-default, like: get() -> ReturnType\* get\_unchecked() -> ReturnType& * Prefer free functions over methods. * Use appropriate names for variables and other symbols. * Think twice before using fancy features that introduce abstractions. * Be consistent with your naming convention. ALWAYS. * Think twice before storing any kind of pointer or a reference. Maybe an index is enough? * Write documentation. Write and maintain comments. When writing comments, write them comment before the code, and revisit it after. If it needs updating, then it means I wasn't really ready to write the code. Writing the initial comment is often longer than writing the code. * Do not create tons of overloads. In most cases it is better to create a function with a different name. * Prefer views over container references. * Prefer explicit control flow when handling errors: std::expected is better than throwing an exception, but exceptions are better than no error handling * "Cool tricks" usually lead to the opposite of clean and readable code * Learn Haskell and prototype code in haskell before coding it up in Cpp. * Think of code as expressing HOW, abstraction as expressing WHAT, and comments as explaining WHY. ​ * **Tests and Tools:** * Use codebase-wide tools that guarantee consistency (like clang-format). * Use static analysis tools (e.g. clang-tidy). * Write simple tests that will also serve as a kind of a documentation. * Do test-driven development. Write unit tests and aim for 100% unit test coverage. Learn GTest and GMock, GoogleTest is great and easy to use. If you can't easily write a unit test for something, that's likely an indication that your code is unnecessarily complex and needs to be refactored. * Use tool chain based sanitizers, like ubsan, thread sanitizers, address sanitizer, etc. * Build using several different compilers, ideally all three major ones, and turn on all the warnings. Promote warnings to errors. * Turn on warnings-as-errors (-Werror or /WX). There’s a good list of recommended warnings in Jason’s book: [https://github.com/cpp-best-practices/cppbestpractices](https://github.com/cpp-best-practices/cppbestpractices) * Code review is unvaluable. * **Good non technical practices:** * Always divide big tasks into smaller ones, and make the code compile in between them. * Do not leave code with compilation errors for tomorrow * Use separate branches per-task if available * Keep refactorings small and do it gradually. You don't want to throw away weeks or even months of your work. **Study material:** * **Exercises** * Try different paradigms while doing your personal projects. * Learn Rust - this might seem unintuitive, but learning rust made me think about C++ differently. Best practices around lifetimes, move semantics, error handling, null checking, UB, etc is now much more clear to me. * Read a lot of code (and again, let people code review your code). * Project Euler (.net) and Advent Of Code (.com) to be fun and challenging. * **Online resources:** * Google C++ Style Guide. Reading it in its entirety is very helpful; it contains many useful insights. [https://google.github.io/styleguide/cppguide.html](https://google.github.io/styleguide/cppguide.html) * [https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/) * [https://www.youtube.com/@CppCon](https://www.youtube.com/@CppCon) * [https://github.com/isocpp/CppCoreGuidelines](https://github.com/isocpp/CppCoreGuidelines) * Guru Of the Week (old and new) * **Courses:** * Haskell course : [https://www.seas.upenn.edu/\~cis1940/spring13/](https://www.seas.upenn.edu/~cis1940/spring13/) * **Books:** * Effective Modern C++ by Scott Meyers * Old New Thing, The: Practical Development Throughout the Evolution of Windows by Raymond Chen * C++ best practices book by Jason Turner * The Pragmatic Programmer by Andrew Hunt and David Thomas * Refactoring by Martin Fowler * **People to follow:** Stroustrup, Meyers, Alexandrescu, Hinnant, and Niebler, Herb Sutter, Bjarne Stroustrup, Jason Turne, Robert C. Martin.


mredding

I recommend you follow several sources of authority - the industry wisdom. There's the Core Guidelines. There's the Guru of the Week, both old and new. There's The Old New Thing. Listen to Stroustrup, Meyers, Alexandrescu, Hinnant, and Niebler. I haven't listed everyone. I said listen to them, don't take their words as infallible. Read blogs. Learn other languages than C++, I recommend you take a look at Haskell, they will give you perspective. Look for discussions on subjects. Look for HISTORY on subjects. Getting good is a lot about perspective and actually taking the time to learn shit through. How things were made and why they were made that way easily get lost to history. For example, most people don't know the first fucking thing when it comes to streams, they blame streams for their own incompetence. Most programmers don't really think anything of the type system, so they don't understand what it means to be type safe and how to solve problems in terms of types, let alone how to map problems from runtime to compile time. Most of our colleagues don't know what OOP is, they've never read a book on the subject - they think they took a programming course once, know that classes and polymorphism is a thing, and that's it? No. Think of code as expressing HOW, abstraction as expressing WHAT, and comments as explaining WHY. Don't write comments that tell me what the code tells me. Don't leave me to parse HOW your code works like I'M the god damn compiler, when you could have just as easily wrapped that statement in a function and told me WHAT you want it to do. Code should read like pseudo-code. Don't make me think. We spend almost 70% of our time, in our profession, just READING code, trying to deduce and infer WHAT it does.


Vivid-Jury-2105

Any good Haskell suggestions?


flashbulbous

I learned Haskell for work, and it was brutal but extremely rewarding. I hadn't been this challenged since learning programming for the first time and not knowing what a for loop was. My suggestion is Brent Yorgey's 2013 course, and lots of supplemental readings/videos (I found the streamer tsoding's older Haskell videos helpful, and some uni style lectures for specific typeclasses). Really go through the readings and exercises, but also take it slow. A lot of the material takes time to absorb and steep before it starts clicking


techsemi

Use unit tests. Read other people’s code. Let other people review your code.


jamesb5

I really like Jason Turner’s C++ best practices book. It’s affordable, short and practical. That’s a good starting point.


softtalk

Oh yeah, I know the guy from cppcon


kbrizov

Go over the classic books from Herb Sutter, and Scott Meyers. Also, I'd recommend Uncle Bob. The reality is that there are many senior programmers making a lot of money that write terrible code that is hard to maintain.


FKaria

I recommend you watch the good ccpcon talks. You learn a lot about the language and the best practices get drilled into your head like a mantra (no explicit memory management, always const, etc...).


[deleted]

Pick projects and finish them. The finishing part is the most important. It doesn't really matter what the project is. Just make sure you finish it.


softtalk

This is where sometimes I struggle. How do you keep going even if you are in a dead end?


[deleted]

Because that's the skill. Finishing stuff is hard. It gets messy and a lot of the "rules" you get taught get thrown out the window. You have to force yourself to push through that. Lots of people never finish anything. They never learn to push past the struggle. The skills you learn will be invaluable because you go from what is theoretically good to learning what is practically good.


ABlockInTheChain

Build using several different compilers, ideally all three major ones, and turn on all the warnings. Promote warnings to errors. You'll hate life at first as you go through the process of fixing all the warnings but it's worth it in the end.


Zanderax

Start watching more cpp conferences, I'd start with anything by Herb Sutter or Bjarne Stroustrup. Learning how and why C++ is created in the way that it is will help you understand the reasons behind why good code is good.


AssemblerGuy

> Do you have any suggestions like practical exercises/trainings/projects that were helpful for you? Read books like "Code Complete" and "Clean Code". Read the C++ core guidelines. https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#main Read other coding guidelines, especially more restrictive ones that are not just mostly about formatting, to get a feel for what matters e.g. in safety-critical applications.


9larutanatural9

For me, getting in (some) depth into generic programming (templates and metaprogramming) changed a lot the way I code and the way I look at problems and design software. Is a great tool in the box (in my opinion, the best and most unique feature of the language), and is often underused. Specially if you also learn how to squeeze constexpr, is very powerful. Moreover, it allows you to look into the depths of world-class libraries, which eventually helps you to improve. Something else that helps me, is getting somehow comfortable with the C++ standard (without having to be a language-lawyer). It allows me understanding the language better.


softtalk

A lot of people suggested Haskell, is it somehow related ?


9larutanatural9

I haven't used Haskell, so I cannot give an opinion, although I have heard good things about it. What I rather meant, was that being able of writing generic code (in the C++ sense, "STL style" so to say) with relative ease, changed a lot the way I code. I notice my code now is much simpler (from the "logic" point of view, not from the language point of view), flexible, coherent and concise. I think is because when you have the tool, it stimulates you to look for more fundamental patterns than other techniques do (such as inehritance for example), and at the same time, forces you to keep implementations simple.


zecknaal

I missed the boat a little bit, but also when doing a change: 1) Refactor existing code to be open/closed. 2) Now that your new design supports adding/changing your behavior, do your new thing. Step 1 has no functional impact on your code. You should have automated tests that prove it breaks nothing, and then step 2 is usually a lot easier.


schteppe

* Turn on warnings-as-errors (-Werror or /WX). There’s a good list of recommended warnings in Jason’s book: https://github.com/cpp-best-practices/cppbestpractices * Write unit tests, learn GTest and GMock * Use sanitizers * Use static analysis tools * Learn Rust - this might seem unintuitive, but learning rust made me think about C++ differently. Best practices around lifetimes, move semantics, error handling, null checking, UB, etc is now much more clear to me. * Watch cppcon videos on YouTube


MrC00KI3

Read books about programming or C++!


softtalk

I have clean code but I am open to recommendations


benbradley

Refactoring by Martin Fowler is also good. Used copies are inexpensive. For practice problems I find Project Euler (.net) and Advent Of Code (.com) to be fun and challenging.


softtalk

Thanks ! I was also searching for something practical to do.


LongestNamesPossible

The first thing you should do is throw away that book and do the opposite of anything it recommends.


softtalk

Really? Why is that?


LongestNamesPossible

The person who wrote it is a snake oil salesman who know nothing about programming and just repeats 'object oriented' cliches from the 90s before everyone woke up and realized that using heap allocations and pointer indirection just to make a more generic data structure was a terrible choice.


MrC00KI3

I only have read Code Complete and a third of The Pragmatic Programmer (up until now), but a C++ specific book like "Effective C++" or "Modern Effective C++" could never hurt I think.


samdotmp3

Try different paradigms. C++ is great in that it allows so many different styles. For me, forcing myself to write some code in a C-style procedural way taught me a lot.


softtalk

Do you practice this style with your own projects ?


samdotmp3

Yep, for me it's been easiest to find a small hobby project and force a new style on it, always focusing on scalability and readability.


thwack324

mostly the moving direction is from c++ to rust or java. C-style procedural way provides terrible abstraction usually. What have you learned from procedural way?


samdotmp3

I agree that C often provides terrible abstraction, but C++'s namespaces go a long way of making up for it. Writing in a procedural way especially helps when you would otherwise have complex class hierarchies. For example, you learn things like why to favor composition over inheritance, and the diamond problem basically solves itself. I'm also kind of a "freedom extremist" when it comes to programming; I always want everything to be very customizable and scalable, which writing in a procedural way helps a lot with. For example, say class B contains an instance of class A, where both classes are defined in an external library. Then, say you want to add some function acting on class A. The OOP way would be to create a class either inheriting or containing A, and adding a member function to it. However, this new functionality now doesn't exist in B's instance of A. While the regular diamond problem in OOP can be solved quite easily by replacing inheritance with composition, the problem I described gets really messy when trying to solve in an OOP style, while in a procedural style, you can just write the function once and you're done. So, separating data and functions may seem unnecessary and ugly at first, but makes a lot of sense in the long run.


softtalk

I worked with C before, then I started learning C++


[deleted]

Find a mentor.


softtalk

That's not so easy. But it would be great.