Beyond the satire, one is supposed to write code which is readable, and like often with written works, one has to think about the "audience", the readers. When you write technical documentation, you have to decide ahead of time the expected skill level of the reader - often that decision is written too in the intro as "prerequisite(s)".
When writing code you have the motto "don't make me think" in mind, but how to know what's the maximum level of trickiness for readers? There are familiar techniques and idioms when it is your main programming language, but they are not for someone using this language on the side.
In any case, neither code nor comments should be tutorials. To a reasonable extent, it is up to the reviewer to do their homework or just ask. Then based on that interaction you can add a comment or a parenthesis, or uncompress a bit the code. But not to the point that it means to "dumb down" things, because it is a downward spiral.
> When writing code you have the motto "don't make me think" in mind
I disagree with this phrasing. We’re engineering after all. The entire job is thinking. If someone doesn’t want to think, then they shouldn’t be a programmer.
Readability matters, though. I try to have a narrative structure in my code, so it leads the reader along. Formatting matters. And documentation helps. If you want to introduce an unfamiliar idiom that might be more functional, good, but document it. Share it with the team and talk about it. I know that writing and reading documentation is usually seen as a waste of time unless you’re doing it for AI, but I’ve seen it work well in multiple teams. In my experience, the teams with poor docs have the worst code.
> > When writing code you have the motto "don't make me think" in mind
> I disagree with this phrasing. We’re engineering after all. The entire job is thinking.
Well, sure. The implied full phrase - more technically-correct, but less pithily-quotable - would be something like "don't make me think unnecessarily; let me spend my thoughts productively. If you've already spent brainpower on figuring something out, explain it to me directly and clearly rather than forcing me to go through the same discovery process"
So - yes, if someone doesn't want to think _at all_, they shouldn't be a programmer; but if someone has an aversion to being forced to solve a problem that someone else has already solved, they likely have the right "shoulders-of-giants" mindset.
(For any potential pedants - yes, there are some practices you simply have to work through before understanding dawns, which cannot be explained directly. Still, though - the explanation should aim to minimize unnecessary thought-requirements so the student can get straight to learning)
100% this. I'm increasingly of the opinion that "ability to evaluate how often/extensively a chunk of logic may need to be changed in the future; and to design accordingly" is one of the most underrated skills in software development:
* If it's "write once, run a few times, discard", go ahead and throw together whatever you want
* If it's "write once, run a bazillion times at the very core of your logic with very few changes over time", optimize for efficiency over legibility
* If it's going to be written and rewritten and evolved and tweaked many times, optimize for readability and flexibility
Just because fires are inevitable in the business of firefighting, doesn’t mean that firefighters are in the business of starting fires.
In engineering, thinking is inevitable but also costly and error-prone, and the more thinking an engineer needs to do the higher the costs, the higher the risks of errors. We should be striving to minimize the thinking required every step of the way, even if we’ll never get it down to zero; that’s the only way to keep it from spiraling towards infinity.
Teams are not a static concept, they change members over time and so talking to them has a net zero effect. The newer members will not understand this clever new concept that was introduced, worse, they will misunderstand it or work around it. Which brings us back to don't make me think. If the concepts can be kept as simple as possible, which overlaps greatly with readability, it will have achieved its purpose.
"I didn’t have time to write you a short letter, so I wrote you a long one." -- Mark Twain
It's difficult to explain how to write well, but bad writing and bad computing systems typically impose far greater cognitive burden on readers than might have been necessary. There is an art to software engineering.
Functional programming does involve idioms, though I would say no more than imperative programming, or OOP, or some other paradigm. One of the overarching themes of FP is to reduce the cognitive footprint to only the essential properties of the problem to be solved.
A novice artist can produce a recognizable figure using many pencil strokes. It takes a master to produce a compelling likeness with only the lines that are necessary.
Maybe a better phrasing is "don't make me think about inconsequential details". If I need to figure out your particular idiom of writing a for-loop, then that takes time away from thinking about what the code is actually doing. Even if that idiom is perfectly fine and works the same as any other for loop, it's not worth it if it makes people think about unnecessary things.
But like you say, if you've got an idiom that's actually useful (like programming in a functional style to avoid action-at-a-distance side effects), then document it so the whole team can get used to it and stop having to think about it.
When I write functional code I start with Peano and then go from there, ommiting comments are descriptive names. It encourages thinking in myself and my coworkers.
// Automatically iterates through all the user's
// departments and assembles a single list of all
// their employees.
Perhaps a note should also be added explaining why the domain model opted for u.departments and not for something more natural like u.company.departments. And the comment should also explain, why we do not filter for duplicates here.
I insert many such comments into my own code when I use a rare language feature or a somewhat peculiar element of the domain model. This makes refactoring my own code much easier, faster and more bug-resistant. When composing code, it is generally simple and quick to add such a comment, as it is merely a matter of writing down the result of my immediate thought process.
Id argue the function name and placement are bad. I have coworkers that arent in my department. If its not obvious what the method is doing from the name and requires a comment then its a bad name.
I would say that this is only true for very, very simple use cases. Even moderately complex code should at least be accompanied with a concise documentation. Here is an example from my work:
Consider the case were two database fields should either both be NULL or both must have a value. Instead of 'amount' and 'currency' and documenting the relation, should we really name the fields 'amount_if_currency_is_not_null' and 'currency_if_amount_is_not_null'?
And is it really sufficient to define 'amount' as INTEGER without any documentation and then demand that everyone new to the project and not familiar with financial calculation immediately understands that the value is given in the lowest unit of the associated currency, i.e. cents for US dollar vs. one hundred millionth of a bitcoin vs. Icelandic króna (which has no subdivision).
Good luck to find a short name that makes that obvious.
If you're a computer programmer, coding in a high level language with closures and garbage collections, and you are confused by flatMap: I think you should find another career.
I don't think anyone is confused by flatMap in isolation. It's chains of not-very-obvious data transformations. When I have to do one of these I typically break out each step into
it's own line/block and add comments with an example object to show precisely what every intermediate step looks like. They're hard to follow otherwise.
And functional programming snorts these long chains like lines of coke and when you add some random curried functions and people who write in a pointless^H point-free style it's easier than folks like to admit it to end up with write-only code.
I've never found myself with a block of code that could be expressed as a flatMap and thought it would be easier to understand by expressing it as such. I'm perfectly capable of writing functional code but after reading it back I almost always throw it out for something imperative because it's clearer as to what's really going on. The code is going to be executed in an order at the end of the day, why make it harder to see what it will be?
When I am doing MBSE, and I discuss what level of detail is required in my abstract models one of my senior coworkers would remind me to “know your audience”. It has helped me and I use the same phrasing when I am coaching my teams now.
On the one hand, this stance seems common sense: why overcomplicate things? Let's just do what's commonly understood and move on.
On the other hand, writing code that the most junior in your team can understand leads to mediocre code. In the end, it crumbles under its own weight.
Most of what we master now was difficult to understand first. Should abandon generics because "it's difficult" ? Should we ditch static typing because "we're not used to it" ?
Maybe.
Or, maybe, this is the right tool that can take us to the next step. So we pause and think at this new approach to understand it then master it.
I don't really believe this but ok. I worked at a functional / typescript heavy shop where when I had parsed what a complicated set of steps was doing discovered multiple redundant queries and a library that was parsing strings into code. But damn some of those functional paradigms chef kiss /s. Imo my dumbass code , besides being demonstrably more performance was way less of a liability.
And this article is -
Oh so you don't like FP do you? Have all the side effects in the world! You don't worship at the church of monad? I guess no "pure" functions for you then! bwa hahah
> I worked at a functional / typescript heavy shop where when I had parsed what a complicated set of steps was doing discovered multiple redundant queries and a library that was parsing strings into code. But damn some of those functional paradigms chef kiss /s
And I've worked at a place where the imperative code was crap. Should we abandon all imperative code because I had that experience?
People can write bad code in any paradigm - that's not what decides how we should code.
Nobody says we should throw away all imperative code because of one poorly implemented code base. But for some reason I see that targeted at FP all the time.
> On the other hand, writing code that the most junior in your team can understand leads to mediocre code.
Disagree on a couple levels. First, while the overall architecture of the system might be complex, there shouldn't be any one single function that isn't readily readable by a junior new hire. Complexity is in the system, there should be no complexity in small sections of code.
Second, the ultimate level of mastery is to be able to build simplicity. Any newbie can write a convoluted mess that nobody can understand.
Every so often I encounter some dev that is not familiar with SQL. So instead of writing a single SQL and relatively "simple" SQL request that does the job db-side (say with a few joins and coalesce but no sub-query), they write several requests then process the result in python.
The argument ? "SQL is complicated, it is simpler to just do it in Python."
Is it though ? I guess it depends on the request and the exact processing we are talking about but in many cases I suspect it is because that person is not familiar with SQL.
What "simple" means is not so simple to define. Sometimes it means "easy for me".
> On the other hand, writing code that the most junior in your team can understand leads to mediocre code.
Sorry but this is absolutely false in almost all regular corporate software jobs.
As i get greyer, I find myself spending much more time planning before I write any code now; what I would previously have run into headfirst and solved with a bunch of advanced language features and complicated logic usually now ends up being implemented in much less and simpler code.
This is the sign of a senior developer, in my book.
Writing code anyone finds hard to understand is a marker of inexperience to me.
If the problem can be solved efficiently with simple, write simple code by all means. Heck, if it can be solved with a spreadsheet, please use a spreadsheet. Even your boss can read it.
But, at some point, spreadsheets crumble and become unmaintainable. And so does "basic" code.
Should people keep on using spreadsheets ? Depends.
> a ledger, like a spreadsheet but simpler, hasnt 'crumbled' in a hundred years despite being as basic as it gets.
Yet, for many reasons, your bank does not run your account with a spreadsheet.
> Sounds like your idea of simple is just bad code that is unfit for its purpose
Not quite. Simple is good. Do simple. But some things cannot be achieved with familiar tools. Sometime it is simpler to use an abstraction that is difficult to grasp, initially, than to write piles of code "the way we are used to" because we are afraid of "making others think".
When writing code you have the motto "don't make me think" in mind, but how to know what's the maximum level of trickiness for readers? There are familiar techniques and idioms when it is your main programming language, but they are not for someone using this language on the side.
In any case, neither code nor comments should be tutorials. To a reasonable extent, it is up to the reviewer to do their homework or just ask. Then based on that interaction you can add a comment or a parenthesis, or uncompress a bit the code. But not to the point that it means to "dumb down" things, because it is a downward spiral.