Live data from Hacker News

You've just inherited a legacy C++ codebase, now what?

gaultier.github.io

331–340 of 356 posts

Re: You've just inherited a legacy C++ codebase, now what?

#331

Some good advice here, and some more...controversial advice here. After inheriting quite a few giant C++ projects over the years, there are a few obvious big wins to start with: * Reproducible builds. The sanity you save will be your own. Pro-tip: wrap your build environment with docker (or your favorite packager) so that your tooling and dependencies become both explicit and reproducable. The sanity you save will be…

Step 0: CI on every commit to build & run all tests / enforce that you never regress once you've finished a step.

Re: You've just inherited a legacy C++ codebase, now what?

#332

Earlier quoted context omitted.

Step 0: reproducible builds (like you said) Step 1: run all tests, mark all the flaky ones. Step 2: run all tests under sanitizers, mark all the ones that fail. Step 3: fix all the sanitizer failures. Step 4: (the other stuff you wrote)

Step 0 sounds so easy. Until you realize __time__ exists. Then you take that away, and you find out that some compiler heuristics might not be deterministic. Then you discover -frandom-seed - and go ballistic when you read "but it should be a different seed for each sourcefile" Then you figure out your linker likes emitting a timestamp in object files. Then you discover /Brepro (if you're lucky enough to use lld-link…

frandom-seed is not quite so bad.

> The string can either be a number (decimal, octal or hex) or an arbitrary string (in which case it’s converted to a number by computing CRC32). > The string should be different for every file you compile.

So basically just pass in the project relative path to the file into random-seed and you'll be fine. It's a shame the guidance doesn't explain why the string should be different because that feels like it could be advice that's not rooted in any technical reality.

__time__ isn't actually that bad as it's an anti-pattern and much better for the build system to inject the build time explicitly as an input macro (if your software needs it for UX purposes).

__FILE__ is the more annoying one but can be solved through fmacro-prefix-map.

Re: You've just inherited a legacy C++ codebase, now what?

#333
post #309

Earlier quoted context omitted.

Just a note on legacy tests: Step 0.5: understand the tests. They need to be examined to see if they've rotted or not. Tests passing/failing doesn't really mean code under test works or not. The tests might have been abandoned under previous management and don't accurately reflect how the code is _supposed_ to be working.

The same applies to comments. I have absolutely inherited codebases where one of the early steps was to make a commit excising every single comment in the code, because so many of them were old, lies, or old lies, that it wasn't worth the risk of a junior developer accidentally thinking they could be relied upon. (and of course they remained available in history to be potentially buffed up and resurrected, but still,…

That's brilliant, but also... sounds like hell? Wouldn't that easily add several months to the timeline?

Re: You've just inherited a legacy C++ codebase, now what?

#335
post #237

Earlier quoted context omitted.

> The last step of an inherited C++ codebase is to rewrite it in a memory safe language Simply getting rid of any actually memory unsafe C++ and enforcing guidelines will do this for you in the C++ codebase. "Rewrite it in X" only adds complexity because it's the flavour of the month as you said in your comment. Author is already doing the work of rewriting large chunks of the codebase in C++, they may as well follow…

How would you get rid of any memory unsafe C++? Isn’t that just another way of saying “do not make mistakes”?

The same way you do it in rust, use wrappers for all memory allocation.

C++ has had RAII forever, since C++11(2024 btw now) have actually good wrappers, Box = std::unique_ptr, whatever the ref counter version is = std::shared_pte.

Do the other things he already said to do, ie clang-tidy with the correct rule will warn/error on any raw pointer usage. You don't need to "not make mistakes". If you never use raw pointers, other than these specific places you tell the linter that it was fine and you have checked then by default it will be memory safe. Does that sound familiar?

"But we don't need a linter in Rust!" It's just built into the LLVM frontend called the rust compiler. If it bugs you so much build a custom executable that runs the linter then the c++ compiler and call it your own internal compiler. First line of code can be "#!/bin/sh"...

If you say you aren't talking about Rust but one of the GC languages, then I agree with you, write it in that other language but then the correct solution is to rewrite the software in the first place since it was never written in the correct language to start with. Rewriting something in Rust is likely the same amount of complexity as fixing the C++ code, if you however first need to learn Rust well there's a reason I am not exactly pro rust ans yes I bave tried to use it in a proper complex project, all deadlines were missed and we ended up writing it in modern safe C++ instead purely because the language didn't force us to make up some obscure abstraction to appease the borrow checker.

Re: You've just inherited a legacy C++ codebase, now what?

#336
post #170
post #31

Earlier quoted context omitted.

On the flip side, auto-formatting will trash your version history and impede analysis of "when and why was this line added".

How does reformatting trash the history? It's one extra commit.. I guess if it splits or combines lines that could cause some noise if you really want the history of a single line... But that happens all the time, and I don't see how it would really prevent understanding the history. You can always do a blame on a range of lines. Maybe I'm missing something though, genuinely curious for a concrete example where refor…

If you ask the IDE to show blame info next to each line, then a lot of lines will be from the big reformatting. If course you can dig in and retrieve the history still, but it's an extras step then. Btw, it seems that at least Git has a way to make `git blame` avoid considering certain commits (.Git attributes). Maybe that works in IDEs too!

Re: You've just inherited a legacy C++ codebase, now what?

#337
post #149

Earlier quoted context omitted.

>"When a feature needs to be added that can just be tacked onto the code, do it without touching anything else." In few lucky cases. In real life new feature is most likely change in behavior of already existing one and suddenly you have to do some heavy refactoring in numerous places.

if you're going to own it for the foreseeable future. then own it. learn it, refactor it, test the hell of out of it. otherwise you're never going to be able to debug or extend it. one thing I always do is throwaway major refactors. its the fastest way for me to learn what the structure is, what depends on what, and what's really kinky. and I might just learn enough to do it for real should it become necessary.

> throwaway major refactors

Thank you for providing me a term for this! I indeed learned a lot from doing this because some things can only be understood by hitting them with a hammer, putting them together again and observing where that doesn't work.

Re: You've just inherited a legacy C++ codebase, now what?

#338
post #337

Earlier quoted context omitted.

if you're going to own it for the foreseeable future. then own it. learn it, refactor it, test the hell of out of it. otherwise you're never going to be able to debug or extend it. one thing I always do is throwaway major refactors. its the fastest way for me to learn what the structure is, what depends on what, and what's really kinky. and I might just learn enough to do it for real should it become necessary.

> throwaway major refactors Thank you for providing me a term for this! I indeed learned a lot from doing this because some things can only be understood by hitting them with a hammer, putting them together again and observing where that doesn't work.

absolutely. the best is when you spend all this time trying to figure out what this awful and convoluted thing is. and you finally just take it out to see what happens, and the answer is .. nothing

its software. we should take full of advantage of its plasticity.

Re: You've just inherited a legacy C++ codebase, now what?

#339
1) Make sure you're getting paid either exorbitantly well, or at least hourly

2) Ask how long it would take to write from scratch? Only ask if the answer to #1 is "salaried well" btw.

Dumping an unsupported codebase on a new employee is a major dick move, and it requires hazard pay. They are doing that because they are desperate.

Post reply on HN