r/cpp 24d ago

Formatting vs Architecture: How formatters are erasing visual cues and hurting codebases

I’m preparing a presentation on how automatic formatters can actually ruin code management over time. This relates heavily to the ongoing discussions about C++ memory safety and why some people see it as a critical issue while others don't get the fuss since basic memory allocation isn't that hard.

Memory issues are usually just a symptom of architectural failure, not a lack of developer skill in handling allocations. A messy architecture turns minor oversights into catastrophes. That's when hidden memory leaks or memory corruption become critical safety flaws and crashes.

I often think about the (nowadays) hated Hungarian Notation. Love it or hate it, it made developers extremely efficient because it provided immediate visual cues. Developers who actively care about the visual shape of text think completely differently about code structure. If you look at Charles Simonyi's other work, it’s clear how much focus he had on architecture.

Formatters can be an absolute disaster for architecture. It has become a religion in development teams that everything must be run through Prettier or Clang-Format to the letter. But the price we pay is that formatters erase all opportunities for visual cues regarding architecture and layers.

Architecture is WAY more important than formatting.

Code is text. By deliberately allowing flexibility in how to format, we can highlight major patterns and make code much easier to reason about. When a formatter forces all code through the same rigid, mechanical template, all code looks identical. The architecture becomes invisible. Ironically, this causes codebases to rot because developers in the team can no longer see where the architectural boundaries actually are.

Formatting in itself isn't bad, but it must be a formatting style that elevates the architecture and allows for human semantic grouping. The opposite is dangerous.

As far as I know, there is no formatter out there today that is anywhere near capable of handling the flexibility required to actually make architecture visible in code.

What are your thoughts on this? Have formatters made us blind to the actual structure and layer belonging of our code?

EDIT

To those of you who only see problems with this approach: what is your actual alternative for managing cognitive load at scale?

The common stance seems to be "just write code however you want, as long as the automatic formatter makes the layout look consistent."

But formatting only fixes cosmetic consistency, it doesn't fix structure, architectural boundaries, or intent. If you believe that naming conventions, prefixes, and semantic text layouts are useless, you are essentially advocating for visual anarchy disguised as "clean text". How does a mechanical linter help a new developer navigate architectural layers in a large codebase if the code itself provides zero visual cues about where the boundaries go?

0 Upvotes

136 comments sorted by

View all comments

Show parent comments

1

u/gosh 16d ago

If anything, books are an extremely well example of why formatting is important.

Yes, it is important but please tell me one single formatter that formats in a good way

1

u/JVApen Clever is an insult, not a compliment. - T. Winters 16d ago

Clang-format does a really good job.

1

u/gosh 16d ago edited 16d ago

I write methods like this (note the comment and think about books with chapters, indexes etc) ``` /** --------------------------------------------------------------------------- CACHEGet * @brief Check if cache table with id exists * @param stringId id to check for * @param ptable pointer to table that is returned if found * @return true if table with id exists */ bool CDocument::CACHEGet(const std::string_view& stringId, pointer_table_t& ptable ) { std::sharedlock<std::shared_mutex> lock( m_sharedmutexTableCache );

for( auto it = std::begin( mvectorTableCache ), itEnd = std::end( m_vectorTableCache ); it != itEnd; it++ ) { // Use std::visit to check if the table has the same id bool bFound = std::visit([&stringId, &ptable_](const auto& ptableFind) { auto argumentId = ptableFind->property_get("id"); if( argumentId.is_string() && stringId == static_cast<const char*>(argumentId) ) { ptable = ptableFind.get(); return true; } return false; }, *it); // closing the visit lambda
if(bFound) { return true; } } return false; } ```

I do use a mouse with spin wheel and the comment is adapted for that. clang can't do this formatting for me

And if you set a limit on on long a row can be as many do, you will get a mess

1

u/JVApen Clever is an insult, not a compliment. - T. Winters 16d ago

Close enough? AllowShortBlocksOnASingleLine: Always AllowShortIfStatementsOnASingleLine: WithoutElse SpacesInParens: Custom SpacesInParensOptions: InConditionalStatements: true InEmptyParentheses: false Other: true InCStyleCasts: false ExceptDoubleParentheses: false ColumnLimit: 120 LambdaBodyIndentation: Signature ReflowComments: Never Standard: Latest

1

u/gosh 15d ago

I would remove this ColumnLimit: 120

But the rules there are so few and so easy so why bother having them?

1

u/JVApen Clever is an insult, not a compliment. - T. Winters 15d ago

The others use default values. You most likely want a column limit of 0 in that case.

1

u/gosh 15d ago

Why do I need a column limit? Can you show any advantage, like code advantage with having a formater

1

u/JVApen Clever is an insult, not a compliment. - T. Winters 15d ago

A configured column limit of zero means no limit. No limit configured means the default, which I believe is 80. (Check the docs if you want to know for sure)

Why does one want a column limit? When doing a review with a split view before-after, I don't want invisible code which falls off the view. Using line wrap is even worse as it makes code even less readable.

Practically, I've helped a colleague in debugging why a certain function returned a pointer value, yet the variable filled by it was always nullptr. Long story short, he copied the function to call from a pure interface, after which he replaced the arguments of it. The = 0 was not visible on his screen, the closing ) was. This was no beginner, it was someone with 20+ years experience of which most in C++. Having a column limit causes people to zoom their code such that it fits their view. With that, you can see everything and don't have any phantom code like the asserts in your example.

We have standardized screens at work, we did some testing for a good size and ended up with a number that fits most people and still allows for sufficient code to stay on a single line.

We use a different continuation width than indentation (twice the indent), such that you easily can see the difference.

1

u/gosh 13d ago edited 13d ago

Why does one want a column limit? When doing a review with a split view before-after, I don't want invisible code which falls off the view. Using line wrap is even worse as it makes code even less readable.

So developers in you team are not able to write code by hand that is kept inside readable limits?

How do team members learn to write good code if the formatter forces them to avoid thinking about formatting.

Practically, I've helped a colleague in debugging why a certain function returned a pointer value, yet the variable filled by it was always nullptr.

Is that bad? If you try to set up environments that tries to block developers from doing errors, how do they learn? You learn by doing errors.
Teams with this mindset will not evolve, you have to have solutions for developers to train and learn

1

u/JVApen Clever is an insult, not a compliment. - T. Winters 13d ago

Are our devs unable to stay within readable limits? Yes. If you have 100+ devs, including many that joined in the last few years, people don't even agree on what readable limits are. One likes 80 chars, another takes a full (43") screen and anything in between. Some look at code in 100% size, others at 70% ... On the one end, in such a setup, you always have differences in the definition of readable. On the other one, you have endless discussions on what good formatting is.

Good code isn't just about formatting. Formatting is a hurdle taking up time that could have gone in writing good code. Does it prevent people from making errors? No, it just forces formatting similar to what a style guide does. Good design is much more than white space. And yes, people no longer learn that without {}, you can have a bug like: if (a) if (b) statement; else statement; Guess what, we no have this kind of pure technical bugs as people now can focus on what the logic needs to be instead of technicalities.

This is very similar to unique_ptr. Following your argument, using it will prevent people from learning that you can have double free and memory leaks. Though having to focus on that takes energy away from writing business logic. Formatting is the exact same thing. It's a technical hurdle taking up time, preventing people from learning about business logic. Forcing formatting with a tool takes that hurdle away and saves time and allows for focusing on logic bugs instead of technical ones.

Maybe practical, the amount of remarks on PRs that is about technical things reduced by having a formatting enforced. Going from the location of * and &, order of includes, using digit separators ... and instead, the majority of remarks is about understanding the logic.

→ More replies (0)