3

Without getting into specific language or implementation:

  • The value of the variables are not known until runtime.
  • All instances of this class will need this variable.

The obvious solutions:

  • Use a static variable that I set before I start using that class, but this feels messy because any user would have to remember to initialize before using.

  • Put the calculation in the constructor. Cleaner, but also wasteful because the value gets recalculated every time. In my case this calculation is very slow and it does cause a noticeable performance difference.

Is there a better way to deal with this than these two methods?

1
  • What about static constructors ? Does your language support these ?
    – Machado
    Commented Jun 6, 2017 at 19:35

4 Answers 4

5

Some languages have constructs just for performing once only calculations. Java has static initializer blocks1. C# has static constructors. Other languages may have similar constructs.

These consist of code that is called either at program startup or when the first instance of the object is created. They usually cannot be called directly, which means you cannot pass parameters. If you require parameters, you'll either have to change your design to remove that requirement or use a different method.


1Java also has non-static initializer blocks, also known as instance initializer blocks. They're similar, but run every time an instance of that class is created, rather than just the first time. The benefit being that they can set instance fields.

1
  • +1 on this, static constructors or even singletons would do. Even a simple IF on the non-static constructor would solve the problem.
    – Machado
    Commented Jun 6, 2017 at 19:37
5

Static variables are fine if used for constants, which includes constants whose values are calculated at run time but do not depend on any input. Static variables might also be OK if they are only used within a class.

Once static variables become part of your external data flow, you might run into a number of problems:

  • Initialization order between multiple classes. If you can't guarantee that this field is initialized before the class can be instantiated, you might potentially crash your application. This is especially dire in C++ where segfaults will ensue.

  • Testability. With static variables, you can't test one object in isolation. You have to think about the whole group of objects that interact with the static variable.

  • Coupling. If external code interacts with this static variable, this code is tightly coupled to that class. This makes it harder to evolve the code base over time.

  • Correctness. If external code sets the variable, they might set nonsense. The correctness of the class now depends on the correctness of all its clients, which is undesirable.

I can see two reasonable solutions to this: Lazy initialization, or instantiation via a factory.

With lazy initialization, the constructor would initialize the value, but only if it is currently uninitialized. How this must be done correctly depends on the language, especially if this initialization must be threadsafe. If I remember correctly, the “lazy singleton initialization dance” would look something like this in Java:

private static volatile Thing variable;

Constructor() {
  if (variable == null) {
    synchronized(Constructor.class) {
       if (variable == null)
         variable = initializeVariable();
    }
  }
}

But don't quote me on it…

With a factory, we can fully avoid global variables. The initialized value now is stored in the factory object, and it is passed to each created instance as a dependency in the constructor. Any code that wants to instantiate objects of your class must be given the factory. The code shouldn't create a new factory each time, because that would recalculate the value again.

private Thing variable;

private Constructor(Thing variable) {
  this.variable = variable;
  ...
}

public static class Factory {
  private final Thing variable;

  Factory() {
    variable = initializeVariable();
  }

  Constructor create() { return new Constructor(variable); }
}

In Java we'd use a nested public static class Factory, in C++ probably a friend class Factory instead. I don't know the appropriate C# idiom.

If you are using a dependency injection framework, explicitly writing the factory can likely be avoided. Instead, you'd declare the expensive to calculate instance field, and wire it up to your framework so that it can be filled in automatically. Then, you create some function that can provide this dependency. The framework probably has some singleton mode so that the function is only invoked once.

1

In C/C++, using function static variables allows you to:

  1. Initialize a variable once.
  2. Initialize a variable before rest of the function gets executed.

In C++, you can use such a variable in the constructor of a class.

MyClass::MyClass()
{
   static ExpensiveToComputeData data(... arguments to the constructor ...);

   // Rest of the code to properly initialize MyClass.
   // Anything from "data" above can be used to initialize MyClass.
}

You'll have to make sure that the constructor of ExpensiveToComputeData takes care of reading/computing the data.

This assumes that the important data from ExpensiveToComputeData is available to MyClass.

0

You will have to calculate the values at some point, right? So you want to pick the best time and place.

Does every instance of the class need its own set? If not, you can use the static constructor and use static variables.

Do you need the results right away after construction or only after some method is called? If you do not need them instantly, you can start a thread in the constructor and have the results calculated asynchronously.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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