Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern for storing several configuration objects

Tags:

javascript

I have several objects that I want to store within an overarching configuration object. The individual objects have various properties in common. I'm used to a functional programming style in JavaScript, but can't figure out a DRY way to implement the storage of these objects in a global config object.

Solution 1

var config = {};

config['myKey'] = {
  'key': 'myKey',
  'name': 'My Key',
  'icon': '<h1>Category One</h1>',
  'filterFn': function(obj) {
     // function unique to this obj
     return obj;
   },
  'values': function() {
    // function unique to this obj
    return myData.filter(function(val) { return val['myKey']; };
  }
}

Problems: repeats keys ('name', 'icon', etc.) for each object, necessitates changing myKey in a few different places

The config['myKey'] object assignment repeats for about 5 different objects. These objects have all of the same properties in common.

There are two noticeable "code smells" with this approach.

  1. One is that I repeat the same property names 5 times (key, name, icon, etc.).

  2. The second is that I have to repeat "myKey" each time I want to use it in the object (e.g., in config['myKey']['key'] and config['myKey']['values'].

I know that I could potentially create a function, for example createMyKeyObject() and if I passed in arguments. This would save the need to repeat the myKey in multiple places, thus solving the second problem. It would look as follows:

Solution 2

function getMyKey(key, name) {
    
  var filterFn = function(obj) {
    return obj;
  };
    
  var values = data.filter(function(val) { return val[key]; };
    
  config.filters[key] = {
    'key': key,
    'name': name,
    'icon': '<h1>Category One</h1>',
    'filterFn': filterFn,
    'values': values
  };
}
    
getMyKey('myKey', 'My Key');

Problems: repeats keys ('name', 'icon', etc.) for each object, declaring object values in two separate places (function call, inside function), modifies global object inside function

This solves the second problem of repeating the key and the name, but creates new problems. One is that I'd be declaring values pertaining to the same object in two separate places (inside of the function and in the functional call). It's also a more verbose solution. And finally, it has the side-effect of modifying the global config object inside of the function.

Is there a proper solution that gets rid of these "code smells"? Can prototypical inheritance solve this in some way?

like image 388
Himmel Avatar asked Jan 24 '26 19:01

Himmel


1 Answers

You can use a constructor, I don't see a need for inheritance

function Config(key, name, icon, values, filterFn) {
    this.key = key;
    this.name = name;
    this.icon = icon;
    this.values = values;
    this.filterFn = filterFn;
}

var cfg = {};
// Don't want to repeat "someKey"? put it in a variable.
var myKey = 'someKey';
cfg[myKey] = new Config(myKey, 'someName', 'icon', 
                         [1,2], function(obj){ return obj + myKey});
myKey = 'otherKey';
cfg[myKey] = new Config(myKey, 'anotherName', 'anotherIcon',
                         [3,4], function(obj){ return obj + '_' + myKey});

// Or create a method to help, may be overdoing it...
function addConfig(key, name, icon, values, filterFn) {
    cfg[myKey] = new Config(key, name, icon, values, filterFn];
}

addConfig('someKey', 'thatName', 'thisIcon', [6,7], o => o);

In EcmaScript 6, you can save some typing

function Config(key, name, icon, values, filterFn) {
    Object.assign(this, {key, name, icon, values, filterFn});
}
like image 134
Juan Mendes Avatar answered Jan 26 '26 10:01

Juan Mendes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!