7

I'm so confused. AngularJS requires services, controllers, and directives to be created within Modules. But those services, controllers, and directives can be injected into any other service, controller, or directive REGARDLESS of the module they exist within! Correct? And, I haven't seen any IDEs or tools that care about the module names... other than ng-app. So, WHY create multiple modules? Does creating modules actually have a benefit other than read-ability within the source code?

Example...

(function(module) {

    var dir = function(something) {
        return {
        };
    };

    module.directive("myDirective", dir);

}(angular.module("pointlessModuleName")));

I've tried finding the answer, but keep getting confused...
Multiple Module in Angularjs

Community
  • 1
  • 1
G. Deward
  • 1,542
  • 3
  • 17
  • 30
  • to separate out all the components like service, factory, controller,etc..Is the same as like namespaces in code which separate outs the modules – Pankaj Parkar Apr 09 '15 at 14:59
  • Sure, but nothing ever acknowledges the module. The IDEs don't care about the module name. Angular doesn't care about the module name. I can use services and controllers without ever specifying a module. So, what's the point? – G. Deward Apr 09 '15 at 15:02
  • Biggest benefit of multiple modules is code portability. Very easy to take one of your modules to another project or drop in modules found through any number of resources online – charlietfl Apr 09 '15 at 15:37
  • @G.Deward Angular does care about the module name. If you want to use anything from a 3rd-party library, for instance, you must first reference the library's module by its name. Saying you can use services and controllers without ever specifying a module isn't always true. – Michael Benford Apr 09 '15 at 16:43

3 Answers3

2

I was thinking the exact same thing, and decided to walk on the wild side and merge everything under one module. Of course, only to find out a few minutes later why that was not a great idea :) So I'd like to take the time to explain where I think modules play a very nice role, independently from "the general opinion".

I started out with something along the lines of:

// main.js - v0

var ServerData = require('./services/server-data')
var filters = require('./filters')

angular.module('ServerLoad', ['ngRoute'])
.factory('ServerData', ['$http', ServerData])
.filter('lastseen', function () {return filters.lastseen})
.config(['$routeProvider', function ($routeProvider) {
  $routeProvider
  .otherwise({
    redirectTo: '/servers'
  })
}])

Now I wanted to add a view that presents a list of servers. A view, in essence, is not much more than a combination of a controller with a route, so I added those to the code. Here is what I got (and then I'll explain why this is not so nice and how a sub module solves that):

// main.js - v1

var ServerListView = require('./views/server-list-view')       // <-- import view
var ServerData = require('./services/server-data')
var filters = require('./filters')

angular.module('ServerLoad', ['ngRoute'])
.factory('ServerData', ['$http', ServerData])
.controller('ServerListCtrl', ['ServerData', ServerListView])  // <-- add controller
.filter('lastseen', function () {return filters.lastseen})
.config(['$routeProvider', function ($routeProvider) {
  $routeProvider
  .when('/servers', {                                          // <-- add route
    controller: 'ServerListCtrl',                              //
    controllerAs: 'servers',                                   //
    templateUrl: 'assets/partials/server-list.html'            //
  })                                                           //
  .otherwise({
    redirectTo: '/servers'
  })
}])

Although this is certainly a valid set-up, what I don't like about it is that main.js defines the controllerAs and the templateUrl properties. To me it feels these properties really ought to be defined where the code that depends on that is defined --- './views/server-list-view', maybe even on the ServerListView class itself.

So, a bit in the same vein as your IIFE, I added a static method to ServerListView to add the view to the module:

// main.js - v2 (from v0)

var ServerListView = require('./views/server-list-view')       // <-- import view
// ...

angular.module('ServerLoad', ['ngRoute'])
// ...

ServerListView.setup(window.angular.module('ServerLoad'))      // <-- adds ctrl and route

and

// server-list-view.js - v2

function ServerListView (ServerData) {
  var scope = this
  // ...
}
module.exports = ServerListView

ServerListView.setup = function (module) {
  module
  .controller('ServerListCtrl', ['ServerData', ServerListView])
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
    .when('/servers', {
      controller: 'ServerListCtrl',
      controllerAs: 'servers',
      templateUrl: 'assets/partials/server-list.html'
    })
  }])
}

I thought this looked slightly better, but now the use of 'ServerData' bothered me. After all, it wasn't declared in server-list-view.js anywhere. Similarly, if the view would need some extra external module, I would have to edit main.js to add it. That feels out of place.

Then it occurred to me that, if I can write an IIFE to take module as argument, why not just let it take angular as argument? Then it can define its own module however it pleases and include all dependencies needed. Moreover, if you're still fanatical about single-module-everything, then just use the 'ServerLoad' module name and drop the dependency declaration. That is the only and whole difference!

// server-list-view.js - v3

// ...

ServerListView.setup = function (angular) {
  angular.module('ServerLoad.ServerListView', ['ngRoute', 'ServerLoad'])
  // ...
}

So, in conclusion, I think that the great advantage of using sub modules is not necessarily that others can reuse my code (I don't think anybody will ever be interested in my server list view), but that each bit of code can stand on its own, reusing other people's code, without requiring the main module to include all of that. The main.js stays lean while the server-list-view.js can pull in all sorts of stuff.

foot note. It still looks a bit odd having ServerLoad as a dependency (to reach the ServerData factory). In version 4 that factory will also live in its own sub module, of course ;-)

Paul
  • 766
  • 9
  • 28
1

As far as I know, the only reasons for having multiple modules is to satisfy code modularity, attain loose-coupling, and fulfill easy maintenance in the future.

For example, you could have an application module that depends on other modules that implement specific functional areas. These modules are unaware of anything external to themselves and should not care ideally.

Let's say you have a data repository module that includes services and factories that deal with REST APIs of some web service. You could basically reuse this module in multiple applications. It's plug-and-play essentially. Putting all of the services into a separate module that can be dependently injected is just a way to package it up nicely and make it reusable.

Your code example of module use isn't ideal in my opinion, nor would I qualify an IIFE as a module. I'd do something more like this:

angular.module('dataRepo', []);
// 'dataRepo' implementation left out for brevity

// create a new angular app that depends on the 'dataRepo' module
angular.module('myApp', ['dataRepo']);

Also, here's a good article you could take a look at. Scroll down to the section on grouping modules by functionality.

Brett
  • 4,268
  • 1
  • 13
  • 28
  • 1
    Sure, I get that. But I'm waiting for something to actually acknowledge the presence of the module. For example, in Java and C#, there is a namespace. IDEs only show what is available in the namespaces that have been included. I would assume a Module should work the same way. However, all of the IDEs I've used (WebStorm, Brackets, etc.) do not filter anything based on the included modules. And, the Module does not have to prefix anything when injecting a service or controller. It's as if the module just doesn't exist. So, what's the point? – G. Deward Apr 09 '15 at 15:19
  • 1
    @G.Deward You mean you're waiting for something besides a *human* to acknowledge the presence of a module. You seem overly dismissive of the readability argument, which you acknowledge in your question. – Dave Newton Apr 09 '15 at 15:29
  • 1
    I edited my answer to include a code example. It acknowledges the presence of the dependent modules by name when used this way. Not sure what you mean by IDE's recognizing the module name. Are you expecting intellisense support? – Brett Apr 09 '15 at 15:30
  • @Brett: Thanks for the update. I guess I'm looking for SOMETHING OTHER than readability. Putting extra syntax into a file is generally bad if it does not accomplish anything. That seems more fitting for a comment. Even the syntax above, where you're including `dateRepo`, this could be a service with the exact same benefit. I don't see how using a module specifically accomplishes anything. – G. Deward Apr 09 '15 at 15:47
  • @G.Deward Even if `dateRepo` is simply a service. Is the fact that you could simply inject it into another module not a good feature for modules? Often, I am able to reuse codes across applications just because I separated out in modules. Separate modules make testing much more easier as well. – kubuntu Apr 09 '15 at 16:21
  • @G.Deward There are many benefits to modularizing code - encapsulation, information hiding, abstraction, testability, etc. `dataRepo` could contain more functionality than one simple service and it deals with the separation of concerns. Stating that `dataRepo` could be implemented as a service is true, but that service would be explicitly bound to the `myApp` module. `dataRepo` in modular form is not. You will find that this "extra syntax" is very minimal compared to all other methods in my experience and requires no comments to understand. – Brett Apr 09 '15 at 16:25
-1

It is possible to create one big module which does everything, but Angular has been setup so that you can distribute responsibility over different modules.

~Does creating modules actually have a benefit other than read-ability?

You might want to read up a bit what the different things in Angular do. For example a service can be seen as a singleton which always returns the same data. This is great for creating HTTP request to receive data from an API.

A directive is made so that it has access to the DOM using jqlite, which makes it great for creating UI components. Then Angular has a bunch of other things you can create in one module like constants.

There are tons of introductions to Angular available where all these things are explained. If you are looking for a good IDE, I personally use webstorm which has great Angular support.

Edit 16.04.15

I misunderstood/misread your question a bit I admit.

You would be able to create one module called 'app' which contains all your directives, controllers, etc. Let me link to the advantages of modules From the Angular website (https://docs.angularjs.org/guide/module):

  1. The declarative process is easier to understand.
  2. You can package code as reusable modules.
  3. The modules can be loaded in any order (or even in parallel) because modules delay execution.
  4. Unit tests only have to load relevant modules, which keeps them fast.
  5. End-to-end tests can use modules to override configuration.

Point 1 is your readability.

2 means re usability. You would be able to create a library with html widgets for example which you can use in different projects. Note that if you would third party libraries, you are already using the module system.

3 means flexibility with loading of modules.

4+5 means testability. If you would have one module with all your code in there, you won't be able to unit test separate parts of your application as easy. You can more easily override settings but also inject mock objects into your modules.

Daan van Hulst
  • 1,426
  • 15
  • 32
  • 1
    This doesn't really help. I've built several Angular apps so far. And, I've watched several Angular tutorials (just finished the Angular Playbook by Scott Allen). Creating directives or services isn't the question. I'm trying to find a direct benefit of the module. – G. Deward Apr 09 '15 at 15:16