1

I'm developing a node.js application. Looking for ways to create the datamodel.

The data being sent to/from the client is JSON. Since database is MongoDb, the data to/from the db is JSON.

I'm new to JS, I could find so many js libraries dedicated to creating encapsulated objects. Is it still required?

What are the possible consequence of just defining models as simple js objects, and use prototype based inheritance where necessary?

Any help is appreciated. Thanks.

sowdri
  • 2,193
  • 5
  • 23
  • 36

2 Answers2

0

What are the possible consequence of just defining models as simple js objects, and use prototype based inheritance where necessary?

IMO, You will lose maintainability over the time as your application size increases or your team size increases as many developers start working on the same code.

In other words - Without proper encapsulation it is easy to modify objects one doesn't own - easy to meddle with the parts that you don't want to be touched.

If you are writing a library/framework of some sort where the just APIs are exposed to the user and you don't have proper encapsulation one could probably bring everything down by just one modification.

For example:

var myObj = {
    mySecretPrivateCrucialFunction: function () {
        // all the awesome crucial logic
    },
    //This is what you want other parts of the code ...
    // ... to be interacting with in this object
    myPublicMethod: function () { 
            // some logic
        mySecretPrivateCrucialFunction(); 
            // some thing else
    }
}

I can do this.

myObj.mySecretPrivateCrucialFunction = function () {
    alert('yay..i got you..');
};

But if you do this way - you don't give that chance.

var myObj = (function () {
        var mySecretPrivateCrucialFunction = function () {
                // all the awesome crucial logic
            }
        //This is what you want other parts of the code ...
        // ... to be interacting with in this object
        return {
            myPublicMethod: function () {} /*some logic */
            mySecretPrivateCrucialFunction(); /*some thing else */
        }
    })();

In case you want to make all your properties hidden/private and still want to get the JSON representation of the object - you can do something like this -

var myObj = (function () {
    // your private properties
    var prop1 = 1;
    var prop2 = 2;
    // your getters
    var getProp1 = function () {
            return prop1;
        };
    var getProp2 = function () {
            return Prop2;
        };
    // your setters
    var setProp1 = function (newValue) {
            prop1 = newValue;
        };
    var setProp2 = function (newValue) {
            prop2 = newValue;
        };
    // your JSON representation of the object
    var toString = function () {
            return JSON.stringify({
                prop1: prop1,
                prop2: prop2
            });
        };
    // Object that gets exposed -
    return {
        "getProp1": getProp1,
        "getProp2": getProp2,
        "setProp1": setProp1,
        "setProp2": setProp2,
        "toString": toString
    }
})();
Johnbabu Koppolu
  • 3,212
  • 2
  • 22
  • 34
  • Thank you. I agree with that. But what if the object has only fields and no methods? To add to it, if I hide all members of the object like we do in java, what will happen to the JSON string? – sowdri Dec 25 '12 at 17:42
  • If I understood you correctly, if you hide all the properties private and have getters and setters for each property like in Java, you have to write your own 'toString' function in that object like in Java, which you can use to get the JSON representation of that object. – Johnbabu Koppolu Dec 25 '12 at 17:53
  • Edited my answer to give another example with hidden properties. Check it out. – Johnbabu Koppolu Dec 25 '12 at 18:15
  • Module pattern is obsolete, it was created during the time all the people was trying to encapsulate and protect things due to a heavy influence of oop languages. Today no one does that, use javascript as is, don't try to encapsulate and protect from yourself. The de facto standard says: "prefix an underscore to the variables names to create private variables", that's all you need in JS. – Gabriel Llamas Dec 27 '12 at 02:16
  • @Gabrel Llamas - 'de facto standard' is what you can't strictly enforce and susceptible to abuse, The above approach would solve some of my maintenance problems in a large applicaton. As per your observation 'Today no one does that' - I don't think that it is a fact, and this is not a forum to evangelise my personal opinions, heard of requireJS and its popularity? – Johnbabu Koppolu Dec 27 '12 at 06:17
  • requirejs, node.js, amd and all the module managers use the module pattern to encapsulate the modules and store them in different closures, but this is mandatory, otherwise it would be impossible to manage modules. Furthermore, module pattern, as the name says, it's a pattern for modules, the object that is returned is a singleton, so there's only 1 instance that cannot be modified because the prototype is not populated. The module patterns it's only used to create module managers. – Gabriel Llamas Dec 27 '12 at 13:52
  • @GabrieLlamas - Don't you think your explanation is contradicting itself? – Johnbabu Koppolu Dec 27 '12 at 14:47
  • First there was 'Today no one does that' and then 'The module patterns it's only used to create module managers.' What is the basis for these statements? - and I don't agree with what ever is stated in your comments after that about modules being singleton and prototype not populated etc. Could you care to explain the drawbacks of the approach I suggested or suggest a solution to OP's problem? – Johnbabu Koppolu Dec 27 '12 at 15:12
0

There are two ways to approach this question as I see it:

I'm assuming that your data is being transfered as a JSON string.
"[{\"key\":\"val\"}]" is showing up in your responses, and you are then putting them through JSON.parse to turn them into viable arrays and objects.

So the first way would be to make "class-instances" (no new or inheritance necessary, just a constructor function which encapsulates data and exposes an interface, based on the data-type).

function makeTweet (data) {
    var tweet = {
            from_user : data.from_user || "anonymous",
            /* ... */
        },

        toString = function () {},

        public_interface : {
            toString : toString,
            /* getters, etc */
        };
    return public_interface;
}

I know you already know this stuff, but consider a situation where you've got two or three different data-types inside of the same process (like at the end of the line, when you're ready to print to the client), and you have a process which is reading and writing to public fields on every object. If different objects have different properties, things end poorly, or end in a sea of flakey if statements.

The other way to look at it might be an entity/service system

function handleTweets (tweetArr) {
    var templateFormat = system.output_format,
        string = "";

    if (templateFormat === "HTML") {
        string = HTMLtemplateTweets(tweetArr);
    } else { /* ... */ }
}

function HTMLtemplateTweets (tweetArr) {}
function JSONtemplateTweets (tweetArr) {}
function XMLtemplateTweets  (tweetArr) {}
...

With the point being that you would turn the JSON string into an array of data-only objects, and feed them down a line of type-specific library/system functions.

This would be more like a very simplified entity/system approach, rather than an OO (as classically accepted) approach.

Now, your data safety comes from making sure that your objects only ever go down one intended path, and thus transforms will be predictable for every object of that type.

If you want "inheritance" for performance/memory purposes in JS, then this might also be a direction to look.

Norguard
  • 26,167
  • 5
  • 41
  • 49