0

I have the following node module:

var _ = require('lodash');

function Config(configType, configDir) {
  this.configType = configType;
  this.configDir = configDir;
};

Config.prototype.read = function() { // read file to buffer };
Config.prototype.modify = function() { // modify buffer };
Config.prototype.write = function() { this.modify(); // now write };

var base = _.curry(Config);
module.exports.A = base('A');
module.exports.B = base('B');
module.exports.C = base('C');

// In some other file
var config = require('config');
var a = new config.A('a/dir');
var b = new config.B('b/dir');
var c = new config.C('c/dir');

The problem is that with ConfigC, I don't actually want to call the modify method. I have thought about doing a conditional in the write function based upon configType but ideally I'd like ConfigC to just 'know' what to do, either by overriding the write function or some other javascript-ism that I'm not aware of.

Does anyone know of an elegant solution to this problem?

nathasm
  • 2,524
  • 5
  • 24
  • 35
  • Have `Config` take a third argument, e.g., `shouldModify`, and have each config set `this.shouldModify = shouldModify`? (And then read `this.shouldModify` in a conditional, obviously.) Is that possible with your use of `_.curry`? – apsillers Aug 21 '14 at 18:10
  • It would be but that is essentially the same thing as checking the configType. – nathasm Aug 21 '14 at 18:12
  • Yes. However, it saves you the trouble of definiing and maintaining a separate table/list of `configTypes` that do or don't require a `modify` call. If you (or a later contributor) adds a new `configType` type, you can specify whether it uses `modify` when you write the constructor call, instead of defining it and then remembering that you need to add the new type to your list of types that omit a `modify` call. If you are sure you'll never have more `modifyType`s (or at least never have any other `modifyType`s that omit `modify`), then there is indeed no difference. – apsillers Aug 21 '14 at 18:19

1 Answers1

1

Use a subclass. Instead of subtracting the modify behavior in the subclass, we'll have the base class not do the modify, then add that behavior in the subclass.

// Add the below to the definition of Config in the question
Config.prototype.write = function() { /* do not modify */ };

// Define subclass which adds modify behavior
function ConfigModify(configType, configDir) {
    Config.apply(this, arguments);
}
ConfigModify.prototype = Object.create(Config.prototype, 
    {constructor: {value: ConfigModify}}); // thanks Felix
ConfigModify.prototype.write = function() { this.modify(); /* now write */ };

module.exports.A = _.curry(ConfigModify)('A');
module.exports.B = _.curry(ConfigModify)('B');
module.exports.C = _.curry(Config)('C');

According to a world-famous computer scientist, "an if statement is just a poorly-implemented subclass. Especially if it's testing a Boolean flag."

  • 1
    Better inheritance setup: `ConfigNoModify.prototype = Object.create(Config.prototype, {constructor: {value: ConfigNoModify}});`. See http://stackoverflow.com/q/17392857/218196 – Felix Kling Aug 21 '14 at 18:32