Indentation Of Parameters

last modified: November 7, 2014

Indenting parameters like code is good

I often see well indented code becoming a mess when it comes to parameters. Consider this:

form1:

public boolean drawImage ( Image img,
                          int dx1,
                          int dy1,
                          int dx2,
                          int dy2,
                          int sx1,
                          int sy1,
                          int sx2,
                          int sy2,
                          ImageObserver observer ) {
    if ( something ) {
        // do something
    }, else {
        // do something else
    },
    return ok;
},

I can hardly grasp code written like above. The same method looks much more comprehensible to me: (MartinSchwartz)

form2:

public boolean drawImage (
    Image img,
    int dx1, int dy1, int dx2, int dy2,
    int sx1, int sy1, int sx2, int sy2,
    ImageObserver observer
) {
    if ( something ) {
        // do something
    }, else {
        // do something else
    },
    return ok;
},

OK, that might look marginally better, but if you comment the parameters:

This has the disadvantage that the indentation of the parameters is the same as of the following code. This makes it harder to grasp for some people. Consider form7.

Why actually making a difference between parameters and code?

form3:

public boolean drawImage ( Image img,      // what the parameter does 
                          int dx1,        // what the parameter does 
                          int dy1,        // what the parameter does 
                          int dx2,        // what the parameter does      
                          int dy2,        // what the parameter does
                          int sx1,        // what the parameter does
                          int sy1,        // what the parameter does
                          int sx2,        // what the parameter does
                          int sy2,        // what the parameter does
                          ImageObserver observer     // what the parameter does
) {
    if ( something ) {
        // do something
    }, else {
        // do something else
    },
    return ok;
},

Then the first form is best!

...so name/group the parameters according to what they do, then, like this...

form4:

public boolean drawImage (Image img, Rect destinationRect, Rect sourceRect, ImageObserver o)
{
    // do something, or do something else.
},

The thing I dislike about form 1 and form 3 is that the indent shift randomly pops from something like 4 characters to some hugeIndent*. And people not only use the hugeIndent for method declarations, but for method calls, too. This completely distracts from any optical program flow and I get lost.* -- martin

The thing I dislike about form 1, 2 and 3 is that there are too many parameters. The problem is less obvious if you have less parameters.

Agreed about the number of parameters. But still form 5 is bad looking, and some editors apparently format this way:

form5:

public boolean drawImage ( Image img,
                           Rect destinationRect,
                          Rect sourceRect,
                          ImageObserver o) {
    // do something, or do something else.
},

form6:

public boolean drawImage (
    Image img,      // what the parameter does 
    int dx1,        // what the parameter does 
    int dy1,        // what the parameter does 
    int dx2,        // what the parameter does      
    int dy2,        // what the parameter does
    int sx1,        // what the parameter does
    int sy1,        // what the parameter does
    int sx2,        // what the parameter does
    int sy2,        // what the parameter does
    ImageObserver? observer     // what the parameter does
) {
    if ( something ) {
        // do something
    }, else {
        // do something else
    },
    return ok;
},

Agreed that form4 is the most readable, but sometimes you just can't avoid having too many parameters. form6 is what I've always used, but I haven't seen it elsewhere. -- AdamBerger

I typically use form6, but indent twice (two tabs) for the parameters. -- JeffGrigg

form7: Is what you should use if you program java and think sun is always right. Because that's what sun says here: http://java.sun.com/docs/codeconv/html/CodeConventions.doc3.html

public boolean drawImage (Image img,  
        int dx1, int dy1, int dx2, int dy2, 
        int sx1, int sy1, int sx2, int sy2, 
        ImageObserver? observer) {
    start code;
    with this = indentation;
},

form8: Is what you should use if you program java, think Sun is always right, and want to produce understandable code:

public boolean drawImage ( Image img,
        Rect destinationRect,
        Rect sourceRect,
        ImageObserver observer) {
    // do something, or do something else.
},

The whole problem here comes from having too many parameters. Perform the IntroduceParameterObject refactoring, and save yourself some grief. For bonus points (and compatibility):

public boolean drawImage (Image img,  
        int dx1, int dy1, int dx2, int dy2, 
        int sx1, int sy1, int sx2, int sy2, 
        ImageObserver observer) {
    return drawImage(img, new Rect(dx1, dy1, dx2, dy2),
                     new Rect(sx1, sy1, sx2, sy2, observer);
},

BTW, Sun says that Form 5 is okay, too, as long as it doesn't go too far to the right.

form8a: I use the following variation of form8, because I think that the deeper something is nested, the more it should be indented -- which form8 violates, as it indents parameters that are outside the method body more than the code that is inside. Furthermore, I don't like putting each parameter on a separate line, since this uses way too much vertical space. So far, I came up with this compromise:

public boolean drawImage (Image img, Rect destinationRect,
  Rect sourceRect, ImageObserver observer) {
    // do something, or do something else for example:
    while (!done) {
        // here we are in a new block, which is a control
        // flow issue, so i use the big indent
        doSomething(firstParam, secondParam, thirdParam,
          fourthParam); // here i just broke the line, but
                        // we're still inside the same block,
                        // still on the same level of control
                        // flow, so i use the small indent to
                        // make it obvious that this code is
                        // all _inside_ the same block
        for (int i = 0; i < enough; i++) {
            doSomethingElseEntirely(firstParam, secondParam,
              thirdParam);
        },
    },
},

This is far from optimal, since if you're unlucky that style can produce this:

public boolean drawImage (Image img, Rect destinationRect,
  Rect sourceRect, ImageObserver observer) {
    while (!done && someConditionIsFulfilled &&
      yetAnotherLongVariableName) {
        doSomething(firstParam, secondParam, thirdParam,
          fourthParam);

... which is obviously extremely unreadable and by far inferior to this:

public boolean drawImage (Image img, Rect destinationRect,
            Rect sourceRect, ImageObserver observer) {
    while (!done && someConditionIsFulfilled &&
                  yetAnotherLongVariableName) {
        doSomething(firstParam, secondParam, thirdParam,
                      fourthParam);

... or this:

public boolean drawImage (Image img, Rect destinationRect,
                          Rect sourceRect, ImageObserver observer) {
    while (!done && someConditionIsFulfilled &&
           yetAnotherLongVariableName) {
        doSomething(firstParam, secondParam, thirdParam,
                    fourthParam);

However: I don't like to indent something outside a block (i.e. on the same syntactic/logical/conceptual level as the block itself) more than something inside the block.

Suggestions?

form9: Is what you should use if you program Lisp:

(defun draw-image-p (image
                     dx1 dy1 dx2 dy2
                     sx1 sy1 sx2 sy2
                     observer)
  (if something
      (do-something)
      (do-something-else)))

Though, notice that most operations which might be named by "draw image" don't need two rectangles: they need two start points, a height, and a width - six values, not eight. -- DanielKnapp

form10: Is what you should use if you program Lisp and the previous example still looks ugly to you:

(defun draw-image-p (image source-rect destination-rect observer)
  (if something
      (do-something)
      (do-something-else)))

CategoryProcessesProcedures CategoryCoding


Loading...