9

I have a public class, which needs 7 parameters to be passed down. At the moment, I am able to make 3 of them being passed to constructor and another 4 to a public method in the class . Like this:


Public Class AClass{
    private XClass axClass;
    private String par4;
    private String par5; 
    private String par6;
    private String par7;

    public AClass(String par1, String par2, String par3){
       aXClass = new XClass(par1,par2,par3);
    }

    public execute(String par4,String par5, String par6, String par7){
       //this is needed because they are used in other private methods in this class
       this.par4 = par4;
       this.par5 = par5;
       this.par6 = par6;
       this.par7 = par7;

       //call other private methods within this class. 
       //about 7 lines here
    }

}


My question is, is this the right way to ask client of the class to passing in paramters?

sarahTheButterFly
  • 1,894
  • 3
  • 22
  • 36
  • I think what you should be passing to constructor depends on the situation.Can you explain in detail what AClass and XClass does and what these 7 parameters are ? – Emil Nov 25 '10 at 05:11
  • 1
    "If you have a procedure with ten parameters, you probably missed some." -Alan Perlis :-) – missingfaktor Nov 25 '10 at 05:43

8 Answers8

15

There shouldn't be anything stopping you from passing 7 parameters to a constructor, if that's what you want. I don't know if there's a maximum number of parameters that can be passed to a method in Java, but it's certainly higher than 7 if there is a max.

When you create a class and its public methods, you're creating an interface on how to use and access that class. So technically what you've done so far is correct. Is it the "right way" to ask the client of a class to pass in arguments? That's up to you, the designer of the interface.

My first instinct when I saw 7 parameters being passed was to silently ask "Is there some relationship between some or all of these parameters that might mean they'd go together well in a class of their own?" That might be something you address as you look at your code. But that's a question of design, not one of correctness.

duffymo
  • 305,152
  • 44
  • 369
  • 561
Marvo
  • 17,845
  • 8
  • 50
  • 74
  • Good answer. There is no "right way", no clearly superior choice. You have to use your best judgment. – John Kugelman Nov 25 '10 at 00:45
  • 1
    As all the 7 parameters are Strings, if they are all in constructor, won't that confuse people? If I create a dummy data object which just has setter and getter for the 7 parameters, client has to know about this data type, is it right approach just for this purpose? – sarahTheButterFly Nov 25 '10 at 01:05
  • Oh, absolutely, it might confuse people. But that's a design issue as opposed to a technical one. That's why I suggested you look at what those parameters are, and see if there's some way of encapsulating them into another class. For instance, maybe all seven are players on some team. Then you might find it makes more sense to create a Team class with a list of player names inside it, and then pass an instance of Team rather than multiple strings of player names. – Marvo Nov 25 '10 at 01:32
14

I'd go for the Builder Pattern instead of many constructor parameters as suggested by

Effective Java Item 2: Consider a builder when faced with many constructor parameters

Here's a simple class to illustrate:

public class Dummy {

    private final String    foo;
    private final String    bar;
    private final boolean   baz;
    private final int       phleem;

    protected Dummy(final Builder builder) {
        this.foo = builder.foo;
        this.bar = builder.bar;
        this.baz = builder.baz;
        this.phleem = builder.phleem;
    }

    public String getBar() {
        return this.bar;
    }

    public String getFoo() {
        return this.foo;
    }

    public int getPhleem() {
        return this.phleem;
    }

    public boolean isBaz() {
        return this.baz;
    }

    public static class Builder {
        private String  foo;
        private String  bar;
        private boolean baz;
        private int     phleem;

        public Dummy build() {
            return new Dummy(this);
        }

        public Builder withBar(final String bar) {
            this.bar = bar;
            return this;
        }

        public Builder withBaz(final boolean baz) {
            this.baz = baz;
            return this;
        }

        public Builder withFoo(final String foo) {
            this.foo = foo;
            return this;
        }

        public Builder withPhleem(final int phleem) {
            this.phleem = phleem;
            return this;
        }

    }

}

You would instantiate it like this:

Dummy dummy = new Dummy.Builder()
                    .withFoo("abc")
                    .withBar("def")
                    .withBaz(true)
                    .withPhleem(123)
                    .build();

The nice part: you get all the benefits of constructor parameters (e.g. immutability if you want it), but you get readable code too.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • 1
    You need to add a check on the build() method to validate all "mandatory" parameters were set, in order to be strictly equivalent to a constructor with 7 parameters (ie: make a difference between a user setting "null", and the "null" default value). That's the downside of this solution imho. – naab Jun 30 '16 at 15:11
  • 1
    @naab these days, I'd use the https://immutables.github.io/ framework for generating the builders. It adds this functionality out of the box, by default – Sean Patrick Floyd Jun 30 '16 at 15:52
1

Can't you just make a class/hashmap that stores these parameters and pass this to the function?

public excute(Storageclass storageClass){
       //this is needed because they are used in other private methods in this class
       this.par4 = storageClass.getPar4();
       this.par5 = storageClass.getPar5();
       this.par6 = storageClass.getPar6();
       this.par7 = storageClass.getPar7();

       //or
       this.storageClass = storageClass;
    }
Mark Baijens
  • 13,028
  • 11
  • 47
  • 73
1

I don't really see the problem with that.

In any case you could create a "Request" object or something like this:

class SomeClass { 
     private String a;
     private String b;
     ....
     public SomeClass( Request r ) { 
        this.a = r.get("a");
        this.b = r.get("b");
        ...
     }

     public void execute( Request other ) { 
         this.d = other.get("d");
         this.e = other.get("d");
         ...
     }
}

See also: http://c2.com/cgi/wiki?TooManyParameters

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
1

Without knowing the use of the child class, I can say that there is nothing inherently wrong with what you have done.

Note though that you have to declare

private XClass axClass;

in the variables of your AClass.

However, you say 'I am able to make....' Does this mean there is some problem with declaring this another way?

KevinDTimm
  • 14,226
  • 3
  • 42
  • 60
  • Thanks Kevin for noticing that. I've edited it. There is no problem with declaring all of them in the constructor. What I meant was, I managed to split them into 3 and 4. – sarahTheButterFly Nov 25 '10 at 00:46
1

I don't care for it much, because an object should be 100% ready to be used after its constructor is called. It's not as written in your example.

If the parameters passed into the execute method can simply be consumed, and that's the method of interest for clients, I see no reason for them to be data members in the class.

Without knowing more about your ultimate aims it's hard to tell. But I would re-think this implementation.

duffymo
  • 305,152
  • 44
  • 369
  • 561
1

If you're planning on introducing an AClass.someMethod() that needs to know par4-7 without requiring you to have called AClass.excute(), then clearly you should be passing the parameters in the constructor.

On the other hand: if you can construct an instance of this object with only par1-3 and do something meaningful with it besides call excute() then it makes sense to allow the object to be constructed with fewer than the full seven parameters.

Yet my own aesthetic is to try and limit the number of "modes" that an object can be in which make certain methods work and others fail. So ideally, a fully-constructed object is ready to run any method the programmer might call. I'd worry about the design issue more than be too concerned about the sheer number of parameters to the constructor.

But as others have pointed out, sometimes there is a natural grouping of these parameters which can deserve objects of their own. For instance: in many APIs instead of passing (x, y, width, height) all over the place they use rectangle objects.

  • Also: is your spelling of http://en.wiktionary.org/wiki/execute intentional or unintentional? Ordinarily I'd just assume typo not worth mentioning, but I just saw a minute ago a method called subGridRowColapsed that made it into the jqGrid API... gotta doublecheck. http://www.trirand.com/jqgridwiki/doku.php?id=wiki:subgrid&s[]=expand – HostileFork says dont trust SE Nov 25 '10 at 01:05
1

As others already wrote, it is technically correct to pass 7 parameters, although not very 'user-friendly', if you can say so.

Since you didn't write much about this class, I can suggest one small thing: in constructor you're just creating XClass object, so it would be sane to create this object before and pass it as a single parameter.

Something like this:

...
XClass aXClass = new XClass(par1, par2, par3);
AClass aClass = new AClass(aXClass);
...

And this is the constructor:

public AClass(XClass aXClass) {
       this.aXClass = aXClass;
}
Zhukikov
  • 118
  • 5