Live data from Hacker News

Modernize your C++ code

jarchitect.com

21–30 of 34 posts

Re: Modernize your C++ code

#22

Earlier quoted context omitted.

So no, I wouldn't like to preemptively prevent bugs, at least for any substantial cost or risk. At least not in my line of work, which usually focuses on exploratory or risky new features where some tolerance for bugs is allowed. As 37signals says, you can't save time, you can only do less . Every effort you make in a code change is a sunk cost (and often leads to more sunk costs, if follow-on changes are necessary),…

This is interesting because it raises the whole meta-question of -- could you have developed feature X faster if you'd already done refactor Y? In my experience the answer is usually "yes", but if you have a mostly-moribund code base already, then it's usually "no". Hey, reasonable people can disagree! :) EDIT: "You should not use it because you read about it on the Internet, or because it's the new hotness.". That's…

I find that if I look at features I write and ask "Could I have developed feature X faster if I had already done refactor Y?", then the answer is usually "yes" as well. The problem is that this isn't the question you're actually faced with when you make a decision (it is the question you're faced with when you're an engineer that actually has to write the code, which is why engineers and management usually differ on the worth of refactoring). It's "If I do refactor X, will it save time on the feature Y that I actually end up launching next?" And for that question, the answer is usually "no".

In other words, we suffer from hindsight bias. For any given feature, there is usually some combination of refactorings that will make it easier. The problem is that these refactorings are only evident in hindsight, once we've actually started to write the feature. If you speculatively do the refactoring, it surely will make some features easier to add, but those features are probably not the ones that you actually end up adding.

The way I solve this in my personal programming (where I am both engineer and manager, so my incentives are aligned) is to do any refactorings I wish I had immediately before writing the code. That way, I know exactly what I'm aiming for and exactly what will make it easier, and there's no guesswork involved. Over time, this also seems to produce optimally-compact code, albeit sometimes non-intuitive to someone newly introduced to the project.

Unfortunately, while this seems optimal from a project perspective, it runs counter to the incentives of both the engineers (who want to seem like really fast & reliable coders to management, and not say "This feature will be delayed because of decisions we previously made") and managers (who want to hear "This feature will be delivered tomorrow", and not delayed because of decisions previously made). Solving this incentive mismatch is an open problem; companies with technical management often do better at it but there's still a big information loss here.

Re: Modernize your C++ code

#23
post #6
post #2

I'm really impressed with this tooling. Effectively Resharper for C++. There's a huge market opportunity for C++ tooling.

How's your astroturfing day going so far?

I don't understand this reaction. If the thread had several posts from green users like these, maybe it would be appropriate to jump to this conclusion.

A more charitable explanation that I also consider to be likely is that jbHawk was a long-time HN reader who simply never felt the need to have an account until this post about a pretty neat tool which inspired them to comment.

Re: Modernize your C++ code

#24

Earlier quoted context omitted.

This is interesting because it raises the whole meta-question of -- could you have developed feature X faster if you'd already done refactor Y? In my experience the answer is usually "yes", but if you have a mostly-moribund code base already, then it's usually "no". Hey, reasonable people can disagree! :) EDIT: "You should not use it because you read about it on the Internet, or because it's the new hotness.". That's…

I find that if I look at features I write and ask "Could I have developed feature X faster if I had already done refactor Y?", then the answer is usually "yes" as well. The problem is that this isn't the question you're actually faced with when you make a decision (it is the question you're faced with when you're an engineer that actually has to write the code, which is why engineers and management usually differ on…

Very informative comment, thanks.

I certainly agree that local optimization (as in your response to my "example") usually wins in entrenched situations, but I disagree that it's "hindsight bias". Hindsight bias usually applies when you're responding to a future situation based on previous (idealized!) experience, but if you're already in the middle of a project and deciding what to do, then you're not really in the same situation as if you're starting a new project based on previous experience. (That's a bit mangled, I hope my intention makes sense.)

I'll state plainly that I tentatively buy into the refactor-early-refactor-often mantra, assuming that the language can support that reasonably.

For me, I really think that every situation is "global" vs. "local" optimization thing, and I'll argue towards "global" whenever I can, even if it reduces productivity in the short term. Michael C. Feathers' "Working Effectively with Legacy Code" was very instructive in this regard.

Re: Modernize your C++ code

#25
> Pass-By-Value: Detect const-ref parameters that would benefit from using the pass-by-value idiom.

I don't get why to make this change and the justification (after following 2 links deep: Want Speed? Pass by Value) is a 404.

Move constructors are great and it's awesome that a bunch of what used to be copy-constructor overuse in C++03 can now be done without deep copies in C++11. But I don't understand why explicitly move from something that is explicit and guaranteed to be cheap (pass by reference) to something that might be cheap if everything has reasonable move-ctors or (if not all ducks are in a row) might simply degrade to incurring the C++03-style over-copies. Does not seem like a strict improvement to me. Seems instead like blindly applying this to existing code will slow it down in some cases, possibly dramatically.

Re: Modernize your C++ code

#26

> Pass-By-Value: Detect const-ref parameters that would benefit from using the pass-by-value idiom. I don't get why to make this change and the justification (after following 2 links deep: Want Speed? Pass by Value) is a 404. Move constructors are great and it's awesome that a bunch of what used to be copy-constructor overuse in C++03 can now be done without deep copies in C++11. But I don't understand why explicitly…

It's an antipattern. Consider the following scenario: a function says "something = move(passed_by_value);". When called with an lvalue, this assumes that copy construction followed by move assignment is as efficient as copy assignment would be (which is what you get when you overload for const X& and X&&, or perfectly forward). This is untrue for vector/string-like things. When you copy construct a vector/string, it must allocate space for N elements, then copy then. Move assignment just transfers ownership, that part is fast. But consider copy assignment. If the destination has sufficient capacity, NO allocation will be performed - instead, the existing elements will be destroyed and the sufficiently-large buffer reused to hold the new elements.

Therefore, "want speed? pass by value" can result in worse performance. Overloading for copy/move is near-optimal and perfect forwarding is optimal - this is what the STL does (push_back is copy/move overloaded, emplace_back perfectly forwards).

Re: Modernize your C++ code

#27

> Pass-By-Value: Detect const-ref parameters that would benefit from using the pass-by-value idiom. I don't get why to make this change and the justification (after following 2 links deep: Want Speed? Pass by Value) is a 404. Move constructors are great and it's awesome that a bunch of what used to be copy-constructor overuse in C++03 can now be done without deep copies in C++11. But I don't understand why explicitly…

There's certainly no reason to pass something (big) by value if you only need to look at it, but not copy. However, if you're going to copy the object in any case, you should do it right-away so that the caller my move their copy to you if they don't need one any more.

I'm guessing this detection is for those cases where the passed-by-ref value is always copied.

Re: Modernize your C++ code

#29
post #7

Earlier quoted context omitted.

More maintainable and idiomatic code.

Generated code is unlikely to be more maintainable.

Code is code. I doubt a computer program could do worse than my undergrads, indeed it will probably be functionally correct. Today I fixed a bug where a condition std::thread member used a condition variable in the constructor, problem was that the std::thread came before the condition variable in the structure declaration. No computer would make that mistake.

Re: Modernize your C++ code

#30

I see no tangible reason to do this. I mean, all of this is nice , but it's just messing with the working codebase for the sake of messing with it.

Well to take the very first example from the article, adding "override" keywords: that improves your chances of avoiding bugs during normal maintenance. Have you never seen a base class that had more than a few derived classes, some of which may be in places you didn't even know about? Now imagine tweaking a base class method's signature slightly, and missing one of those derived classes somewhere, which had been try…

I'd just like to say that I have found meaningful bugs in existing code bases by running clang-modernize on them and then manually verifying that override was added everywhere I expected it to. It's just not a hypothetical benefit.
Post reply on HN