1

A module app.js includes another module service.js. The service.js module/file contains some functions but also does some module scoped initialisations(registry variable).

// service.js

const registry = database.connect()

function getItems(){
 const items = registry.getItems();
 return items;
}

function doSomethingElse(){
 //do something
}}

To my opinion module scoped initialisation outside any object/function is an antipattern as it can lead to unexpected results, f.e. importing service.js to another module in order to use the doSomethingElse function, which does not need the database connection, but having a database connection created as an unwanted side effect.

So, is this considered a bad practice? If yes, is there a name for this antipattern?

1
  • Well, it would be pretty awful to connect to a database as a side effect of importing a module. However, sometimes the side effecting code simply ensures that preconditions are met. A classic example is a polyfill, which absolutely should have such an initializer. Jul 13 at 21:35

1 Answer 1

1

I see three issues with static initialization:

  1. Global Variables.
  2. Complex initialization order.
  3. Unexpected error conditions.

Most initialization code is going to store some values (config parameters, DB connections, etc) into global variables. There are many other questions about global variable usage, I would say the summary is global variable are generally bad, but there are exceptions and initialization is often sighted as one of the exceptions.

Depending upon your language it is not always obvious the order initialization code runs:

  • Sometimes all the code runs before main.
  • Sometimes initialization code can run when something is loaded (after the app proper has started).
  • And when multiple items are loaded/referenced the order of initialization between them can be unclear.

In Java if a static initializer throws an exception, that exception will propagate back up the call stack - however a second reference to the class will result in a ClassNotFoundException - this is simply an example of a weird situation that can occur when initialization goes wrong - unfortunately it needs to be handled in more places when the initialization order/sequence is non-obvious.


So there are certainly issues associated with distributed/static initialization - however if you make initialization explicit (every class library etc has an initialization function that must be manually called) you run the risks of not initializing something or initializing items out of order.

I suspect (no evidence for this) that a lot of static initialization creeps in simply to allow sane defaults to be added so that other developers can get started quickly with libraries/frameworks.

In summary, I would suggest avoiding static initialization in your own code, but I wouldn't freak out about it too much in standard frameworks/libraries.

Your Answer

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

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