The Montreal problem: Why programming languages need a style czar
earthly.dev
earthly.dev
Bad style is just confusion: noise, but not necessarily error.
The real problem is history and architecture.
E.g., Swift has new concurrency, and the old grand central dispatch, and thread-local's, and you can reach for atomics and even C-style locks, and each of these can be used in different ways. But your application will die unknowable deaths if you don't pick exactly one and stick with it.
The same is true for data modeling and liveness.
And given the (testing) cost of migrating legacy code, the best thing is often to keep doing things the same way.
So to my mind, the most valuable people are not language mavens or even the design theorist who can make a greenfield work of algorithmic art, but the person who can migrate a system, knowing both the old and new ways and the incremental steps that can be taken while the system is running.
Recent examples are moving from Google moving to Go, or Apple moving from x86 to Apple silicon, or C/Objective-C to Swift, and even Java iterating much faster these last few years. In many cases it's as much a people problem: getting stakeholders to be patient, oldsters to be flexible, and everyone to be happy with limited improvements.
"When languages are designed for other people, it's always a specific group of other people: people not as smart as the language designer. So you get a language that talks down to you."
The same applies to these style standards. I agree with his third point in that article:
"3. Give the Programmer as Much Control as Possible."
You could argue that Go ultimately does give you a much control as possible but it certainly doesn’t do it like Lisp in the way that Paul Graham admires, and Go definitely doesn’t focus on brevity, beyond avoiding Java style magic incantations and boilerplate.
Interestingly Go is designed for “yourself and your friends” and they ended up in a very different place from the hackers that Paul Graham admires. It’s a language spawned from the pain points of large corporate software projects that wins a lot of sympathy from smart engineers that are working on large corporate software projects. The fact that it translates well to small projects as well is definitely an engineering feat.
Then I'd say concurrency, native compilation, static linking...
The simplicity of its language constructs is IMHO one reason why Go is not more popular. The point seems moot anyway. Go is mostly used by experienced programmers, usually havong experience in other, richer languages.
(Java and C# don't compete in that area at all)
That's Rust. I would not call _any_ language containing some kind of nil pointers to be " designed to prevent poor programmers from making mistakes". Go is mainly designed to be "easy to read" (and excels at that if you are used to C-style syntax).
Null pointers are a free runtime check for invalid assumptions. I don't understand the fuzz about them being bad at all.
The issue with null pointers is that they are, as you said, a stand-in for an invalid state. However, most null pointers don’t prevent you from trying to use the underlying data, which can, among other things, cause crashes (think not checking the return value of malloc). Additionally, it doesn’t make formal the litany of possible forms that a value can take — if you codify possible states, then you don’t always need to check everything. I’m currently working to port security firmware from C to Rust, and I’ve found I make fewer state checks, because the data I’m working with has bounded state — the data given cannot be in an invalid state.
Re null pointers, in Java or Python they raise an exception. Isn't that ok? It doesn't end up doing something invalid like in C.
I can quite easily follow any ML, or C-like language, even if this is the first time I see it, and then go just writes some bullshit list of tokens, where you can’t even decipher which is a type or an identifier name. And then does some receiver syntax in function definitions that is absolutely unhinged.
I don't get why Golang, ObjC, or Swift exist other than some company pushing them, and their guiding design principles are "be different to be different."
It does, arguably to a fault.
* Single-letter variables
* Capitalization instead of private/public
f, err := Sqrt(-1)
if err != nil {
// handle error
}
Probably async/await would make things briefer too, idk, haven't used Golang enough to tell.1. https://www.php-fig.org/psr/psr-2/ - coding style guidelines that are then used in tools like phpcs for automated linting
2. phpcs allows for defining additional rules that can be used in automated linting - https://gist.github.com/andreyAndrienko/19941c4b621f3212976a...
3. phpstan used for static analysis of files, allowing for defining architecture rules like: "this method cannot be used" or "this class cannot be used in this folder"
4. phpat (https://www.phpat.dev/examples/) (and architecture plugin in pest - https://pestphp.com/docs/arch-testing) allowing for defining architecture rules
Over enthusiastic machine driven style enforcement can get pretty unreadable - do you have a "one arg per line" rule - do you even enforce that in front-end validation where you have thirty parameters? Alternatively do you compromise the strength of your type safety and pack them all into a params[] just so the code is less messy? I remain skeptical that there is a reasonable one-size fits all solution to styling but I'm quite certain that python isn't it if it exists.
When your hammer is a type system
If using getOrElse in one function and using an if in another is confusing, I am very sorry: things differ, things change, and its best to just learn to read code.
When engineers tell me these sorts of style changes confuse them, I think lesser of them. It's probably not socially acceptable to say, but there it is.
if the same thing is being done in two different ways, you have to actually read and think about the both chunks of code to see that they're the same.
with consistent style you can essentially speed-read a codebase because things are predictable.
with inconsistent style, you're constantly reading slightly-different pieces of code and figuring out "is this different purely for style reasons, or was there a reason that one section if different?"
Interesting.
Just to be consistent with the rest of the internet.
It's like reading a book with no paragraphs. Of course you can do it. Nobody is "confused" by the lack of paragraphs. But you're an idiot if you think paragraphs don't matter, or don't make reading easier.
I tend to think less of people that don't understand this, or don't care.
Finding code that suddenly zigs where all the rest of the systems code zags takes extra mental overhead. It's annoying, and misleading. All too frequently bugs are coupled to such style violations, adding extra frustration around such misleading code.
That's a really good point actually. Style violations can make the code look like it does something that it doesn't, `if (a=b)`, missing curly brackets in C/C++, missing semicolons in Javascript, mismatched brackets, etc. An autoformatter can make it more obvious when you've done something wrong.
Is it an architecture thing? Because that's another great aspect of Montreal.
Maybe something like "the peanut-butter-and-anchovy" problem or the "circus at a funeral" problem.
The idea actually came from a podcast interview with a C++ expert. We talked about some parts of any large C++ code base looking like Old Montreal and some looking like Art Deco or whatever other style.
To me it was a very accurate and memorable metaphore but I get why it hits wrong for many.
Montréal is a beautiful City that has a mix of styles. Thats great for the city, just not great in a big code base.
Clearly I need a better term.
> But as code grows, it’s like Montreal. Every part of the city is different.
---
It's like "Cathedral vs Bazzar." No slight against cathedrals or bazzars; these are just colorful analogies for design/organization philosophies.
Question, do you use elixir professionally? If so, how did you get in that position?
The company I currently work at is planning to build a large messaging system using C# and a ton of memory mapped files, but I think just leveraging elixir/erlang and BEAM would make life easier.
Not really sure how to convince bossman of that, though.
If you want my personal opinion, I think you'll spend more time getting cut by the razor sharp edges of `mmap(2)` (or whatever the Windows equivalent is) than picking up Elixir, must less the difficulty in handling edge cases such as extremely high load and network failures. Elixir (or rather, BEAM + OTP) is built specifically with the problems you will face in mind, and it would be naive to not at least take a serious look at it.
I'll also add, that while I don't know the specifics of your system, message broker/passing systems tend to have very hard boundaries with serialization in-between, making it easy to build polyglot systems.
Edit: also w.r.t. picking up a new language, I'm referring to the cost of a team picking up a new language, not you as an individual :)
The biggest problem is that for the most part it's a pretty and a pretty cool language - but it doesn't have a huge community you can hire out of. So if all of your Elixir experts leave, and you're faced with a problem you cannot solve, it becomes significantly harder to figure out what the correct solution is. And for us, especially, using Elixir didn't give us any huge benefits that other languages couldn't also provide.
So you don't need to convince the bossman that Elixir is the correct language to use; you need to convince the bossman that it's a solution that will still be maintainable when you and several of your coworkers who wrote the thing leave for greener pastures.
Dart also has a kind of "standard lints" (one for Flutter, one for just Dart): https://dart.dev/tools/linter-rules
Even though you can write your own lints to verify every little detail of the code, the fact that standards exist is great.
Check out the rules enabled by the default lints, it's pretty amazing: https://github.com/dart-lang/lints/blob/main/rules.md
Many proprietary programming systems do follow this model, like Mathematica and visual IDEs like PLC programmers. But to bring it to wide programming audience we need to agree on an open format for representing syntax trees and implement several editors for typical use cases, from ultra-lightweight slow-connection-SSH-capable to more or less fully featured IDEs. Though I don't know much details about them, tree-sitter and language server protocol could be centers of crystallization for such software. I hope we'll see interesting developments in this space.
Also the whole which package manager to use in Python, or which Async lib to use, or which part of std-lib is to be avoided in certain cases or so on.
I think those things need specific guidance and agreement. AST would help with code layout though, but lots more to do in a language with many ways to accomplish something.
Not saying this isn't a solvable problem.
I say this from my own experience designing a language. Writing the AST directly was at least 2x as long as the language code.
This is more of a past idea (e.g. sexpr) than a new one, fwiw. Whether or not it's due for revisiting is unclear.
that combined with a personal "stylesheet" would allow my editor to display it the way I like
only the AST would be version controlled and other users do the same
that's the dream
To the extent that these problems exist, they are per codebase problems and allowing per codebase solutions is fine.
Languages can support multiple idiolects where different idioms are prevalent. Competent developers fluent in a language might need to learn to code switch - the way data scientists speak Python behind closed doors calls for a wholly different level of formality from the way Django coders might speak it. C# devs who build enterprise apps on Azure don’t use the same inflections that their fellow C# speakers building games in Unity use.
The important thing is to read the room and choose how you express yourself in a way that’s appropriate for the people you’re with. Are these people going to appreciate your fluent continuation passing style free expression? Or are they more comfortable if you express yourself in classes and methods?
The title was changed, the one here on HN is wrong.
He doesn't say it's a problem for Montreal, so he doesn't need to explain that.
As a montrealer I think thee effect isn't really present here but whatever, if it helps him make a point.
> The Montreal C++ Problem
And indicates that having old ‘stuff’ around when new ‘stuff’ arrives is the cause of ‘the Montreal Problem’:
> C++20 had a lot of good ideas, but lots of code predates that standard. And so drift occurs. You either don’t adopt the new way or you end up with a code base with more than one style. If you do the latter, you end up with the Montreal Problem.
(Emphasis mine)
The next section makes it seem like the ‘problem’ is about culture and language rather than, say, architecture:
> If you are doing work in the old-Montreal code section. It’s like a different dialect. You now need to know multiple dialects of the language and when and where to apply each one.
And then suggests that the new-Montreal old-Montreal problem is a divergence of community, which is ‘splitting’ people ‘apart’:
> So, how do you evolve a language without splitting it apart? This gets trickier with a whole community involved. ... And with that, the community fractures.
Overlaid with the idea that the solution is a ‘czar’ of some sort the metaphor feels clumsy and kind of inappropriate.
He certainly did before he changed the title and article. It would be nice if the author at least had a note on why and when he updated the article...
Isn't this what we call "dynamism" and frequently a highly desired trait for a group?
The whole Go philosophy rubs me the wrong way.
I mean this only jokingly: Who gets to decide what programmers are supposed to be like? You?
As someone who tries on a new language every year or two, I love using languages with formatters. Worrying about how many spaces to indent with or other arbitrary things is the opposite of what this particular programmer likes to worry about--I want to jump right in and solve problems with a language, and let the formatter make the code look like it came from a textbook.
> we need to trust people to do engineering and decide for themselves how to use that grammar.
i agree with this very much, but one snag point in a lot of projects is when people do pull-request reviews and there are disagreements about "what is readable" or "easy to understand" then a lot of time gets wasted going back and forth so having a style-czar approved format can make things smoother because there isn't much to argue about any moreSo if someone proposes that their language should have stated idiomatic style, I'd go further and say that a language style guide should come with tooling to automatically fix and automatically detect issues in as much of the style guide's scope as reasonably possible.
For some humans, they don't have to be "made" to do it. They love squabbling over style issues and rearranging deck chairs. I will never, ever understand caring about style issues, so auto-formatters are a gift from the heavens. Now the guy that used to waste time in code review can waste time tweaking the formatter rules, and everyone else can move on with their life.
Had worked with one such person before, unfortunately after introducing formatters he found a new thing to be pedantic about and started annoying everyone with that instead (it was C++ and his second obsession was ensuring that all objects are always moved correctly and no CPU cycle is being wasted while our enterprise app is waiting on the network to resolve tons of API calls).
Also you probably used less efficient algorithms because the smarter ones were too annoying to implement in C++, and there's possibly a solid Python lib that does it with hyper optimized C code anyway.
You always have some low-level detail which can be nitpicked about, even though it does not matter in the slightest.
Admittedly, choosing C++ for such a high-level project wasn't a good idea at all, but that is what the first few devs knew best and sticked with it.
I have noticed that some people will present tidy code during interviews and amazingly drop that habit once they’re employed.
Once you've read tons of code formatted with the same formatter, passing the same linter rules and following the same general idiomatic rules, it becomes so much easier to read and review new code that adheres to all the same rules.
And if someone does care about something in particular, often they will contribute to an auto-cleanup tool that makes it a certain way. So there was no reason for me to do it manually.
def ABSOrSeven(maybeNumber: Option[Int]): Int = maybeNumber match {
case Some(int) => Math.abs(int)
case None => 7
}
Somewhat more verbose but I think is the most clear and should have fewer function calls than the getOrElse version and has no unsafe operations like the (safely guarded) `maybeNumber.get` call.The point though is that the author is correct that scala provides too many ways of doing the same thing such that disagreement is inevitable.
I’ve seen entire language ecosystems get overwhelmed by fads of this sort, and dealing with these waves of pointless trend-chasing is exhausting.
I think this is because all of tech seems to be culturally downstream from FAANGs who have weird problems like "we have 500 devs making multiple commits a day and we can't trust them to do anything more than close tickets." Those are wholly self-inflicted problems, but the rest of the industry laps them up as if they are the secret to being as "great" as FAANGs. Couple that with tons of people who have less than <7 YOE in tech and/or are switching into it and you see there are very real political advantages to "keeping up with best practices."
The zeitgeist re style is very much “don’t fret too much about it, use an automated tool and move on”.
Compared to the flame wars of the past about tabs vs spaces and other inconsequential things we’ve come a long way, and for good.
Isn't that just a consequence of how much--or little--context is shared with (or easily-communicable-to) Random Strangers On The Internet?
For example, I've got some architectural issues going on, but it's a lot of work just to summarize it in a way that doesn't require local/domain knowledge. In contrast, talking about the weather or tabs-vs-spaces doesn't need much set-up.
I say this with 20+ years of programming experience: a project that doesn't do that is a project run by amateurs.
That argument doesn't make much sense IMHO. By enforcing as many things as possible using some tooling we now do have more time to actually learn "core principles" instead of figuring how to configure/use/... $IDE/$EDITOR/$TOOL/$COMPILER/$OS to get comparable results (or anything to build at all).
Last job we were having trouble communicating and collaborating with some acquired teams, and I figured something out that helped a little - a culinary analogy - my team knew how to cook, let's not aggrandize ourselves too much but say we were at least short order cooks at the diner, while these new teams were McDonalds' workers. McDonald's workers aren't all idiots or lacking work ethic, but they know how to follow the laid down McDonald's burger production processes, not how to cook.
So there's gonna be a desire for McDonald's processes.
Or what if an apostate arises and promulgates a radically different vision of what ‘good style’ is in the language?
This isn’t a purely theoretical risk. The ‘Automatic Semicolon Insertion’ heresy is an active alternate reality in the JavaScript world - with some developers willing to argue to the death that semicolon-free style is the only professional way to write JavaScript code; while many developers carry on coding in the C-like syntax JavaScript was clearly intended to use blissfully unaware that they are actually on one side of a violent debate.
Also, nobody has to follow the guidance of 'style czar'. Each team and community could deviate in whatever ways. "We follow the standards expect for these changes about semi-colons." I think just having a standard can helpful when having your own style as well, because you can contrast it against something concrete.
That is what has solidly convinced me that programming languages themselves, like the compiler, absolutely need to fuck off with the rigid style proscriptions.
There does need to be a solid, configurable linter so that any given codebase can have its own strongly held and automatically corrected opinions. I don't trust any one person or a cabal to determine style for everyone using the language though.
When it comes to something like that Javascript semicolon debate, the way to solve it is linters with a flag for either set of people, so they can be their own dictators over their own codebase.
If you happen to remember, please update your comment or respond to mine.
[I believe that this doesn't exist OR it isn't useful, but I really want to be proven incorrect.]
EDIT:
Were you referring to the architectural complexity mentioned here: https://swizec.com/blog/two-types-of-complexity-and-their-im... ?
Then how exactly am I supposed to pretend that I'm writing Haskell at my day job??
Maybe i've got lucky? Or maybe this is a solution looking for a problem? All I know is that whatever you adopt as a standard today will look weird and outdated in 20 years time, so frankly, don't sweat it.
I’ve seen a codebase where one guy wrote all code in Obfuscated C Code Competition style with all optional whitespace removed. Huge solid blocks of spaghetti code with the line breaks inserted only to make the code line up visually into rectangles.
Another guy at the same company thought that a good naming convention is to name all identifiers starting with ‘a’ alphabetically and then extending that with ‘aa’, ‘ab’, etc… when he ran out of single letters. I mean all identifiers including namespaces, class names and methods names. Code read literally like this:
z = g.h.p( ab, j, y );
At least with the IOCCC style it was possible to simply use an IDE reformat to fix it, but this basically required decompilation to make sense to any other human.Another example is Jarek Duda's paper on the ANS compression algorithm. A brilliant guy by all accounts, but his diagrams are... well... impenetrable. Check out Figure 4 on page 10: https://arxiv.org/pdf/1311.2540.pdf
There's lines and arrows going every which way. There's about five different concepts layered on top of each other into one diagram, with nothing to obviously disambiguate them. Like... what is the black dot between C(s,x) and D(x), and why is it pointing in random directions!?
The most extreme and stereotypical version of this style are the billboards written by some homeless people. You can probably picture it already in your mind's eye: A wall of very dense text with little whitespace or structure, and a mix of fonts and colours seemingly at random.
I had a brilliant mathematician friend who wrote like this. He would squeeze an entire semester's worth of study notes into a single sheet of paper, on one side. It was impenetrable gibberish to everyone else, but the colours and 2D positioning let him build a mental mind-map.
For people like this, if you reformat their code even a tiny bit, their mental map is invalidated, and they lose track of it completely and become upset. I discovered this (the hard way) when applying automatic code formatting tools to the codebases I mentioned previously.
Personally, I find this type of thing to be absolutely fascinating, because it's the intersection of many scientific fields but belongs in none, and hence is under-studied. There's elements of pedagogy, psychology, literacy, neuroscience, computer science, etc...
It remains an open question how we can get large groups of neurodiverse humans to collaborate on a codebase when they don't even "read" or "think" in compatible ways!
Enforcing a single style may work for most developers, but clearly not all.
PS: Even on an anecdotal level, when I was a beginner programmer I could only read a single brace and indentation style. After two decades, I can now read almost any style, including inconsistent and outright crazy indentation without even noticing that something is amiss.
I'm sure you've seen plenty of projects succeed without tests or CI or code review or comments or bug trackers or static types or linters or version control or ...
None of those are required for a project to succeed, but they're all best practices that we have learned make things better than not doing them.
If code was stored as an AST, everyone could tailor the rendering (tabs vs space, where brackets go. Whether to put a return on the last line in Kotlin) to however they like and tools like gofmt would be obsolete. That's not to say this approach isn't without its downsides though.
> I can write a single file, calculator class and start with a Java style:
// Returns, braces and semi-colons
def getResult(): Double = {
return result;
}
def multiply(number: Double): Calculator = {
if (number == 0) {
println("Multiplication skipped: number is 0");
} else {
result = result * abs(number);
}
return this;
}
Scala has this problem, but this is a terrible example. Because literally no one writes like this.More plausible is:
def getResult: Double = result
def multiply(number: Double): this = {
if (number == 0) {
println("Multiplication skipped: number is 0");
} else {
result *= abs(number);
}
this
}
And even that's a bad example.Because still no one writes Scala like this, with mutable chaining. (Java yes, Scala no.) It's either mutable, or immutable chaining.
Maybe there is a style implied by Odersky's Scala course, but I'm not sure even that style is considered the in fashion style these days.
Somebody needs to write these things down. People can ignore them, but at least deviation would be explicit. See my diagram with the arrows.
But for actual “tabs vs spaces” or “opening bracket on same or next line” discussions? These days those are a total waste of time. Just run Black, prettier, godfmt, whatever your language has - that removes like 80% of coding style-related discussion.
this is not just a style issue, its also a functional one https://tpolecat.github.io/2014/05/09/return.html
AKA the systemd approach.
I’m willing to say that I am (was?) in the doesn’t exist camp, and was shocked when I found it in inside the compiler and in a few other places.
The shock was similar to that I’d experienced writing in languages that don’t have a “style czar”. When reading Go, you usually can predict exactly where every variable is declared, but with struct embedding that certainty is lost.
LISP is incredibly flexible. The ability to use macros to build DSLs without ever leaving the language, and have all the tooling designed to work with the language able to work within that DSL, is a game-changer.
... but what it changes the game into is "If you're working solo you can bend the whole language around to fit your mental model, but if you're working in a group you now have every engineer creating dozens of (probably unsanitary) bespoke macros to bridge the gap between their problem and their mental model today and the end result can become indecipherable to a new user, which jeopardizes a business project."
Paradoxically, flexibility can kill a large project. Large-codebase projects with 100 engineers don't need multitiools. They need what the army needs: an M4/M4A1 5.56mm Carbine with mass-produced ammunition. And they need it because when a fellow software engineer "falls in battle," it's in the company's best interest if you can pick up their weapon and start shooting immediately without having to learn the eighteen abstractions they hid the trigger behind, even if that makes your day-to-day work a little slower because there are upper bounds on how you can modify your weapon.
They're not planning for your needs; they're planning for your needs and the needs of everyone after you who will pick up your weapon and wield it when you're gone.
I'd be interested to know what approach Lucent took to wrangling the complexity.
But then you'll need a lot of tools and architecture to deal with that. To reduce the code size to write, they probably would need to add frameworks, code generators, model-driven architecture, domain specific language, ... lot's of tools. Let's say you'll need to persist C++ objects into a database, they probably used an OO-database (at that time) for C++ with a special query language. Otherwise they would have used a more traditional relational database, either map things to an object-oriented persistence framework or write SQL. Tool building/usage is key, I would think.
Greenspun's tenth rule also applies.
No particular style is important, but design centralism and simplicity is important. Tools like Gofmt and black/isort I make sure are baked into dev environments, and I aggressively question the addition of new dependencies. Why are you importing superl33thttp when we already have requests?
I may not always agree but I go with clippy's suggestions anyway (which btw. just means passing --fix, most of the time, and they're done for me).
Because I care about other people reading my code.
One of the realizations the article touches on: if everyone uses the same idioms in a language, code becomes way easier to read for everyone.
This wasn't so obvious to me until recently. I was regularly still writing/touching a lot of C/C++ (25 years -- until ca. early 2021).
So everyone's lib/header/whatever uses their own style and when you also need to modify or at least audit/understand 3rd party code, you're kinda use to dealing with that. I.e. I would have said: what is all the fuzz about?
Or I guess I could also be saying: when you get kicked in the shin every day, it won't hurt so much any more after some time.
I never though of this as making such a difference until I started using Rust professionally: my shins hurt way less; mostly not at all as everyone is using rustfmt & clippy. In fact, many Rust repos now have these two coming out clean as a condition for a PR to even make it through automatic checks.
I think this could be an interesting experiment. Maybe choosing a style to save that is better for reviewing/diff-ing, then being free to have your own personal preferences when editing.
Good style in an SDK or a library is not necessarily the same as good style in a self-contained business app.
Just like suburbs and downtown can't be expected to look similar (whether in Montreal or elsewhere), style, too, is context-dependent, and there's more aspects to this context than just the language of choice.
This is inspired by my love / hate relationship with Scala. I love the language, but it's so flexible that in a large enough code base, it becomes a mess.
It's not a Scala-specific problem, though. I think that languages that have a lot of powerful constructs need to be explicit about style, what's idiomatic, what approaches are no longer considered ideal, and when it's appropriate to reach for various features.
I see here that many disagree with me, which is ok I guess. But I'm pretty pro code formatters and style guides and I wish their were someone in charge to break the impasse of package managers in python? How do you overcome the XKCD 927 issue?
I think someone needs to be empowered to force convergence in languages when its needed.
it's not scala specific, but it is a function of the flexibility of a language.
scala and perl are the only two languages that i am aware of where this issue is a common complaint. other languages are either not popular enough for this issue to surface or they are not as flexible for it to be as big of an issue as it seems to be in scala and perl.
At some point, a problem is unsolveable.
After setup.cfg and setup.py and pyproject.toml and pip and poetry and pyenv and pipenv, it's actually over for Python. There is no way to mulligan after 15 years of mediocre tools followed by mediocre tools.
The other day somebody tried to convince me that poetry's handling of index urls is safer and saner than pip. It's probably true, but I only used pip because it was available, not because I like to be unsafe. So when another group of experts comes along and says "lmao of course pip (the only tool you could use until now) is worse than poetry", I just can't care anymore.
tl;dr once the XKCD 927 issue lands, it's here to stay. A language has to come opinionated out the gate (like Go or Rust).
Québécois language and culture was forced upon Montreal's sizable and established populations of English-speaking and non-Québécois residents via Loi 101 and other policies.
Regardless of one's stance on the matter, the reality is that it was extremely disruptive to Montreal, socially and economically.
Throughout the 1970s and 1980s, many residents and businesses ended up leaving Montreal, and moving to cities like Toronto, Calgary, and Vancouver.
Toronto, Calgary, and Vancouver subsequently saw significant economic and social growth, while Montreal stagnated throughout the 1980s and 1990s, and even beyond then.
Today, Montreal still has a rather fractured society in many ways.
Maybe a "Style Czar" figure or mentality can bring a sense of consistency, but forcing it on existing and established communities will likely cause a whole new set of problems.
It wasn't meant to be a knock on Montreal. But on code bases that have very apparent different eras and styles.
The idea actually came from Kate Gregory, in an interview I did with her some time ago, where she talked about some parts of any large C++ code base looking like Old Montreal and some looking like Art Deco or whatever other style.
Edit: Yes, Montréal Effect seems better... changing.
Perhaps calling it the "Montréal effect" would be more apropos?
Widely homogeneous cities are not necessarily failures, but it's hardly a indicator of somewhere that functions well (as a city).
At the end of the day, I don't really care how you write your code as long as I can read and understand it, which comes 90% down to 1) did you choose clear names, 2) do you have clean abstractions / interfaces. If you did that, write your code however you want. And in fact, it's antisocial to demand that other devs (junior or otherwise) adapt to your own personal idiosyncrasies. Just as in writing prose, different authors have different, clearly intelligible "voices" that distinguish them. Stamping out someone else's voice just to match your own preferences kills the joy of programming for them, you should only do so in the direst of circumstances.
Most people see it as the exact opposite of this: it's you who are trying to impose your own personal idiosyncrasies on the project if you don't just adopt the project's style (which is hopefully automated so all you need to do is press a shortcut once you're done, or run a command before comitting) and insist on doing your own thing.
last week in a codereview i got asked to clean up indentation of some html structures that i had added.
my response was: i duplicated an existing structure and made mine look exactly the same. i agree that proper indentation would be nice. but if i did that, my structures would look different from the original. i could clean up the original too, but then the diff would be harder to read because it would contain unrelated changes.
copying the original unclean structure in this case is best for readability, because consistency is more important than any particular style.
if anyone cares about the style, they can submit a style cleanup separately.
The idealist part of me wants to say: Clean up the original code, submit that as the first diff, then rebase your additions on top as a separate diff.
The pragmatist part of me recognized long ago that a lot of software engineering now is like what you describe. The days of elegant, carefully-maintained codebases where someone sweated over every semicolon are long gone.
this is not a thing that has ever existed. what on earth are you talking about.
when working by myself without PRs then i would do almost exactly as you describe. i would probably put the cleanup after the code change though mainly because i want to focus on solving the problem first, and worry about cleanup later. but i can see the benefit of doing the cleanup first.
* Indenting consistent with the curly braces, and well enough defined that when you remove an outer loop and want to unindent the code from that block, you don't have to do it by hand.
* A one-line code change doesn't bring with it a 500-line style change because the file passed between people with different style tastes.
Unfortunately, it's often difficult to achieve these modest desires without someone also wanting to limit line lengths, ban the ternary operator, ban nulls, and so on...
[edit] naming, yes. That’s important. Static types are enormously important—machine-checkable documentation is the best sort. Comments are excellent if names and types aren’t enough. Separate documentation if all of those fail. Where my braces go or tabs-v-spaces or what have you? Not so much, but again, maybe it’s because we write different languages.
things
.where($"key" === lit(key))
.select("value")
.as[String]
.repartition(N1, $"value")
.flatMap(new ThingIterator(_))
.repartition(N2)
.write
.parquet(
s"s3a://bucket/things/key=$key")
As for naming, I see stuff like “every method must take one arg whose name ends with Request” even when envelope or notification would make more sense.That’s much closer to being “the way infrastructure operates” than formatting is.
I suppose 100% of IAC is right out, then.
In general, one should refrain from drive-by refactoring.
It doesn't matter what the style convention is so long as you have one, you have automated tooling that creates and validates it, and that enforcement is done by machines as part of the delivery process.
Not because style is valuable but because time is a valuable resource and spending it on preference differences and dealing with variances is wasteful.
When I've led teams, I've never enforced things like indentation or bracketing styles. Things I do enforce are (1) explain complicated code with comments, (2) make it readable (for whatever definition of readable), and (3) reasonable naming conventions (i.e., don't name every variable i, j, k). These guidelines are useless for automated tooling. Perhaps in the age of LLMs this will change (who knows).
I've found the strict requirements and automated tooling absolutely terrible. I often align things to keep parallel structure to show how different lines are the same or to create 'tables', etc. Formatting tools destroy this. For me, using my emacs rectangular editing, the alignment greatly increases productivity. This is one example. I'm much faster at editing personal projects / projects I've led than ones with strict style guidelines.
For me, I always tell my guys: edit in the style in which you are fastest and most efficient. I believe this greatly increases productivity rather than having a team 'nosy neighbor' that cares whether you use two or four spaces for indentation.
My two cents.
I work at a large tech company, and while I don't really participate in style wars, I do care that there is a single enforced standard across any particular codebase.
I also think this is more of a Zeitgeist thing, to be honest.
I disagree for two reasons:
1. Optimizing for what each dev is used to is optimizing for a local maximum. If they’re THAT good it won’t take them long to adjust to new defaults. Good engineers should be able to pick up a new lang quickly so some changes in the context of a language should not bog them down significantly in the long term.
2. The overly long time it took to set up tooling in a particular company or language do not outweigh the bigger advantage of being able to quickly get a grasp about what a piece of completely unfamiliar code does.
I might paste something, but mess up and forget to select one of the curly braces or select too many. I am seriously considering closing all of them on the same line in this style
if blah {
thing; }He lost a lot of credibility in my eyes that day. Really, you are so very much more experienced than me, but you cannot cope with tabs?
Since that time, I am even more tired of style discussions. Choose whatever you want, as long as you don't make it annoying to me (e.g. if you want a specific formatting, give me a tool; don't force me to do it).
I would rather have an Abstraction Czar that ensures that all code is properly abstracted (not too much, not too less) instead of the nightmares I have to deal with every day.
Well, I was new here, but it seems that contributing is not for me. I will go back to just reading then. You people do you ...