Domanda

RequireJS dependencies are expressed as a partial order... which is great! Every module can specify exactly those dependencies it needs and no more. Particularly, there is no need to specify a linear order between all modules.

An oft mentioned problem with this is the possibility to accidentally specify circular dependencies. I'm now running into what you might call the opposite problem. Say I have three modules, A, B and C:

define('A', [],    function () { ... });
define('B', ['A'], function () { ... });
define('C', [],    function () { ... });

The actual loading order between such modules is non-deterministic. In this case there are three possible loading orders: ABC,   ACB, and CAB. The dependency structure ensures that A is always loaded before B.

Now imagine that at some point, module C becomes dependent on A too, but I forget to specify this in the module header. This would be very difficult to detect. Two-thirds of runs (assuming all orders are equally probable) won't manifest any problems, because by pure chance, A happens to load before C as intended. But in one third of cases, an error message (or worse, incorrect behavior) will occur.

This problem would not exist if all modules return a value as their only interface. Then a very clear error message would be presented by the absence of the corresponding function parameter. But in reality, many modules just add or change something by accessing the global state or by modifying state through their own dependency links. This is the case, for example, with AngularJS directives and services.

Question: What is a good way to prevent this situation from occurring, or to debug it when it does?


The answer given by Louis is, I think, the 'proper' way to go about it for large projects with rigorous testing practices. But I was looking for something simpler. For example:

  • a coding convention that guarantees proper dependencies by construction
  • a tool that runs all possible loading orders and then checks that the resulting states are equal
È stato utile?

Soluzione

Design your unit tests so that they start from a state where no modules are present, and do not load the whole app but only the module under test. Loading this module will cause its dependencies to be loaded. If a dependency was forgotten, then the tests should fail.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top