
Vim plugin to disapprove deeply indented code - danjoc
https://github.com/dodie/vim-disapprove-deep-indentation
======
dheera
... and then people just "solve" the problem by not indenting at all.

Seriously though, it's super hard to avoid deeply-indented code in some
languages ( _cough_ Java, JavaScript).

    
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(someCrap != null) {
                PendingResult<MessageApi.SendMessageResult> pending = Wearable.MessageApi.sendMessage(mGoogleApiClient, mPhoneNode.getId(), path, data);
                pending.setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
                    @Override
                    public void onResult(MessageApi.SendMessageResult result) {
                        runOnUiThread(new Runnable() {
                            ....

~~~
platz
"Bulldozer code" \- gives the appearance of refactoring by breaking out chunks
into subroutines, but that are impossible to reuse in another context (very
high cohesion)

~~~
golergka
Subroutine that is only used in one place still improves readability: instead
of a bunch of statements, you have a name, explicit parameter list and a
retugn value.

~~~
platz
it's not when applied once, it's when something that can be understood more
easily "locally" is exploded into a billion such pieces - then you have to
mentally find all the call sites and usages to mentally build the call graph
back up — you still have to understand how the whole ensemble works and
bulldozing can (but not always) make understanding the ensemble more difficult
especially if done by a poor programmer has the effect of obfuscation rather
than clarification.

~~~
patmcguire
It's good when it gives a name to what you're doing.

connection = establish_connection_given_these_conditions(cond1, cond2)

Vs the many lines of checking, creating the ConnectionFactory, passing in the
the conditions to the ConnectionConditionFactory, and generally having a new
statement every time you want to blow your nose. What were we doing again? I
dunno.

I've used it. I'll defend it. It's better than comments when done properly as
above.

~~~
barrkel
What's the difference between cond1 and cond2 parameters? Can they be swapped?
If cond1 and cond2 are booleans, they're almost indecipherable at the call
site. Why not cond1 && cond2 (or symbolic equivalent)?

Abstracting away the gruntwork of your connection factory and your connection
condition factory into a couple of separate routines - those are resuable bits
of code, they'll let you write this code at a higher level of abstraction
using reusable abstractions. But pushing the ugly wiring into a non-reusable
black box and pretending it's better design - bullshit.

~~~
patmcguire
Good point on the conditions. I wanted to avoid pasting prod code I'd been
working on and was trying to make an example: I generally use this for things
like logging.

It's best when:

1) The logic is very specific to the situation and isn't reusable 2) Isn't
important to the function's api contract.

------
K0nserv
Cyclomatic complexity[0] is a decent proxy for indentation level all though
not all indentation increases cyclomatic complexity and not all increase in
cyclomatic complexity increases indentation. However for the purpose of
reducing complexity it is wonderful. The ruby community is fairly good at
using Rubocop[1] to enforce number of lines in methods and cyclomatic
complexity. I've found that limiting yourself to 10-20 lines per method and a
cyclomatic complexity lower than 7-10 is very beneficial to code quality and
perceived complexity. Those numbers obviously need to tweaked to suite the
language, but work well for ruby.

Often this does involve pulling out blocks of code into a methods that's only
called once, but as discussed elsewhere in the thread this is still an
improvement in perceived complexity and readability.

0:
[https://en.wikipedia.org/wiki/Cyclomatic_complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity)
1: [https://github.com/bbatsov/rubocop](https://github.com/bbatsov/rubocop)

------
mnarayan01
So looking at the example, you can avoid one level of indentation by doing
e.g.:

    
    
      if (items === null) { return 0; }
    

at the start. Which is fine if that's the preferred style, _but_ if it is,
then you should do it regardless of how deeply nested the dependent stuff is.

~~~
mplewis
Yep! That's happy path/golden path/line of sight programming, and it's
awesome.

[https://medium.com/@matryer/line-of-sight-in-
code-186dd7cdea...](https://medium.com/@matryer/line-of-sight-in-
code-186dd7cdea88#.m3qqyv35i)

~~~
moonshinefe
Nice, I didn't know there was actually a name for it. My 15 years of coding
experience has just taught me it's the far better way to code.

It's one of my peeves to be following code paths and oh look, now we're in a
situation where it's if (OK) { if (OK) { if (OK) { if (OK) { ... } } } } and
I'm trying to remember what all the conditions were to get here since it's
long since scrolled off the page. I always find myself thinking "why, why
didn't you just return way up there!?"

~~~
shthed
other names for it:

[http://wiki.c2.com/?ArrowAntiPattern](http://wiki.c2.com/?ArrowAntiPattern)

[http://thedailywtf.com/articles/Coding-Like-the-Tour-de-
Fran...](http://thedailywtf.com/articles/Coding-Like-the-Tour-de-France)

------
hodgesrm
Sorry to be cynical, but this sounds as about as useful as Microsoft Word
syntax checkers that draw green lines under perfectly valid sentences.

~~~
hackuser
I was helping someone edit a book, and that syntax checker came in very handy.
There were indeed many false positives, but it provided a much smaller search
space for my eyes than 'every word on every page'. (I did read every word, but
the ones with the green lines under them got extra focus that was not going to
be available for 200+ pages.)

~~~
oblio
I also love how the very people who can spend tens of hours on configuring
vim, emacs, bash, zsh or their IDE can't be bothered to spend 5 seconds
disabling the Office spellchecker if it bothers them so much :)

------
hackuser
Does anyone know a good plugin that will provide faint vertical lines so I can
see where the indents line up (as described below)?

Someone I know used something called Cream, which they said was Vim with a
simplified GUI-based interface (I know; what's the point?). But it had one
nice feature: If you indented a line, then Cream would draw an unobtrusive
vertical line, extending down from the indent's left-most character (I forget
how far the lines extended or what that logic was, but they went far enough to
be useful). You could easily see how many tabs 'in' you were and line up a
current line with one (not directly) above.

~~~
cmcginty
I think you're looking for
[IndentLine]([https://github.com/Yggdroot/indentLine](https://github.com/Yggdroot/indentLine))

I also use the following options in my vimrc:

    
    
      " set indentline style
      let g:indentLine_char = '│'
      let g:indentLine_color_term = 66
      let g:indentLine_color_gui = '#4f5b66'
    
      " fix performance issue with long lines
      let g:indentLine_faster = 1

~~~
hackuser
Excellent, thanks.

------
htor
This plugin made me laugh! Those disapproving eyes.

Might go crazy if using this while developing though.. (stop harassing me,
EDITOR)

------
lomereiter
Nice idea, but I'm afraid those who are too lazy to structure their code are
not likely to give Vim a chance either. A plugin for a popular IDE would be
more beneficial.

~~~
watwut
I have opposite experience. People with good IDEs (idea, visual) were more
likely to structure the code while people with weaker IDEs (vim, sublime) less
likely. Mostly because weaker IDE does not navigate code that well and jumping
from call to definition requires more manual scrolling.

In the extreme, with pure text editor, you want all details together where you
effortlessly see them. Helper function means manual search and scroll.

~~~
andrewshadura
Helper functions mean one key press to jump to their definition and another
one to jump to their declaration, and one more to jump back.

~~~
watwut
Yes, when you have full blown IDE and use typed language. It is somewhat
weaker when you have full blown IDE and use something like javascript (e.g.
which find function from gazimillion find functions in project was it supposed
to be)?

It is really weaker with sublime or vim, at least from what I have seen. They
often did not found right function even when it was in the same file and there
was no ambiguity - leading to harder to read code with deep nesting and
loooong functions (that really should have been split into named steps).

It does not do that at all when vim user did not bothered to configure right
plugins or did not bothered to learn them.

~~~
sbov
It's funny because I went from vim to intellij a year ago and recently tried
out sublime text, and found my intellij code to be worse than my vim code.
Mostly because intellij's auto complete and easy "go to implementation" makes
up for (and can cause, if you aren't aware of the problem) a lot of quality
issues - things you can't ignore in vim unless you want an codebase you won't
be able to easily change.

I would gather that sublime text pushes you towards more focused, tight code,
because their auto complete isn't context aware.

To your specific point, helper functions should be as close as possible to the
function it is helping. If you have easy "go to function" functionality, some
people will slack off on this.

~~~
watwut
I found the "tight" code collegues generated (quite possibly much different
then yours) harder to read. It was pretty much impossible to read high level
overview of what was supposed to happen without having to go through all the
low level details. When things were split into smaller functions, I could come
to unknown code and read it fast. Reading what it is supposed to do from vim
written code took much more time. It was harder to mentally split it into self
contained pieces that means something.

Refusal to use helper fuctions also led to a lot of code repetition in various
(especially on click) handlers. When you have bugs from people forgetting to
change fourth place where pretty much same thing is done, then the code is
bad.

We had deadlines and I really think that everything would be way more
effective if we took advantages of ide and generated code that express intent
better and is composed of smaller units. Instead everything took longer and
complexity was pretty much unmanaged (since they refused to use helper
fuctions they never learned how to use then effectively nor how to effectively
modularize code - the codebas was fine while small and increasingly
unmanageable as it grew).

------
vomitcuddle
Never needed a plugin for this, just `:set tw=79`

------
shultays
Reminds me of this emacs plugin, deldo:

[https://youtu.be/D1sXuHnf_lo?t=2m57s](https://youtu.be/D1sXuHnf_lo?t=2m57s)

Slightly NSWF.

------
tribune
Clever idea but I tend to disapprove of using things like this in practice.
Formatting (or rejection of poor formatting) should be handled in CI.

~~~
falcolas
If you wait for CI, you're adding time to the feedback loop. This is, imo, a
bad thing since it interrupts The Flow to go back to previously written code
to fix it. By the time I commit, I've already evicted that stack from my
mental model; I'd rather not have to go back and rebuild it 5 minutes later
when the build breaks.

~~~
mikewhy
So run the linter locally, either on-demand or using git hooks in addition to
CI?

~~~
falcolas
Which is pretty much exactly what this tool is doing...

------
jlebrech
I'd like a language that designed to have zero indentation and you wire things
up graphically from those subroutines you've created.

~~~
TorKlingberg
Try LabView. It is graphical programming and you can make literal spaghetti
code. It has problems, like diff and merge is very hard.

~~~
msoucy
It's also good at making extremely simple things incredibly complex... but
then provides some high level "functions" to do weirdly specific things.

------
joe563323
The problem is not in the code you write, in the code you have to extend or
maintain.

