Live data from Hacker News

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

gaultier.github.io

141–150 of 356 posts

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

#141

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…

Great advice. Almost all of it applies to any programming language.

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

#142
> So what do I recommend? Well, the good old git submodules and compiling from source approach.=

It is strange that the author complains so much about automating BOMs, package versioning, dependency sources, etc, and then proceeds to suggest git submodules as superior to package managers.

The author needs to try vcpkg before making these criticisms; almost all of these are straightforwardly satisfied with vcpkg, barring a few sharp edges (updating dependencies is a little harder than with git submodules, but that's IMO a feature and not a bug—dependencies are built in individual sandboxes which are then installed to a specified directory. vcpkg can set internal repositories as the registry instead of the official one, thus maintaining the 'vendored in' aspect. vcpkg can chainload toolchains to compile everything with a fixed set of flags, and allows users to specify per-port customisations.

These are useful abstractions and it's why package managers are so popular, rather than having everyone deal with veritable bedsheets' worth of strings containing compile flags, macros, warnings, etc.

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

#143
post #31

I'd swap 2 and 3. Getting CI, linting, auto-formatting, etc. going is a higher priority than tearing things out. Why? Because you don't know what to tear out yet or even the consequence of tearing them out. Linting (and other static analysis tools) also give you a lot of insight into where the program needs work. Things that get flagged by a static analysis tool (today) will often be areas where you can tear out enti…

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

This is another reason why you should track important information in comments alongside the code instead of trusting VCS to preserve it in logs/commit messages, and to reject weird code missing comments from being merged.

Not saying that fixes decades of cruft because you shouldn't change files without good reason and non-white space formatting is not a good reason, but I'm mentioning it because I've seen people naively belief bullshit like "code is self explanatory" and "the reason is in the commit message"

Just comment your code folks, this becomes less of a problem

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

#144

> What do you do now? Look for another job > You’d be amazed at how many C++ codebase in the wild that are a core part of a successful product earning millions and they basically do not compile. Wow I really hope this is hyperbole. I feel like I was lucky to work on a codebase that had CI to test on multiple computers with WError

> Wow I really hope this is hyperbole.

I am sure its not, I dont have much experience as I have worked in only 3 companies in the last 25 years, but so far I have found no relation between code quality and company earnings.

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

#145

Earlier quoted context omitted.

I'm not hardcore on auto-formatters, but I think their impact on code history is negligible in the case of every legacy system I've worked on. The code history just isn't there. These aren't projects that used git until recently (if at all). Before that they used something else, but when they transitioned they didn't preserve the history. And that's if they used any version control system. I've tried to help teams wh…

>I think their impact on code history is negligible in the case of every legacy system I've worked on. The code history just isn't there. Not sure if I agree here or not - whilst yes, the history isn't there, if it's a small enough team you'll have a good guess at who wrote it. Definitely found I've learnt the style of colleages so know who to ask just from the code outline.

Legacy systems that you inherit don't have people coming with them very often. That's part of the context of this. You often don't have people to trace it back to or at least not the people who actually wrote it (maybe someone who worked with them before they got laid off a decade ago), and reformatting the code is not going to make it any harder to get answers from people who aren't there.

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

#146
post #29

Is it worth getting more into C++ in 2024? Lots of interesting jobs in finance require it but it seems almost impossible to get hired without prior experience (with C++ and in finance).

Depends on the industry you are interested in entering.

My myopic view of the world has seen the general trend from C to C++ for realtime embedded applications. For example: in the Automotive Industry all the interesting automotive features are written in C++.

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

#147
post #30

It's funny. My first step would be 0. You reach out to the previous maintainers, visit them, buy them tea/beer and chat (eventually) about the codebase. Learned Wizards will teach you much. But I didn't see that anywhere. I think the rest of the suggestions (like get it running across platform, get tests passing) are useful stress tests likely to lead you to robustness and understanding however. But I'd def be going…

I wouldn't make it the first step. If you do, you will probably waste their time more than anything. Try to work on it a little bit first, and once you get stuck in various places, now you can talk to the previous maintainers, it will be much more productive. They will also appreciate the effort.

There’s a fine balance with no right or wrong answer. Previous maintainers will appreciate if you spent literally more than a second trying to understand before you reach out to them, but for your own sanity you should know when it’s time to stop and call for help.

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

#148
Not mentioned were code comprehension tools / techniques:

I used to use a tool called Source Navigator (written in Tcl/tk!) that was great at indexing code bases. You could then check the Call Hierarchy of the current method, for example, then use that to make UML Sequence Diagrams. A similar one called Source Insight shown below [1].

And oh, notes. Writing as if you're teaching someone is key.

Over the years, I got quite good at comprehending code, even code written by an entire team over years. For a brief period, I was the only person actively supporting and developing an algorithmic trading code base in Java that traded ~$200m per day on 4 or 5 exchanges. I had 35 MB of documentation on that, lol. Loved the responsibility (ignoring the key man risk :|). Honestly, there's a lot of overengineering and redundancy in most large code bases.

[1] References in "Source Insight" https://d4.alternativeto.net/6S4rr6_0rutCUWnpHNhVq7HMs8GTBs6...

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

#149
post #77

I’m not sure why there’s so much focus on refactoring or improving it. When a feature needs to be added that can just be tacked onto the code, do it without touching anything else. If it’s a big enough change, export whatever you need out of the legacy code (by calling an external function/introducing a network layer/pulling the exact same code out into a library/other assorted ways of separating code) and do the res…

>"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.

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

#150

My first thing is usually: #0: Replace the custom/proprietary Hashmap implementation with the STL version. Once upon a time, C++ academics brow beat the lot of us into accepting Red-Black-Tree as the only Map implementation, arguing (in good faith yet from ignorance) that the "Big O" (an orgasm joke, besides others) worst case scenario (Oops, pregnancy) categorized Hash Map as O(n) on insert, etc. due to naieve imple…

In the mid 1990s when C++ was getting std::map and the other containers CPU caches were not a big deal. Average case was the correct thing to optimize for. These days CPU caches are a big deal and so your average case is typically dominated by CPU cache miss pipeline stalls. This means for most work you need different data structures. The world is still catching up to what this means.

Well, Red-Black algos are supposed to be better at cache-locality, but I have an AVL-tree impl (ugg jokes, again: AVUL (ALV) is the "evil" tree of "forbidden" {carnal?} wisdom from The Garden of Eden, associated with Yggdrasil/Odin [a "pagan" God of Balance & Pleasure]) that has improved cache locality since its data nodes can be made to contain AvlTreeNode structure(s), and avoid copying any data, as users are made to provide node alloc/free function pointers to this C lib's Tree "constructor". This means, for real example, I have a command line option interpreter with const structures for each option, each node added to two AVL trees (to find by unicode codepoint and find by length prefixed unicode string name). C++ STL Map implementations can not conditionally generate code for const types and thus do needless coppies, whereas my C collections API causes 0 calls to malloc (vs STL's 2 mallocs per node insert). NodeAlloc is just pointer math to get at the apt AvlNode, NodeFree is NoOp.

Benchmarking the STL vs my AVL approach results in millions of times quicker cmd line opt interpretaion (for my gnu getopt replacement lib) due to reduction of pointer chasing...

And if I want to do something similar in C++ (overloading operator new), I have to instantiate multiple copies of the Tree code, one per each "class". What if I want to use my Sortable class with various allocators: OBJ cache, dynamic GC'd, static (no alloc, its in the .data section already)...? Well then I get N copies of EXACT SAME template code for no real reason, only differing in delete and new [con|de]structors. The cache-misses galore this causes isn't even fair to bench against the C w/ fn() ptr approach.

Post reply on HN