TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

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

380 点作者 broken_broken_大约 1 年前

73 条评论

eschneider大约 1 年前
Some good advice here, and some more...controversial advice here.<p>After inheriting quite a few giant C++ projects over the years, there are a few obvious big wins to start with:<p>* 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 your own.<p>* Get the code to build clean with -Wall. This is for a couple of reasons. a) You&#x27;ll turn up some amount of bad code&#x2F;undefined behavior&#x2F;bugs this way. Fix them and make the warning go away. It&#x27;s ok to #pragma away some warnings once you&#x27;ve determined you understand what&#x27;s happening and it&#x27;s &quot;ok&quot; in your situation. But that should be rare. b) Once the build is clean, you&#x27;ll get obvious warnings when YOU do something sketchy and you can fix that shit immediately. Again, the sanity you save will be your own.<p>* Do some early testing with something like valgrind and investigate any read&#x2F;write errors it turns up. This is an easy win from a bugfix&#x2F;stability point of view.<p>* At least initially, keep refactorings localized. If you work on a section and learn what it&#x27;s doing, it&#x27;s fine to clean it up and make it better, but rearchitecting the world before you have a good grasp on what&#x27;s going on globally is just asking for pain and agony.
评论 #39560212 未加载
评论 #39555280 未加载
评论 #39558147 未加载
评论 #39555623 未加载
评论 #39556142 未加载
评论 #39565982 未加载
评论 #39555063 未加载
Jtsummers大约 1 年前
I&#x27;d swap 2 and 3. Getting CI, linting, auto-formatting, etc. going is a higher priority than tearing things out. Why? Because you don&#x27;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.<p>Things that get flagged by a static analysis tool (today) will often be areas where you can tear out entire functions and maybe even classes and files because they&#x27;ll be a re-creation of STL concepts. Like homegrown iterator libraries (with subtle problems) that can be replaced with the STL algorithms library, or homegrown smart pointers that can just be replaced with actual smart pointers, or replacing the C string functions with C++&#x27;s on string class (and related classes) and functions&#x2F;methods.<p>But you won&#x27;t see that as easily until you start scanning the code. And you won&#x27;t be able to evaluate the consequences until you push towards more rapid test builds (at least) if not deployment.
评论 #39555138 未加载
评论 #39551880 未加载
评论 #39555605 未加载
评论 #39552015 未加载
评论 #39551963 未加载
评论 #39551710 未加载
vijucat大约 1 年前
Not mentioned were code comprehension tools &#x2F; techniques:<p>I used to use a tool called Source Navigator (written in Tcl&#x2F;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].<p>And oh, notes. Writing as if you&#x27;re teaching someone is key.<p>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&#x27;s a lot of overengineering and redundancy in most large code bases.<p>[1] References in &quot;Source Insight&quot; <a href="https:&#x2F;&#x2F;d4.alternativeto.net&#x2F;6S4rr6_0rutCUWnpHNhVq7HMs8GTBs6osGo8uUyXjqk&#x2F;rs:fit:2400:2400:0&#x2F;g:ce:0:0&#x2F;YWJzOi8vZGlzdC9zL3NvdXJjZS1pbnNpZ2h0XzM5MTk4MV9mdWxsLnBuZw.jpg" rel="nofollow">https:&#x2F;&#x2F;d4.alternativeto.net&#x2F;6S4rr6_0rutCUWnpHNhVq7HMs8GTBs6...</a>
评论 #39561344 未加载
Night_Thastus大约 1 年前
&gt;worry not, by adding std::cmake to the standard library and you’ll see how it’s absolutely a game changer<p>I&#x27;m pretty sure my stomach did somersaults on that.<p>But as for the advice:<p>&gt;Get out the chainsaw and rip out everything that’s not absolutely required to provide the features your company&#x2F;open source project is advertising and selling<p>I hear you, but this is <i>incredibly</i> dangerous. Might as well take that chainsaw to yourself if you want to try this.<p>It&#x27;s dangerous for multiple reasons. Mainly it&#x27;s a case of Chesterton&#x27;s fence. Unless you fully understand why X was in the software and fully understand how the current version of the software is used, you <i>cannot</i> remove it. A worst case scenario would be that maybe a month or so later you make a release and the users find out an important feature is subtly broken. You&#x27;ll spend days trying to track down exactly how it broke.<p>&gt;Make the project enter the 21st century by adding CI, linters, fuzzing, auto-formatting, etc<p>It&#x27;s a nice idea, but it&#x27;s hard to do. One person is using VIM, another is using emacs, another is using QTCreator, another primarily edits in VSCode.. Trying to get everyone on the same page about all this is very, very hard.<p>If it&#x27;s an optional step that requires that they install something new (like commit hook) it&#x27;s just not going to happen.<p>Linters also won&#x27;t do you any good when you open the project and 2000+ warnings appear.
评论 #39552045 未加载
评论 #39551921 未加载
评论 #39555208 未加载
评论 #39555620 未加载
评论 #39551820 未加载
评论 #39556828 未加载
评论 #39558550 未加载
keepamovin大约 1 年前
It&#x27;s funny. My first step would be<p><pre><code> 0. You reach out to the previous maintainers, visit them, buy them tea&#x2F;beer and chat (eventually) about the codebase. Learned Wizards will teach you much. </code></pre> But I didn&#x27;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.<p>But I&#x27;d def be going for that sweeet, sweet low-hangin&#x27; fruit of just talking to the ol&#x27; folks who came that way before. Haha :)
评论 #39551861 未加载
评论 #39552676 未加载
评论 #39559431 未加载
评论 #39561216 未加载
评论 #39551421 未加载
评论 #39560260 未加载
评论 #39551235 未加载
评论 #39560387 未加载
mk_chan大约 1 年前
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.<p>If it’s a big enough change, export whatever you need out of the legacy code (by calling an external function&#x2F;introducing a network layer&#x2F;pulling the exact same code out into a library&#x2F;other assorted ways of separating code) and do the rest in a fresh environment.<p>I wouldn’t try to do any major refactor unless several people are going to work on the code in the future and the code needs to have certain assumptions and standards so it is easy for the group to work together on it.
评论 #39554725 未加载
评论 #39555402 未加载
评论 #39556319 未加载
summerlight大约 1 年前
This thread has lots of good advice. I&#x27;ll add some of mine, not limited to C&#x2F;C++. If you have luxury of using VCS, make a full use of its value. Many teams only use it as a tool merely for collaboration. VCS can be more than that. Pull the history then build a simple database. It doesn&#x27;t have to be an RDB (it&#x27;s helpful though); a simple JSON file or even a spreadsheet file is a good starter. There are so many valuable information to be fetched with just a simple data driven approach, almost immediately.<p><pre><code> * You can find out the most relevant files&#x2F;functions for your upcoming works. If some functions&#x2F;files have been frequently changed, then it&#x27;s going to be the hot spot for your works. Focus on them to improve your quality of life. If you want to introduce unit tests? Then focus on the hot spot. Suffer from lots of merge conflicts? The same. * You can also figure out correlation among the project and its source files. Some seemingly distant files are frequently changed together? Those might suggest an implicit structure that not might be clear from the code itself. This kind of information from external contexts can be useful to understand the bird&#x27;s eye view. * Real ownership models of each module can be inferred from the history. Having a clear ownership model helps, especially if you want to introduce some form of code review. If some code&#x2F;data&#x2F;module seems to have unclear ownership? That might be a signal for refactoring needs. * Specific to C&#x2F;C++ contexts, build time improvements could be focused on important modules, in a data driven way. Incremental build time matters a lot. Break down frequently changed modules rather than blindly removing dependencies on random files. You can even combine this with header dependency to score the module with the real build time impact. </code></pre> There could be so many other things if you can integrate other development tools with VCS. In the era of LLM, I guess we can even try to feed the project history and metadata to the model and ask for some interesting insights, though I haven&#x27;t tried this. It might need some dedicated model engineering if we want to do this without a huge context window but my guts tell that this should be something worth try.
评论 #39558207 未加载
bArray大约 1 年前
&gt; 3. Make the project enter the 21st century by adding CI, linters, fuzzing, auto-formatting, etc<p>I would break this down:<p>a) CI - Ensure not just you can build this, but it can be built elsewhere too. This should prevent compile-based regressions.<p>b) Compiler warnings and static analysers - They are likely both smarter than you. When it says &quot;warning, you&#x27;re doing weird things with a pointer and it scares me&quot;, it&#x27;s a good indication you should go check it out.<p>c) Unit testing - Set up a series of tests for important parts of the code to ensure it performs precisely the task you expect it to, all the way down to the low level. There&#x27;s a really good chance it doesn&#x27;t, and you need to understand why. Fixing something could cause something else to blow up as it was written around this bugged code. You also end up with a series of regression tests for the most important code.<p>n) Auto-formatting - Not a priority. You should adopt the same style as the original maintainer.<p>&gt; 5. If you can, contemplate rewrite some parts in a memory safe language<p>The last step of an inherited C++ codebase is to rewrite it in a memory safe language? A few reasons why this probably won&#x27;t work:<p>1. Getting resources to do additional work on something that isn&#x27;t broken can be difficult.<p>2. Rather than just needing knowledge in C++, you now also need knowledge in an additional language too.<p>3. Your testing potentially becomes more complex.<p>4. Your project likely won&#x27;t lend itself to being written in multiple languages, due to memory&#x2F;performance constraints. It must be a significantly hard problem that you didn&#x27;t just write it yourself.<p>5. You have chosen to inherit a legacy codebase rather than write something from scratch. It&#x27;s an admittance that you don&#x27;t have some resource (time&#x2F;money&#x2F;knowledge&#x2F;etc) to do so.
评论 #39559755 未加载
delta_p_delta_x大约 1 年前
&gt; So what do I recommend? Well, the good old git submodules and compiling from source approach.=<p>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.<p>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&#x27;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 &#x27;vendored in&#x27; aspect. vcpkg can chainload toolchains to compile everything with a fixed set of flags, and allows users to specify per-port customisations.<p>These are useful abstractions and it&#x27;s why package managers are so popular, rather than having everyone deal with veritable bedsheets&#x27; worth of strings containing compile flags, macros, warnings, etc.
tehnub大约 1 年前
I enjoyed the article and learned something. But I&#x27;ve been wondering: When people say &quot;rewrite in a memory-safe language&quot;, what languages are they suggesting? Is this author rewriting parts in Go, Java, C#? Or is it just a smirky, plausibly deniable way of saying to rewrite it in Rust?
评论 #39552917 未加载
评论 #39554882 未加载
评论 #39557743 未加载
Kon-Peki大约 1 年前
The article doesn&#x27;t mention anything about global variables, but reducing&#x2F;eliminating them would be a high priority for me.<p>The approach I&#x27;ve taken is, when you do work on a function and find that it uses a global variable, try to add the GV as a function parameter (and update the calling sites). Even if it&#x27;s just a pointer to the global variable, you now have another function that is more easily testable. Eventually you can get to the point where the GV can be trivially changed to a local variable somewhere appropriate.
bluetomcat大约 1 年前
Been there, done that. Don&#x27;t be a code beauty queen. Make it compile and make it run on your machine. Study the basic control-flow graph starting from the entry point and see the relations between source files. Debug it with step-into and see how deep you go. Only then can you gradually start seeing the big picture and any potential improvements.
评论 #39555496 未加载
评论 #39551944 未加载
VyseofArcadia大约 1 年前
&gt; Get out the chainsaw and rip out everything that’s not absolutely required to provide the features your company&#x2F;open source project is advertising and selling<p>Except every legacy C++ codebase I&#x27;ve worked on is decades old. Just enumerating the different &quot;features&quot; is a fool&#x27;s errand. Because of reshuffling and process changes, even marketing doesn&#x27;t have a complete list of our &quot;features&quot;. And even it there was a complete list of features, we have too many customers that rely on spacebar heating[0] to just remove code that we think doesn&#x27;t map to a feature.<p>That&#x27;s <i>if</i> we can even tease apart which bits of code map to a feature. It&#x27;s not like we only added brand new code for each feature. We also relied on and modified existing code. The only code that&#x27;s &quot;safe&quot; to remove is dead code, and sometimes that&#x27;s not as dead as you might think.<p>Even <i>if</i> we had a list of features and even <i>if</i> code mapped cleanly to features, the idea of removing all code not related to &quot;features your company is advertising or selling&quot; is absurd. Sometimes a feature is so widely used that you don&#x27;t advertise it anymore. It&#x27;s just there. Should Microsoft remove boldface text from Word because they&#x27;re not actively advertising it?<p>The only way this makes sense is if the author and I have wildly different ideas about what &quot;legacy&quot; means.<p>[0] <a href="https:&#x2F;&#x2F;xkcd.com&#x2F;1172&#x2F;" rel="nofollow">https:&#x2F;&#x2F;xkcd.com&#x2F;1172&#x2F;</a>
评论 #39560087 未加载
评论 #39557338 未加载
ecshafer大约 1 年前
This is pretty great advice for any legacy code project. Even outside of C++ there is a huge amount of code bases out there that do not compile&#x2F;run on a dev machine without tons of work. I once worked on a Java project that due to some weird dependencies, the dev mode was to run a junit test which started spring and went into an infinite loop. Getting a standard run to work helped a ton.
评论 #39555813 未加载
grandinj大约 1 年前
This is generally the same path that LibreOffice followed. Works reasonably well.<p>We built our own find-dead-code tool, because the extant ones were imprecise, and boy oh boy did they find lots of dead stuff. And more dead stuff. And more dead stuff. Like peeling an onion, it went on for quite a while. But totally worth it in the end, made various improvements much easier.
pvarangot大约 1 年前
Besides what everyone else told you make sure you are making at least 250k&#x2F;y
ilitirit大约 1 年前
I&#x27;ve had to do this several times in the past. Honestly, my best advice would probably be make several backups, then to do as little as possible. If you need to make a small change, fine. Bigger changes? Consider if you can&#x27;t do the bulk of the work in a technology or stack <i>you understand</i> and only make a small change to the legacy code base.<p>Most of the time I spend with C++ code revolves around figuring out compile&#x2F;link errors. Heaven forbid you need to deal with non-portable `make` files that for some reason work on the old box, but not yours... Oh, and I hope you have a ton of spare space because of some reason building a 500k exe takes 4GB.<p>Keep in mind, this advice only applies to <i>inherited</i> C++ code bases. If you&#x27;ve written your own or are working on an actively maintained project these are non-issues. Sort-of.
sjc02060大约 1 年前
A good read. We recently did &quot;Rewrite in a memory safe language?&quot; successfully. It was something that shouldn&#x27;t have been written in C++ in the first place (it was never performance sensitive).
评论 #39554611 未加载
评论 #39557378 未加载
评论 #39552013 未加载
hgs3大约 1 年前
Rewriting is questionable. Joel Spolsky has a famous blog post about this from two decades ago that&#x27;s still relevant today [1].<p>[1] <a href="https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2000&#x2F;04&#x2F;06&#x2F;things-you-should-never-do-part-i&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2000&#x2F;04&#x2F;06&#x2F;things-you-should-...</a>
sk11001大约 1 年前
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).
评论 #39551916 未加载
评论 #39556274 未加载
jcarrano大约 1 年前
Good points, but this is not something you can solve with a recipe. Investigate, talk to people and make sure you are solving actual problems and prioritizing the right tasks.<p>This is an extremely crucial step that you must do first: familiarize yourself with the system, its uses and the reasons it works like it does. Most things will be there for a reason, even if not written to the highest standard. Other parts might at first sight seem very problematic yet be only minor issues.<p>Be careful with number 4 and 5. Do not rush to fix or rewrite things just because they look like they can be improved. If it is not causing issues and it is not central to the system, better spend your resources somewhere else.<p>Get the team to adopt good practices, both in the actual code and in the process. Observe the team and how they work and address the worst issues first, but do not overwhelm them. They may not even be aware of their inefficiencies (e.g. they might consider complete rebuilds as something normal to do).
评论 #39555768 未加载
happyweasel大约 1 年前
If you have a codebase with lots and lots of tests, you are not in a bad place. Remember legacy means a codebase that works and solved and still solves problems over decades. In a sense,a successfull software project implies it will be marked as legacy. Always prefer legacy over Hype.
评论 #39565535 未加载
bobnamob大约 1 年前
This article (and admittedly most comments here) doesn&#x27;t emphasize the value of a comprehensive e2e test suite enough.<p>So much talk about change and large LoC deltas without capturing the expected behavior of the system first
rurban大约 1 年前
I just went this very same dance with an old project, smart, which evaluates string matching algorithms. Faster strstr(). From 2013. It was in a better shape than zlib, but still.<p>Their shell build script was called makefile, kid me not. So first create a proper dependency management: GNUmakefile. A BSD makefile would have been prettier, but not many are used to this. dos2unix, chmod -x `find . -name *.c -o name *\.h`, clang-format -i All in seperate commits.<p>Turns out there was a .h file not a header, but some custom list of algorithm states, broken by fmt. Dontg do that. Either keep it a header file, or rename it to .lst or such.<p>Fix all the warnings, hundreds. Check with sanitizers. Check the tests, disable broken algorithms, and mark them as such.<p>Improve the codebase. There are lots of hints of thought about features. write them. Simplify the state handling. Improve the tests.<p>Add make check lint. Check all the linter warnings.<p>Add a CI. Starting with Linux, Windows mingw, macos and aarch64. Turns out the code is Linux x64 only, ha. Make it compat with sse checks, windows quirks.<p>Waiting for GH actions suck, write Dockerfiles and qemu drivers into your makefile. Maybe automake would have been a better idea after all. Or even proper autoconf.<p>Find the missing algorithms described elsewhere. Add them. Check their limitations.<p>Reproducible builds? Not for this one, sorry. This is luxury. Rather check clang-tidy, and add fuzzing.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;rurban&#x2F;smart">https:&#x2F;&#x2F;github.com&#x2F;rurban&#x2F;smart</a>
rayiner大约 1 年前
This is excellent advice, especially the list of what not to do. I don’t think it’s just C++, it’s just C++, it’s working with any legacy code base. You gotta approach it on its own terms, and analyze and fully understand what’s happening before you start changing things.<p>I observed from afar when the Gwydion Dylan folks (the Dylan successor to the CMU CL compiler) inherited Harlequin’s Dylan compiler and IDE and decided to switch to that going forward: <a href="https:&#x2F;&#x2F;opendylan.org" rel="nofollow">https:&#x2F;&#x2F;opendylan.org</a>. The work (done out in the open in public mailing lists and IRC) is a very nicely done case study in taking a large existing code base developed by someone else, studying it, and refactoring it to bring it incrementally into the present. They started with retooling the build system and documenting the internals. Then over time they addressed major pain points, like creating an LLVM backend to avoid the need to maintain custom code generators.
t43562大约 1 年前
I think the very best thing one can do is reduce the amount of variation you have to support. The burden of change is thus vastly reduced and the number of possible avenues for improvement explodes.<p>We could have left customers with old operating systems on the older versions of the product. A lot of them never upgraded anyhow. We absolutely destroyed our productivity by not making this kind of decision. We also really hurt ourselves by supporting Windows - as soon as there are 2 or more completely different compilers things turn to **t. I&#x27;m not even sure we made much money from it.<p>Given the ability to use new tools (clang, gcc and others) that are only available on newer operating systems we could have done amazing things. All those address sanitizers etc would have been wonderful and I would like to have done some automated refactoring which I know clang has tools for.<p>Most of the problems were just with understanding the minds of the developers - they were doing something difficult and at a level of complexity that somewhat overmatched the problem most of the time but the complexity was there to handle the edge cases. I wanted to go around adding comments to the files and classes as I understood bits of it. I was working with one of the original developers who was of course not at all interested in anyone understanding it or making it clearer and this kind of effort tended to get shot down.<p>If you don&#x27;t have good tests you&#x27;re dead in the water. I have twice inherited python projects without tests at all and those were a complete nightmare until I added some. One was a long running build process in which unit tests were only partially helpful. Until I came up with a fake android source tree that could build in under a minute I was extremely handicapped. Once I had that everything started to get much better.<p>My favorite game ... is an open source C++ thing called warzone2100 - no tests. It&#x27;s not easy to make changes with confidence. I imagine to myself that one day my contribution will be to add some. The problem is that I cannot imagine the current developers taking all that kindly to it. Some people get to competence in a codebase and leave it at that.
myrmidon大约 1 年前
Really liked it! Especially the &quot;get buy in&quot; is really good advice-- always stressing how the effort spent on refactoring actually improves things, and WHY its necessary.<p>Something that&#x27;s kinda implied that I would really stress: Establish a &quot;single source of truth&quot; for any release&#x2F;binary that reaches production&#x2F;customers, before even touching ANY code (Ideally CI. And ideally builds are reproducible).<p>If you build from different machines&#x2F;environments&#x2F;toolchains, its only a matter of time before that in itself breaks something, and those kinds of problems can be really &quot;interesting&quot; to find (an obscure race condition that only occurs when using a newer compiler, etc.)
sega_sai大约 1 年前
To be honest a lot of recommendations apply to other languages as well. I.e. start with tests only then change, add autoformatting etc. At least I had experience of applying a similar sequence of steps to a python package.
cljacoby大约 1 年前
Despite being framed as something for legacy C&#x2F;C++ codebases, this is pretty good advice for setting up testing and CI automation around any project.<p>I recently started on a new Rust project, and despite not having to worry about things like sanitizers as much, I followed a similar approach of getting it to compile locally, getting it compile in a docker container, setup automated CI&#x2F;CD against all PRs.<p>Although I would order the steps as 1, 3, 4, 2. Don&#x27;t get out the chainsaw until you have CI&#x2F;CD tests evaluating your code changes as you go.
joshmarinacci大约 1 年前
You need to install linters and formatters and security checkers. But you need to start using them incrementally. Trying to fix all the issues found at once is a quick recipe for madness. I suggest using clang-tidy with a meta-linter like Trunk Check<p>docs:<p><a href="https:&#x2F;&#x2F;docs.trunk.io&#x2F;check&#x2F;configuration&#x2F;configuring-existing-linters&#x2F;clang-tidy-setup" rel="nofollow">https:&#x2F;&#x2F;docs.trunk.io&#x2F;check&#x2F;configuration&#x2F;configuring-existi...</a>)
jxramos大约 1 年前
I like to use cppdepend to navigate a large and unfamiliar codebase <a href="https:&#x2F;&#x2F;www.cppdepend.com" rel="nofollow">https:&#x2F;&#x2F;www.cppdepend.com</a>. The interactive dependency graph and integration to the editor to jump back and forth in diagrams to actual code and the many logical constructs in the source certainly accelerates getting a quick sense of the layering and a bit of the architecture of the project.
cesaref大约 1 年前
I think the approach suggested in &#x27;Working effectively with Legacy Code&#x27; (<a href="https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;working-effectively-with&#x2F;0131177052&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;working-effectively-wit...</a>) is the right one. It&#x27;s all about testing, and the confidence to make changes.<p>So buy the book, read it, apply the ideas.
w10-1大约 1 年前
Once you have the SCM in order, and before you make any changes:<p>Structure101 is the best way to grok the architecture er tangles of a large code base. They have a trial period that would give you the overview, but their refactoring support is fantastic (in Java at least).<p><a href="https:&#x2F;&#x2F;structure101.com&#x2F;products&#x2F;workspace&#x2F;" rel="nofollow">https:&#x2F;&#x2F;structure101.com&#x2F;products&#x2F;workspace&#x2F;</a>
FpUser大约 1 年前
And I have at some point inherited 5000+ files long legacy PHP code. I had to write Python program to parse that insanity to look for particular patterns and report those for manual fixing or do it automatically if possible. The example would be database access. That single software used 5 different methods to access it.<p>So no. I would not call C++ any special in this regards.
AtlasBarfed大约 1 年前
1) Make sure you&#x27;re getting paid either exorbitantly well, or at least hourly<p>2) Ask how long it would take to write from scratch? Only ask if the answer to #1 is &quot;salaried well&quot; btw.<p>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.
Jean-Papoulos大约 1 年前
A lot of this assumes the codebase is testable, but most of those legacy applications rely on global state a lot...
rwmj大约 1 年前
Surprisingly good advice. In a similar vein, Joel&#x27;s 12 steps to better software: <a href="https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2000&#x2F;08&#x2F;09&#x2F;the-joel-test-12-steps-to-better-code&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2000&#x2F;08&#x2F;09&#x2F;the-joel-test-12-s...</a>
dureuill大约 1 年前
&gt; What do you do now?<p>Look for another job<p>&gt; 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.<p>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
评论 #39556180 未加载
JoeAltmaier大约 1 年前
Read it. A little every day until you&#x27;ve passed your eyes over all of it.<p>Make notes about mysterious things. Check them off once you&#x27;ve figured them out.<p>Try to find the &#x27;business case&#x27; database. You will fail, nobody has one. Make one then, while you&#x27;re reading the code.
victorronin大约 1 年前
<a href="https:&#x2F;&#x2F;medium.com&#x2F;@victor.ronin&#x2F;hn-inherited-the-worst-code-and-tech-team-i-have-ever-seen-how-to-fix-it-f06ede3fc3b5" rel="nofollow">https:&#x2F;&#x2F;medium.com&#x2F;@victor.ronin&#x2F;hn-inherited-the-worst-code...</a>
Kapura大约 1 年前
&gt; Get out the chainsaw and rip out everything that’s not absolutely required to provide the features your company&#x2F;open source project is advertising and selling<p>Great advice! People do not often think about the value of de-cluttering the codebase, especially _before_ a refactor.
geoelectric大约 1 年前
If the blog author is lurking on here, I tried to bookmark the article since it&#x27;s very relevant to my current situation, but it didn&#x27;t have a title set for the page. NBD to copy&#x2F;paste one in, but it took me by surprise.
codelobe大约 1 年前
My first thing is usually:<p><pre><code> #0: Replace the custom&#x2F;proprietary Hashmap implementation with the STL version. </code></pre> 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 &quot;Big O&quot; (an orgasm joke, besides others) worst case scenario (Oops, pregnancy) categorized Hash Map as O(n) on insert, etc. due to naieve implementations frequently placing hash colliding keys in a bucket via linked list or elsewise iterating to other &quot;adjacent&quot; buckets. Point being: The One True Objective Standard of &quot;benchmark or die&quot; was not considered, i.e., the average case is obviously the best deciding factor -- or, as Spock simply logic&#x27;d it, &quot;The needs of the many outweigh the needs of the few&quot;.<p>Thus, it came to pass that STL was missing its Hashmap implementation; And since it is typically trivial (or a non issue) to avoid &quot;worst case scenario&quot; (of Waat? A Preggers Table Bucket?), e.g., use of iterative re-mapping of the hashmap. So it was that many &quot;legacy&quot; codebases built their own Hashmap implementations to get at that (academically forbidden) effective&#x2F;average case insert&#x2F;access&#x2F;etc. sweet spot of constant time &quot;O(1)&quot; [emphasis on the scare quotes: benchmark it and see -- there is no real measure of the algo otherwise, riiight?]. Therefore, the affore-prophesied fracturing of the collections APIs via the STL&#x27;s failure to fill the niche that a Hashmap would inevitably have to occupy came to pass -- Who could have forseen this?!<p>What is done is done. The upshot is: One can typically familiarize oneself with a legacy codebase whilst paying lip service to &quot;future maintainability&quot; by (albeit usually needless) replacing of custom Hashmap implementations with the one that the C++ standards body eventually accepted into the codebase despite the initial &quot;academic&quot; protesting too much via &quot;Big O&quot; notation (which is demonstrably a sex-humor-based system meant to be of little use in practical&#x2F;average case world that we live in). Yes, once again the apprentice has been made the butt of the joke.
评论 #39556357 未加载
评论 #39555843 未加载
评论 #39557804 未加载
asah大约 1 年前
I love how HNers assume there are automated tests with any amount of test coverage. So cute!<p>...but grandpa, how did you know your code worked? Son, we didn&#x27;t. &lt;silence&gt;<p>(wait until they hear that source control wasn&#x27;t used...)
davidw大约 1 年前
Well, tomorrow is the &quot;who&#x27;s hiring?&quot; thread...
Scubabear68大约 1 年前
The “rip everything out” step is not recommended. You will break things you don’t understand, invoke Chesterson’s Fence, and create enormous amounts of unnecessary work for yourself.<p>Make it compile, automate what you can, try not to poke the bear as much as you can, pray you can start strangling it by porting pieces to something else over time.
girafffe_i大约 1 年前
Rewrite it in Rust.
bfrog大约 1 年前
How legacy we talking? Needs turbo C++ legacy?
m_a_g大约 1 年前
I don&#x27;t want to be that person, but I&#x27;d change teams or move to a different company.
xchip大约 1 年前
Write unit tests to make sure your refactoring work.<p>It better, change job to do something more interesting
huqedato大约 1 年前
Whenever I inherited a project containing legacy code, regardless of the frameworks, tools, or languages used, we always found it necessary to drop it and begin anew. Despite my efforts to reuse, update, or refactor it, we inevitably reached a point where it was unusable for further development.
Cloudef大约 1 年前
1. Setup nix flake 2. Replace the build system with build.zig
jeffrallen大约 1 年前
This was my job at Cisco. But it was a C code base, which used nonstandard compiler extensions, and so could not be built without the legacy compilers with their locally made extensions. Also the &quot;unit tests&quot; were actually hardware-in-the-loop tests. And the Makefiles referenced NFS filesystems automounted from global replicas, but none of them were on my continent.<p>Fun times. Don&#x27;t work there anymore. Life is good. :)
elzbardico大约 1 年前
1990 Windows C++ code? Consider euthanasia as a painless solution.
btbuildem大约 1 年前
&gt; Get the build working on your machine<p>Nope. Make a portable&#x2F;virtualized env, and make it build there. That way it&#x27;ll build on you machine, in the CI pipeline, on your co-worker&#x27;s machine, etc etc.<p>&gt; linters, fuzzing, auto-formatting<p>No, for at least two reasons:<p>1) Too risky, you change some &quot;cosmetic&quot; things and something will quietly shift in the depths, only to surface at the worst possible time<p>2) Stylistic refactors will bury the subtle footprints of the past contributors - these you will need as you walk through the tunnels on your forensic missions to understand Wat The Fuk and Why<p>Generally, touch as little as possible, focus on what adds value (actual value, like, sales dollars). The teetering jenga tower of legacy code is best not approached lightly.<p>Work with PMs to understand the roadmap, talk to sales and support to understand what features are most used and valuable. The code is just an artifact, a record of unhappy accidents and teeth-grinding compromises. Perhaps there&#x27;s a way to walk away from it altogether.
评论 #39565765 未加载
cratermoon大约 1 年前
Kill It with Fire <a href="https:&#x2F;&#x2F;nostarch.com&#x2F;kill-it-fire" rel="nofollow">https:&#x2F;&#x2F;nostarch.com&#x2F;kill-it-fire</a>
cloudhan大约 1 年前
You run or your code runs, choose one and choose it wisely ;)
Merik大约 1 年前
if you have access to Gemini Pro 1.5 you could put the whole code base into the context and start asking questions about architecture, style, potential pain paints etc.
Dowwie大约 1 年前
Immediately rewrite everything in Rust.
leecarraher大约 1 年前
create bindings and externalize function libraries for other languages, hope to your prefered deity nothing breaks
评论 #39551724 未加载
professorTuring大约 1 年前
How good is AI refactoring the code? Haven’t tried it yet, but… as someone who has need to work on tons of legacy in the past… looks interesting!
评论 #39555865 未加载
sealeck大约 1 年前
rm -r<p>Problem solved
评论 #39552393 未加载
评论 #39551936 未加载
评论 #39551833 未加载
throw_m239339大约 1 年前
I quit. Life is short.
nottorp大约 1 年前
&gt; Most people resort to using the system package manager, it’s easy to notice because their README looks like this:<p>... and goes on against using system packages.<p>Well if you&#x27;re not using what your OS provides, why don&#x27;t you statically link?<p>After all, it&#x27;s the customer who pays for the extra storage and ram requirements, not you.
bun_terminator大约 1 年前
&gt; Rewrite in a memory safe language?<p>like c++11 and later?
评论 #39551699 未加载
评论 #39556370 未加载
评论 #39557991 未加载
dirkc大约 1 年前
My take:<p>1. Source control<p>2. Reproducible builds<p>3. Learn the functionality<p>4. ...<p>If you don&#x27;t understand what the code does, you&#x27;re probably going to regret any changes you make before step 3!
EvgeniyZh大约 1 年前
RiiR
hesdeadjim大约 1 年前
Start grinding leetcode and find another gig?
girafffe_i大约 1 年前
Lol no one reads, just RIIR.
BlueTemplar大约 1 年前
&gt; If you’re not doing [CI] already as a developer, I don’t think you really have entered the 21st century yet.<p>Ah yes, nothing like a veiled insult towards the people that might need that advice the most, blaming them for not using a developer paradigm that you even fail to name and for which you only give a hard to (directly) search two-letter acronym ! (&#x2F;s)<p>( CI stands for Continuous Integration :<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;</a> wiki&#x2F;Continuous_integration )
beanjuiceII大约 1 年前
the whitehouse says i should RiiR
legacybob大约 1 年前
Every morning I wake up in my legacy bed, before taking breakfast using a legacy coffee cup. I then take a shower using - you guessed it - legacy shower taps (after all, I do live in a legacy building).<p>I then sit on my legacy chair to browse the Internet and read about brand new programming things (through a legacy monitor).
jujube3大约 1 年前
Look, I&#x27;m not saying you should rewrite it in Rust.<p>But you should rewrite it in Rust.