1

I am making a simple web app mostly in JavaScript. I was wondering as to how do I deploy settings/preferences? Do I just store user preferences somewhere and make use of if...else... statements all over the code?

I think that there must be a better alternative. I am know JS, jQuery & PHP and willing to learn anything new if at all required.

I have already made the app, only the settings are remaining. I know what options to give users and how to program them in js.

What's the most optimal way? How is it done in professional web apps and software made by companies (I am independent Student Developer - this is my first "BIG" project)?

EDIT:

For all the modifications that the settings are supposed to make (in this particular app), the whole js code base would litterally be filled with many branches of if...else...statements and I think that would make the code a lot harder to read and maintain.

In my app, the whole database table to be fetched from the database and the number and types of HTML DOM manipulation to be done, new elements to be added to HTML dom and whether some are visible or not would change. How do I deal with all that?

  • You'd first have to figure out how you want user settings to work, and then you'd have to write the code to make it happen. – zzzzBov Jan 16 '14 at 15:55
  • @zzzzBov Kindly elaborate. I have already made the app, only the settings are remaining. I know what options to give users and how to program them in js. – user52009 Jan 16 '14 at 15:56
  • 2
    What research have you done that you don't think applies to javascript and/or isn't professional quality? – JeffO Jan 16 '14 at 15:57
  • @JeffO For all the modifications that the settings are supposed to make (in this particular app), the whole js code base would litterally be filled with many branches of if...else...statements and I think that would make the code a lot harder to read and maintain. – user52009 Jan 16 '14 at 16:01
  • 4
    @user221287 I think we'd need examples of what you have in mind, because I cannot imagine a situation in which settings would have much branching. I'd expect little to none. – Izkata Jan 17 '14 at 0:49
2

I think it depends on the nature of the settings.

Some settings are basically numbers, like number of results to display or a zoom factor or such like. These settings can be read from your settings structure (or API) as needed and plugged in as parameters to functions in your code. I think these are straightforward.

Other settings control functionality, like whether entire blocks of information are displayed. These naturally lead to branches in the logic of the app (if/else statements). If you want to eliminate these, use the strategy or delegate design patterns. You basically have a function preconfigured to follow one path or the other, and you pass that function as a parameter. The main code then becomes simple, and complexity is pushed to the set-up code that composes and selects the desired implementation functions.

If the logic that you think you need to generate your page is complex, and the content of the page is complex, some logic in the final implementation might be unavoidable. What you can do to keep it manageable is to rethink the logic and see if you can simplify it. I find this is often quite possible. Factoring out implementation from the logic that engages it can also make your code more manageable. In the main body you will have some logic that reads settings values and that invokes subroutines as needed. Well-selected parameters to those subroutines, including function parameters, might result in fewer of them overall. JavaScript lends itself to this model. Take advantage of it.

For example:

function addTable(tablename)
{
    while (readFromDatabase(tablename))
    {
        writeTableLine(...);
    }
}

function addGraph(tablename)
{
    while (readFromDatabase(tablename))
    {
        buildGraph(...);
    }
}

// in the main code:
var table1 = settings.getTable1name();
var table2 = settings.getTable2name();
var outputFunction = settings.shouldShowGraph() ? addGraph : addTable;

outputFunction(table1);
// more stuff
outputFunction(table2);

The code above can output data from any number of tables in either table or graph form with no if statements.

  • Yes, my app settings controls functionality: In my app, the whole database table to be fetched from the database and the number and types of HTML DOM manipulation to be done, new elements to be added to HTML dom and whether some <div> are visible or not would change. How do I deal with all that? – user52009 Jan 17 '14 at 12:54
  • Your page sounds complex. I still recommend the strategy pattern, though if you can tolerate a few if/else statements, read my additions to my answer above. – Randall Cook Jan 17 '14 at 22:12
0

Ideally, you wouldn't be storing your user-specific settings as discrete items access all over the place, but would instead have a single area of your application that gathers ALL settings as either the default or a user-specific override, and you would just reference the setting directly.

That is, assuming you have a loadUserSettings function that returns an object, instead of something like the following:

window.userSettings = loadUserSettings()

if(userSettings.favoriteColor) {
  document.backgroundColor = userSettings.favoriteColor;
} else {
  document.backgroundColor = 'blue';
}

if(userSettings.useSnark) {
  makeReply(userSettings.useSnark);
} else {
  makeReply(false);
}

You would have

function loadSettings() {
  var userSettings = loadUserSettings();
  var baseSettings = {
    favoriteColor: 'blue',
    useSnark : false
  }      
  window.settings = {};
  for(var s in baseSettings) {
    settings[s] = (userSettings[s] == undefined ? baseSettings[s] : userSettings[s])
  }
}

document.backgroundColor = settings.favoriteColor;
makeReply(settings.useSnark);

You could also have your baseSettings be its own function, or use a framework's shallow-copy to do the same as the for loop above. But the basic idea is to centralize the "settings" code into properties you can access directly as needed, rather than adding conditional branching everywhere to either do a default or follow the basic setting.

You will need some if branches, for things like "swagger when replying with snark", but their use would be minimal.

if(snark && settings.swaggerWhenReplyingWithSnark) {
  swagger();
}
  • In my app, the whole database table to be fetched from the database and the number and types of HTML DOM manipulation to be done, new elements to be added to HTML dom and whether some <div> are visible or not would change. How do I deal with all that? – user52009 Jan 17 '14 at 8:42
  • The same way; as I said, you'll have some conditional operations, such as "do we share this or not?" (CSS would not be bad, btw.) – DougM Jan 17 '14 at 15:36
0

There are many solutions. One of these, (which I consider very clean, easy to maintain and to test), comes from MV* architecture.

In a MVC/MOVE/MV* context your user would be represented by a model. All views of your application would be listening for data changes (representing the preferences) of this model (Event Driven).

By focusing the application around the state of the user, each change of state into it, will be reflected in the interfaces due to the binding of the views on this object.

The UserModel object could then have some basic methods, such as:

  1. localLoad: load client data from local storage (LocalStorage, cookies, etc.)
  2. localSave: save client data to local storage (LocalStorage, cookies, etc.)
  3. remoteLoad: load client data from remote API
  4. remoteSave: save client data to remote API
  5. initialize: State control
  6. stayUpdate: timer to update the customer's preferences

The views, could listen to events like these:

  1. LISTEN TO USER.ID
  2. LISTEN TO USER.PREFERENCES.BACKGROUNDCOLOR

An example of how to handle this using Backbone.js is Backbone.ModelBinding

There are different MV* frameworks for creating javascript applications. Among the most famous you have Angular.js and Backbone.js.

0

This is a hard question to answer generally but I'm going to try. Consider the following:

#1 Does that need to be state?

For instance the DOM. One mistake people make a lot is to not see the DOM for the big giant live global data-structure construct that it is. It's there. It's doing work all the time whether you touch it or not. Take advantage of it. Do not save information that the DOM already has or can get very quickly. You will eventually fall out of sync with it and your app will faceplant. I mention this in a settings conversation because settings are exactly the kind of place where DOM concerns typically get way too close to higher-level app logic. If you can check the DOM for the state of something, stick with the DOM.

So, don't set DOM stuff directly from your settings. Your settings should be more about what, in plain English terms, the app does or doesn't do when you flip that switch.

Now mind, DO avoid setting anything in the DOM before you absolutely have to. That's when CSS reflow concerns kick in. Get like crazy but don't set two things at different times if they can happen in the same function.

#2 Let Your Features Check the Settings

If an object knows whether to hide/show the HTML that is its face to the user because it checks the settings itself, you shouldn't have to think about it when flipping a boolean that says whether the feature that object handles is available.

#3 One Setting Value Always Means One Thing

I break this one somewhat regularly to be honest but I think it's worth considering as a heuristic and I've often regretted breaking it. If behavior established by one setting can become altered based on a combination of it and the values of other settings, that can get ugly. It's better to flip a switch that makes an object realize it will have to do a certain set of things depending on its circumstances than to flip a switch that then causes some third party to run around and sort out the circumstances and then tell the object exactly what it and the other relevant objects must do.

#4 Listen, Don't Tell

Odds are good you're using jQuery. It actually has a very nice architectural tool not at all related to the DOM. It can trigger and listen for custom events on the fly on any old object. Try this:

var someObject = {};

$(someObject).on('ICanMakeUpAnyEventIWant', function(){
    alert('I can do anything I want based on that event.');
} );

$(someObject).trigger('ICanMakeUpAnyEventIWant');

On the whole theme of "let your lower-level objects handle the logic" you could also set your settings properties via getter/setter-style methods that trigger events when changes happen. By triggering an event, you can add new things that need to respond to said event without changing the behavior of anything else that responds to that event or the thing that originated said event. This can be very good where settings are concerned.

That trigger method can also be used to hand off an event object with data:

$(someObject).on('someEvent',function(eventObj){ alert(eventObject.dataForAnyListener); });
//'yay'
$(someObject).trigger({type:'someEvent', dataForAnyListener:'yay'});

So for instance, imagine a settings object whose settings were set with methods that also triggered 'someSpecificSettingChange' events with 'newValue' properties in their event objects.

#5 Sometimes you need a crap-ton of logic

Don't get me wrong. It's a good smell to sniff for, but sometimes there's no way around a buttload of flow-control. Always see what you can do to reduce your if/elses but don't assume they're always wrong merely for existing. UI gets hairy sometimes.

#6 Start With Defaults

function SpyCar(overrides){

    var defaultSettings = {
        ejectionSeatArmed:true,
        oilSlickFlammability:.99,
        car:'Aston Martin DB5'
    } 

    for(var x in overrides){
        defaultSettings[x] = overrides[x];
    }
    //See also $.extend(defaultSettings, overrides) if into JQ

    //do important spy car code here based on defaultSettings
}

var boDukeSuperSpy = new SpyCar( { car:'\'69 Dodge Charger' } );

Considering defaults before the code is even written can be helpful in organizing code because it kicks off your lazy developer instincts. What's the easiest most common setup you'll deal with? How do those common settings relate? Sometimes you might never need a setting. Other times you might realize that just because nobody will ever want a genre-bending General Lee as a spy car, doesn't mean it wasn't later useful to leave the door open for make/model swapouts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy