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.
> 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)
You might choose to add comments and let the logic unfold in a less succinct way in order to improve readability and understandability.
You might also consider your colleagues’ limited cognitive reserves, some of which could be spent on more important issues.
* 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
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.
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.
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.
This 100%
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.
Just remember that, at some point, the "dumbass" thing was pushing sticks into clay tablets.
Functional programming may not be the future. But dismissing other's code because it is not done "the way we are used to" is stupid.
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.
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.
But, at some point, spreadsheets crumble and become unmaintainable. And so does "basic" code.
Should people keep on using spreadsheets ? Depends.
Case in point, a ledger, like a spreadsheet but simpler, hasnt 'crumbled' in a hundred years despite being as basic as it gets.
Simple is good when it's fit for purpose.
Sounds like your idea of simple is just bad code that is unfit for its purpose. Theyre not the same thing.
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".
Please make me think, but only if it is worth it.
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".
We need to have a basic level of competency.
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?
Why not? To take the example from the article:
def userCoworkers(u: User): List[Employee] =
u.departments.flatMap(_.employees)
Why not add a comment like: // 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.
But only the author(s) can capture why it exists via commenting.
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.
You name the fields currency and amount and have the business logic rejecting invalid pairs.
You should use a currency type for the other issue, not an integer.
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.