← Back to context

Comment by jdsully

7 years ago

There seems to be a more modern trend of wanting all code to look the same. I've worked in large projects that have existed over many eras (including as far back as K&R C). The "Refactor when it becomes a problem" seems to work amazingly well. Global refactors and project wide styles seem to always fail miserably - inevitably a new era comes before the previous standardization effort completes.

E.g. in the C->C++ transition most malloc's were left alone. If you wanted to add a ctor/dtor then you would go refactor them as necessary. It also encouraged you to encapsulate your work moreso than you would have otherwise.

"Global refactors" work well with type system support, and not at all otherwise - and more modern languages do tend to come with better such support. Even for C++ itself, LLVM has a few bespoke tools to help you refactor old code as suggested by the semi-official C++ Core Guidelines - of course not all possible "refactors" are equally supported!

A project where different modules are written in different C++ dialects is a real pain when you have to refactor code across modules or even just write or review code in different modules. And the finer the granularity at which you allow dialects to be mixed (within a module, within a file, within a function), the more horrible it gets. Every time you make a change you need to think "what dialect am I supposed to be using here?" The mental surface area required to understand code grows and grows.

But it is also true that forcing all the code in a project to use a single dialect is expensive. Developers need to decide what that dialect is --- not just once, but constantly as C++ evolves. ("Is it time to use Ranges yet? Concepts?" etc.) You need to do expensive refactors every time you update the dialect. You need to enforce the dialect at code review time (harder as it changes). Every time you import third-party code into the project you need to update its dialect.

A constantly evolving language that regularly deprecates commonly-used features in favour of "better" alternatives, like C++ does, is problematic. The faster pace of C++ evolution is making this problem worse.

  • Which features are painful?

    Aside from exceptions (Can't use them safely if RAII is not universal) and shared pointers, most new language features are pretty localized in effect. E.g. using a lambda in a function originally written in C++98 does not make the existing code less safe. Only your sense of aesthetics would force you to update the rest of it.

    • > E.g. using a lambda in a function originally written in C++98 does not make the existing code less safe.

      You may not be able to if the lambda captures state and you need to convert it to a function pointer.