0

I would like to know if there are advantages to setting an object's properties after construction as opposed to in the constructor.

I am using objects with properties which are expensive to create so it seems to me that I should set the properties after the object is created. However, when using the objects I have to question whether the property has been set when I would prefer to assume that it is set.

Specifically applying to my problem: Let's say we have a User object with a friendslist property (array of Users). If the friendslist property had to be set then each 'friend' User would have to be initialized with its own friendslist.. and this would go on forever? But, it seems as if a friendslist fits as a property of User - so do we separate friendslist from User or set friendslist optionally later?

Would appreciate any insight on the matter, thanks.

Tito
  • 832
  • 10
  • 24

2 Answers2

0

Ideally objects should not have invalid state, so building the object directly into the configured state should be preferable.

However, you will run into the specifics of the language you use. For example, in C++ for instance there are two forces that will push you against this:

  • the problem of exceptions from constructors. Function-try blocks help, but they tend to be on the esoteric side and many developers are not aware of them.
  • proliferation of many complex signature constructors for classes, making difficult to asses which one is the right one.

Other language can do some syntactic sugar that mask the problem. Eg. C# has the object initializer construct like new A() {foo="x", bar="y";} which make it hard (not impossible!) to use an object in intermediate, uninitialized state.

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • Let's say we have a User object with a friendslist property (array of Users). If the friendslist property had to be set then each 'friend' User would have to be initialized with its own friendslist.. and this would go on forever? But, it seems as if a friendslist fits as a property of User - so do we separate friendslist from User or set friendslist optionally later? - will add this to my q. – Tito Oct 28 '13 at 14:22
  • Apples and Oranges. [Lazy loading](http://en.wikipedia.org/wiki/Lazy_loading) vs. Eager loading is a **very** different question. Read about the [Proxy pattern](http://en.wikipedia.org/wiki/Proxy_pattern). – Remus Rusanu Oct 28 '13 at 14:26
  • The concept of lazy loading is interesting, but surely lazy loading causes the object to set its own properties? – Tito Oct 28 '13 at 14:32
0

I generally choose to initialize all the properties of the object in the constructor. Here is my reasoning:

You can't accidentally set some of the properties of the object and now the other, in pseudo code:

obj = new Obj(prop_a, prop_b, prop_c) // Error if not all three properties are set
method_requiring_all_three_values_are_initialized(obj)

vs

obj = new Obj() //No error, becuase constructor doesn't take the arguments
obj.set_prop_a(val);
obj.set_prop_b(val_2);

method_requiring_all_three_values_are_initialized(obj) // Runtime error

Also, if the object is immutable (you can't modify it after constructing it,) your code will be easier to maintain because you don't always have to worry about the state of the object. See Mutable vs immutable objects

However, if after profiling your code and early initialization of the object's properties becomes a clear bottle neck, you can refactor your code to initialize later as an optimization, and I'm sure you've heard the Donald Knuth quote:

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil"

For your specific problem, I would separate friendslist from User because it would make User objects easier to reason about (you don't have to worry about what state it is set to, or if the properties are well defined, you just know that a User is a User...) You can have a single data structure and function that takes a User object and returns its corresponding friendslist.

Community
  • 1
  • 1
DJG
  • 6,413
  • 4
  • 30
  • 51