4

Possible Duplicate:
Are there guidelines on how many parameters a function should accept?

I have got class with 30 variables (it is an application form), so I wonder what is the best practice to organize class creation.

Should I use huge constructor:

MyClass mc = new MyClass(a, b, c, d)

Or setters:

MyClass mc = new MyClass();
mc.setA(a);
mc.setB(b);
mc.setC(c);
mc.setD(d);

What is the best practice in OOP for such a situation? I saw a similar question, but I don't need immutability.

5
  • 4
  • 7
    C# gives you the best of both via its initializer syntax: MyClass mc = new MyClass { A = a, B = b, C = c, D = d };
    – Ant
    Jun 14, 2012 at 21:42
  • 7
    The answer is highly dependent on the programming language. Jun 14, 2012 at 22:08
  • Not enough information. We need to know the usage semantics. Is this really a class that encapsulates its properties or a simple property bag. Jun 14, 2012 at 23:26
  • Huh? I have built many GUI forms and I never had to supply more than 5 arguments. Can you give an example of what you are trying to do with names other than a, b, c, and d?
    – Job
    Jun 15, 2012 at 0:31

6 Answers 6

18

There is a Third Option that is the most Object Oriented Idiom

The best thing to do is to use the Builder pattern.

The class has an default no-arg constructor, and you set all the required parameters and then call .build() or .materialize() or some appropriately named method to validate and finalize the construction of the object and get return a reference to the completed object.

This can be used very successfully with the Fluent API design pattern as well.

Here is an example on how to enforce a Builder pattern API adherence to construct only valid objects. The blog post is about Java, but it applies to any statically type Object Oriented language that supports interfaces. It makes it very easy to know what you must do next with auto completion in an IDE as well.

I am not a big fan of the Fluent API pattern because it can be abused very easily, and when it abused the method chaining makes it very hard to diagnose exceptions, but in this particular case it is very appropriate.

23

The main difference between your 2 examples is that the user of the class is forced to use the constructor but not forced to set its state via set methods.

You should place all arguments in the constructor that will setup your instance in the correct state. Other 'setting' methods should be optional.

What I would do in your case is identify within your 30 variables comman themes that in themselves can be broken down into DTO's. So you might have instead (for example):

MyClass mc = new MyClass(personInfo, companyInfo, salaryInfo);

Addtionally you might want to look at whether your class is doing too much and whether you can limit the use of internal state by creating smaller component classes rather than having one large class.

1
  • Do you mean "can be broken down into Value Objects"? DTO is for other purposes.
    – Lombas
    Feb 23, 2021 at 18:39
10

The answer depends on how you use the class...

  • If you want your class to be immutable, you'll have to use constructor parameters.

  • If you want your class to be deserializable by relection based (de)serializers, you will need a default constructor and setters.

  • If your class isn't supposed to be immutable and you want consumers to be able to change all the properties during the objects' lifetime, then you will need to add setters anyway (or add modification methods, which may seem less straightforward to consumers).

  • If you do use the default constructor and properties approach, then you must make sure that the consumers can not invalidate the object's state by setting in an unexpected order, that default values are valid and that all the setters check things like ranges before applying the changes.
    If you have two (or more) dependant properties, either encapsulate them in a class, or make sure that if either of them is set (e.g. X is set), it changes the other's value (e.g. Y's value) if (Y's) current value doesn't not go together with the new value (of X).


Also, consider if your class really should be one class:

If it has 30 parameters, you may be breaking the OO principle of encapsulation - where each class does one thing and does everything for that one thing.

Perhaps you should be using composition of a few classes or, if you have a lot of common parameters between classes, perhaps you need one or more vertical classes that handles a specific aspect and can act on multiple classes (either using reflection or using additional classes in a visitor pattern).

1

I'd go with the huge constructor. It's simplest. If each call to the constructor uses different parameters (that is, you'd end up passing a lot of nulls), either make more constructors. The basic idea is keep the code to a minimum; make it as simple as possible. If you need to get real fancy setting values and the setters would be simpler, use them.

There's something sloppy about too many parameters, so you might want to see if you should be passing objects that each contain several parameter values. Don't strain yourself on this one, but if you've got 15 parameters, I betting you'll find a simpler way to do it.

Too many parameters are bad, but too many mindless setters aren't good either; there's no right answer. You have to choose the lesser of two weevils. This discusses setters better than I can.

0

I would ask yourself if you will ever really be constructing this giant object, or will it always be loaded from a database?

I cannot see any reasons to have an object this large constructed with values coming from code.

If this thing is always saved and loaded from a database or a file, give it a simple default constructor and focus on getting the object-database mapping or serialization correct.

3
  • it says right in the first sentence (it is application form) which implies it is coming dynamically from the end user, not some database input.
    – user7519
    Jun 15, 2012 at 0:47
  • @JarrodRoberson: Then it needs a GUI binding. Or it needs a HTML POST binding. Seriously, what would it use a constructor for?
    – Zan Lynx
    Jun 15, 2012 at 3:05
  • I'm with @Zan Lynx here. Not sure of the exact usage, but a constructor taking an HTML Node, a Map of key-value pairs, the raw string of key-value pairs, or similar would be a nice approach if possible.
    – user949300
    Mar 11, 2015 at 17:42
0

Assuming you're not in a language that makes it convenient to write named parameters (e.g., Python or Common Lisp), you should consider whether your objects are considered to be read-only or read-write. If the former, you must set values from the constructor, but otherwise it's really up to you as long as you have setters (or your language's equivalent). Given that you're dealing with 30 variables though, I'd really consider using something which would let you avoid having to write out constructors with that many arguments. Even 10 would be rather too many for sanity…

1
  • C# 4 also introduced named parameters.
    – Roman
    Jun 14, 2012 at 23:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.