I'm trying to set up a large angular web app, with an architecture as described here
What I can't get my head around is how to make modules completely independent from other modules. All github boilerplate's or example projects which focus on modules all seem to have modules which heavily depend on common modules or functions/services. That would sort of defy the purpose of keeping everything separate doesn't it?
Take the following two example:
I have a utilities module which handles some basic functions (hashes etc.), and another module which handles all communication with an API. Imagine a User module which needs to make hashes and communicate with the API, how do I handle that? Directly injecting the Util and API modules as dependencies would break the in dependability, and putting them into the User module as well would mean a lot of double code (imagine multiple modules using the Util and API modules). Or should I use the mediator to mediate the communication?
User information which is stores in the User module is something that should be used almost application wide, and in the facade as well for example (the facade should handle security according to the article). How can I allow all of the application to access the information, without everything being dependent?
Thanks in advance :)
I answered a similar question here.
You are on the right track with separating behaviors into modules.
The idea is to embrace Dependency Injection as a means of collecting these behaviors into a rolled up module. With an IoC container at your disposal you can exercise discipline in your naming and other conventions to keep your app loosely coupled through configurable components.
We have a general app type module that simply registers the appropriate feature modules. That is in turn bootstrapped by a boot module that simply calls angular.bootstrap(['app']) somewhere (ours is in the page).
We can easily decorate or replace existing services/controllers/whatever with this setup and teams can work in isolation while features scale at different rates.
For example:
var myWidget = angular.module('myWidget',[])
myWidget.directive('myWidget',function(){...})
myWidget.factory('somethingImportant',function(){...})
var myDomainModel = angular.module('myDomain',[])
myDomainModel.factory('someModel',function(){...})
... //more models
var app = angular.module('app',['myWidget','myDomain'])
app.factory('applicationWidePolicyHere',function(){...})
//on index.html; das boot.
(function(){ angular.bootstrap(document,['app']) })()
Related
I'm very new to modules in Prism and am struggling to understand how to use them properly. I want to have a navigation panel like in the image below, which I stole from Google.
Let's say that I have 3 modules for 3 separate concerns: NavigationModule, HelpModule, and FeedbackModule. If I want to show "Help" when the app first loads, my understanding is that I would do something like the following:
Define Regions for navigation and content in my Shell (main WPF project)
Upon execution, load the navigation view into the navigation Region
Upon initialization of the NavigationModule, load a view from HelpModule into the main content Region
This leaves me with a few questions about what modules should know about each other:
Should the Shell's project have a reference to the NavigationModule in order to load its view?
Should the NavigationModule have a reference to the HelpModule in order to load its view? And a reference to FeedbackModule in order to load its views on demand?
If the answer to these questions is "no," then what's the best way for modules to be aware of each other's views? I could create a shared class library with constants for view names, but it seems a bit troublesome to maintain a bunch of strings that way whereas with references I could use nameof(). I would appreciate any direction. Thanks.
Modules should not "know" each other in the sense of having a project reference from one module to another, because that kind of defeats anything gained from having modules in the first place, that is, to have a modular application (built of components that can be swapped out independent of each other).
Modules should interact through shared interfaces, which are define outside of modules, that is either in the framework or in assemblies that "are" no modules themselves. Depending on your requirements, you should define upfront (and enforce in the build process) which modules there are and which interface-assemblies and which module is allowed to reference which interface-assembly.
So how to show the Help-view when the application loads? Send a message (e.g. via IEventAggregator or any other communication mechanism) when it's time to load the initial view (whatever that may be). The Help-module listens for the message and navigates to the Help-view. Important: the SessionResume-module might also listen for our message. It's the responsibility of whomever choses which modules to deploy to only deploy modules that are compatible with each other.
So I have encountered a practice where people will create a module for each component that has service dependencies. that way, when someone wants to use a given component, they dont have to read through the code to see what providers to add to the given module. is this an antipattern? will it cause performance issues or something?
Is there some recommended guidelines on lower/upper limits on how many components/directives/providers/etc should be in a given module? has there been testing of the angular/angularJs ecosystems with 100s of modules on a view? in comparison with if just regular components were all bundled in maybe like 20ish modules instead?
Generally, there are different module types in Angular and guidance as to what they should contain and what modules should import them:
Widget modules - Contains mostly UI components, but no services. Imported by Feature modules.
Features modules - Contains domain-specific private components. Imported by AppModule.
Service modules - Contains services exclusively. Imported by AppModule.
Routed modules - A specialized Feature module, that is the target of routing.
Routing modules - Contains navigation routes and resolver/guard services.
Modules can have dependencies on other modules. For example, a Widgets module could be expected to be used with a Services module, where AppModule imports the ServicesModule, and FeatureModule imports the WidgetsModule. The BrowserModule/CommonModule is an example of this pattern; so is RouterModule.forRoot()/RouterModule.forChild().
I would say its overkill to have one module per component. It would be hard to organize and group common functionality together and leverage services in any meaningful way. It could easily become unwieldy when your imports for a single module run into double-digits.
[Edit]
After re-reading this question, I would like to add a clarification because I think the one-component approach with NgModule encapsulation deserves more attention. I don’t believe in 1:1 module-to-component - that would be overkill. However, I am in full support of 1:many module-to-component where the module exports only one component, and all the other components are private to the module. This latter approach is known as NgModule encapsulation, and it is an excellent way to build your application in a way that loosely couples your top-level components.
If you have a relatively small app then bloating a single module is ok. Once your app starts to get relatively large then it makes sense to start lazy loading modules so your users don't have to download the entire build on app start. Grouping related functionality into modules makes things easier to maintain as well.
So for a smallish site, a single module will be fine but as your app grows it makes sense to start refactoring components and services into modules.
Practically, angular always prefer you to have basic module -
Features module, Shared module, Routing module, Core module,
But if application is big it is better to have lazy loading for modules, to have module for every component is best option, which increase app speed along with this browser load that component which is required.
I've noticed some people define a new module for each controller, service, directive etc.
angular.module('controllers.Dashboard',[]).controller(...);
angular.module('controllers.Details',[]).controller(...);
angular.module('controllers.List',[]).controller(...);
However, isn't that a performance issue? I mean: for each controller you create, you also create a new module.
What do you think?
Any performance hit would be incredibly minimal. What you do gain in terms of performance though, is testing speed. Testing can be localized to small modules that don't need to load in the entire application to perform what they need to.
On the code organization side, I personally like the idea of breaking up modules depending on feature not architectural slice. So instead of having a module for controllers, a module for services, etc, create a new module for every new feature/piece of the application. This way you can group together conceptually related controllers, views, services, filters, and so on.
The overhead will be minimal in practice. It is really more of a code organization type issue. On my project we have a FooService, FooController,FooDirectives, BarService...
I've been struggling trying to strike the right balance between reusability and complexity when it comes to organizing my Backbone objects into AMD's (for medium- to large-scale applications)
(A) Should every Backbone object (models, views, etc) be in their own module?
(B) Should related Backbone objects be in the same AMD module? (ie: PersonModel, PersonCollection, PersonView objects in the same module definition)
Option (A) seems to allow the most flexibility and reusability, but also the most complexity because of the (potentially) high number of files. While option (B) may make it easier to manage things, but less flexible and really difficult to unit test.
How is (or has) everyone else structured these things?
I good thing about requirejs is that it allow you to abstract the physical files into structured namespaces. You can take the approach (A) and create each backbone class in their own file, then create a "namespace" module to glue all the related classes together.
// Suppose you have PersonView.js, PersonCollectionjs, PersonModel.js as modules
// create a Person module to function as namespace
define(["PersonModel", "PersonCollection", "PersonView"], function(model, collection, view) {
return {
Model: model,
Collection: collection,
View: view
};
});
This keep the modules organized in their own files and gives you some flexibility to write one module per class without requiring you to expose this organization for the rest of the application (I really don't like to have to write require("PersonView", "PersonModel" ... ) every time I need to use the person's objects, it's easier and cleaner for consumers to declare a dependency on a "namespace" instead of independent classes).
For medium to large backbone projects I prefer to use requirejs with a separate module for every model, collection, and view. I also use the "Text" plugin for requirejs so I can load underscore templates just as I would any other module. This for me seems to be the sanest way to manage a large project and I have never really felt overwhelmed with the number of files I have.
+1 on using the requirejs optimizer when pushing your app to production. Works really well.
http://requirejs.org/docs/optimization.html
I just released an open source toolkit which will hopefully help others as much as it helps me. It is a composition of many open source tools which gives you a working requirejs backbone app out of the box.
It provides single commands to run: dev web server, jasmine single browser test runner, jasmine js-test-driver multi browser test runner, and concatenization/minification for JavaScript and CSS. It also outputs an unminified version of your app for production debugging, precompiles your handlebar templates, and supports internationalization.
No setup is required. It just works.
http://github.com/davidjnelson...
I need to create plugins that hook into the functionality of my main application. CakePHP plugins only instantiate themselves when its own controller is called meaning I cannot affect the processes of my main application.
mainapp/action2baffected
myplugin/
I like the idea of having self contained pluggable models , is there any other way to get this to work? Creating models on the fly etc or write a plugin system from scratch with no cakeiness!
You can use components and behaviors (from the plugins) into your core application. There is one very good presentation of Pierre MARTIN Using reusing-plugins. It's a really inspirational resource.
We have put quite a lot of work into making plugins truly self contained in Infinitas
You can have a look at some of the methods that are used, but the main code is in the events. Everything from cache configs, db connections and include assets like css/js are done from within the plugin, even injecting some markup into views is handled.