Nobody writes code like the op though (I'm pretty sure it's satire)
That and the fact most of the community started out with similar ideas on good code, so there was less bikeshedding around formatting.
Formatting could be beneficial, but it gets abused so fast that it becomes a problem.
First thing, no one challenges the choices made by the formatter, which is a problem in the long term. The other thing is how far the formatter goes. Rubocop in ruby is a clear example of this, they went way too far with it and producing a readable rspec test is impossible without violating at least one of the rules.
A few days ago, I ended up writing something along these lines:
```
def something err, obj1 = dependency1.call(someargs) return err, obj1 if err.nil?
err, obj2 = dependency2.call(obj1)
return err, obj2 if err.nil?
err, obj3 = dependency3.call(obj2)
return err, obj3 if err.nil?
err, obj4 = dependency4.call(obj3)
return err, obj4 if err.nil?
err, obj5 = dependency5.call(obj4)
return err, obj5 if err.nil?
[nil, obj5]
end```
This is a pipeline, to a human being it looks simple because the "return line" after reading the first time and understanding it's an early exit in case of errors, it's identical in all 5 steps. Human brain just excludes those returns after having read the first one.
Rubocop however claims that there is too much complexity going on here due to 5 if branches. That's a machine reading the code.
If I have to rewrite the code according to rubocop standards, it ends up being a lot less readable and with a lot more indirection for no particular advantage.
I find it funny, we use styleguides to ease human interactions with code, but we let the machine evaluating that. It's problematic, the machine doesn't see the code as us.
Correct me if I'm wrong but I think there are 1 (and a half) other ways you could write it - that don't result in branching
1:
def something(args) do
with {:ok, obj1} <- depencency1.call(args),
{:ok, obj2} <- dependency2.call(obj1),
{:ok, obj3} <- dependency2.call(obj2),
{:ok, obj4} <- dependency2.call(obj3),
{:ok, obj5} <- dependency2.call(obj4)
do
{:ok, obj5}
else
{:error, msg} -> {:error, msg}
end
end
1.5: Use a try/rescue block where you match {:ok, obj} and then catch Match errors.mix format is not a linter it’s a formatter.
The complexity rules have always struck me as being of a whole different category thnan Rubocop's other rules. As you note, they're especially frustrating in tests.
Edit: by "the complexity rules" I mean https://www.rubydoc.info/gems/rubocop/0.27.0/RuboCop/Cop/Met..., rather than the ones about variable naming, line length, etc.