The Revealing Module Pattern (RMP) disadvantages
Asked Answered
T

2

14

I recently got familiar with the Revealing Module Pattern (RMP) and I've read quite a few articles about it.

It seems like a very good pattern and I would like to start using it in a big project. In the project I'm using : Jquery, KO, requireJS, Jquery Mobile, JayData. It seems to me like it'll be a good fit for the KO ViewModels.

In specific I'd like to use THIS version of it.

One thing I could not find are disadvantages for using this pattern, is it because there aren't any (I find it hard to believe)?

What should I consider before starting to use it?

Tercet answered 27/12, 2012 at 7:3 Comment(1)
Check this article: addyosmani.com/resources/essentialjsdesignpatterns/book/… there is a disadvantages section at the end.Doykos
T
4

I read the article that @nemesv referenced me to (Thanks :)) and I thinks there is one more disadvantage that was not mentioned, so I thought I'd add it here for reference. Here is a quote from the article:

Disadvantages

A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions.

Public object members which refer to private variables are also subject to the no-patch rule notes above.

As a result of this, modules created with the Revealing Module pattern may be more fragile than those created with the original Module pattern, so care should be taken during usage.

And my addition:

You can't use inheritance with this pattern. For example:

var Obj = function(){
    //do some constructor stuff
}

var InheritingObj = function(){
    //do some constructor stuff
}

InheritingObj.prototype = new Obj();

InheritingObj.prototype.constructor = InheritingObj;

This a simple example for inheritance in js, but when using the Revealing Prototype Pattern (archived here) you'll need to do this:

InheritingObj.prototype = (function(){
    //some prototype stuff here
}());

which will override you inheritance.

Tercet answered 31/12, 2012 at 7:14 Comment(1)
It seems like it works perfectly with Object.create(urlBuilder); Another way to do the inheritance is this way jsfiddle.net/d0n7kfmx what do you think?Outshoot
B
16

The Revealing Module Pattern (RMP) creates objects that don't behave well with respect to overriding. As a consequence, objects made using the RMP don't work well as prototypes. So if you're using RMP to create objects that are going to be used in an inheritance chain, just don't. This point of view is my own, in opposition to those proponents of the Revealing Prototype Pattern.

To see the bad inheritance behavior, take the following example of a url builder:

function rmpUrlBuilder(){
  var _urlBase = "http://my.default.domain/";
  var _build = function(relUrl){
    return _urlBase + relUrl;
  };

  return {
    urlBase: _urlBase,
    build: _build
  }
}

Setting aside the question of why you would use RMP for an object with no private components, note that if you take the returned object and override urlBase with "http://stackoverflow.com", you would expect the behavior of build() to change appropriately. It doesn't, as seen in the following:

var builder = new rmpUrlBuilder();
builder.urlBase = "http://stackoverflow.com";
console.log(builder.build("/questions"); // prints "http://my.default.domain/questions" not "http://stackoverflow.com/questions"

Contrast the behavior with the following url builder implementation

function urlBuilder = function(){
  return {
    urlBase: "http://my.default.domain/".
    build: function(relUrl){ return this.urlBase + relUrl;}
  }
}

var builder = new urlBuilder();
builder.urlBase = "http://stackoverflow.com";
console.log(builder.build()); // prints "http://stackoverflow.com/questions"

which behaves correctly.

You can correct the Revealing Module Pattern's behavior by using this scope as in the following

function rmpUrlBuilder(){
  var _urlBase = "http://my.default.domain/";
  var _build = function(relUrl){
    return this.urlBase + relUrl;
  };

  return {
    urlBase: _urlBase,
    build: _build
  }
}

but that rather defeats the purpose of the Revealing Module Pattern. For more details, see my blog post http://ilinkuo.wordpress.com/2013/12/28/defining-return-object-literals-in-javascript/

Bonnard answered 31/12, 2013 at 11:33 Comment(1)
This is an answer looking for a question. Its examples are contrived, it calls correct behavior bad, it calls expected behavior unexpected. OP wrote a series of long answers on this topic that all suffer from the same problems, and he defends his answers adamantly against anyone who points out those problems. "You must not understand the examples." But going on seven years, these answers are where people have landed when they searched for the Revealing Module Pattern.Milfordmilhaud
T
4

I read the article that @nemesv referenced me to (Thanks :)) and I thinks there is one more disadvantage that was not mentioned, so I thought I'd add it here for reference. Here is a quote from the article:

Disadvantages

A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions.

Public object members which refer to private variables are also subject to the no-patch rule notes above.

As a result of this, modules created with the Revealing Module pattern may be more fragile than those created with the original Module pattern, so care should be taken during usage.

And my addition:

You can't use inheritance with this pattern. For example:

var Obj = function(){
    //do some constructor stuff
}

var InheritingObj = function(){
    //do some constructor stuff
}

InheritingObj.prototype = new Obj();

InheritingObj.prototype.constructor = InheritingObj;

This a simple example for inheritance in js, but when using the Revealing Prototype Pattern (archived here) you'll need to do this:

InheritingObj.prototype = (function(){
    //some prototype stuff here
}());

which will override you inheritance.

Tercet answered 31/12, 2012 at 7:14 Comment(1)
It seems like it works perfectly with Object.create(urlBuilder); Another way to do the inheritance is this way jsfiddle.net/d0n7kfmx what do you think?Outshoot

© 2022 - 2024 — McMap. All rights reserved.