Many (most?) AngularJS folks seem to advocate for breaking AngularJS apps up into many modules.
Brian Ford in his blog already states that packaging by layer (controller, service, etc.) is a “silly” notion, so I won’t even go there. (See http://briantford.com/blog/huuuuuge-angular-apps.)
But let’s suppose that you modularize an app by feature. Perhaps you have a users module and a messages module, along with the standard app module to load these feature modules. You thoughtfully place the routes related to user functionality in the users module, and the message-related routes in the messages module. Now, in my mind, you’ve created a dependency in EACH feature module on ngRoute. So each module should list “ngRoute” in its array of dependencies, right?
Unfortunately, AngularJS makes it all too easy to screw that up. If your app module loads both users and messages, but only users lists “ngRoute” as a dependency, it doesn’t matter at runtime: $routeProvider will still be injected into your config function in messages, having essentially been resolved through the users module’s dependency on ngRoute.
My issue may be with the common pattern of an “app” module loading/referencing various feature modules. The pattern makes sense to me, as do transitive dependencies. What is problematic is that Angular’s particular implementation can mask cases where a module doesn’t reference its module dependencies even indirectly. The module may work in the context of a particular app (because the module is referenced by another “app” module that also happens to reference its dependencies directly or indirectly), but if you were to copy the module into another app, it would fail due to missing dependencies.
I get the impression that most folks wouldn’t give much consideration to the fact that the users module is now essentially a dependency of the messages module. However, it is an issue I have trouble looking past. To me, if we are likely creating these confusing dependencies between feature modules, it really diminishes the net benefit of modularization, and I would rather just have a single app module that encapsulates all components for all features in the app.
1
I would not advocate many small modules, their gain is too small. The angular module is really not much of a module system. They provide no real namespacing, they are not strict either, if some other active module ‘imports’ your dependency it will usually work (as you mentioned) etc.
Because of this it will not help you ‘document’ your dependencies per module, it will be incomplete.
Just stick to very coarse/large modules. I learned to mostly look at them as a dependency injection container configuration not so much a means to ‘componentize’. All these ‘modules’ usually violate YAGNI anyhow, as if you’d ever run the app without. Reuse considerations are mostly a promise that rarely ever delivers.
Nowadays I use TypeScript’s modules to partition my code. Angular module dependencies I largely reserve for true 3rd party stuff.