Good OO practice is to encapsulate your data. I recently wrote a script that managed some data and methods for a mobile application to write WiFi information to an NFC. My first design looked something like this:
1
2
3
4
5
6
7
8
9
var SSID;
var pass;
function formatNetwork() {
toWrite= {};
toWrite['SSID'] = SSID;
toWrite['pass'] = pass;
return JSON.stringify(toWrite);
}
Except this is terrible: SSID
and pass
are global variables and exposed to the whole world. Additionally, the network formatting is fragile and difficult to expand. I decided to upgrade to the following and store everything in an object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var wifiWriter = {
SSID: 'none',
pass: 'none',
formatNetwork: function() {
var toWrite = {};
for (var prop in wifiWriter) {
if (!isFunction(prop)) {
toWrite[prop] = wifiWriter[prop];
}
}
return JSON.stringify(toWrite);
}
}
// isFunction() was pulled from UnderscoreJS
Much better. There’s only a single global variable now. The formatNetwork
function checks all of the non-variable properties of the wifiWriter
object and adds them to the object, so we can add more fields to the string without breaking everything. I did end up adding a field, so this paid off sooner rather than later.
It’s still not encapsulated. Anyone can access the two variables and modify them directly. My OO training tells me that this is horrible, and I don’t trust myself not to screw things up somehow. We’ll encapsulate it in a function for best results, returning an object that has methods to access and modify the variables.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var wifiWriter = function () {
var SSID = 'none';
var pass = 'none';
return {
getSSID: function() {
return SSID;
},
setSSID: function(newSSID) {
// Validation goes here right?
SSID = newSSID;
}, // pass get/set left as exercise to reader
formatNetwork: function() {
var toWrite = {};
for (var prop in wifiWriter) {
if (!isFunction(prop)) {
toWrite[prop] = wifiWriter[prop];
}
}
return JSON.stringify(toWrite);
}
}; // trick #1: end the return statement
}(); // trick #2: call function immediately after declaring it
PROBLEM. My clever way of looping through the variables no longer works, since its a function and not an object anymore. It might be possible to pull the variables out in a similar manner, but you know, what if I wanted to add additional fields that weren’t to be incorporated? Let’s wrap it an object!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var wifiWriter = function () {
var wifiInfo = {
SSID: 'none',
pass: 'none',
locationID: 'where even'
};
return {
getSSID: function() {
return SSID;
},
setSSID: function(newSSID) {
// Validation goes here right?
SSID = newSSID;
}, // pass get/set left as exercise to reader
formatNetwork: function() {
var toWrite = {}
for (var prop in wifiInfo) {
if (!isFunction(prop)) {
toWrite[prop] = wifiInfo[prop];
}
}
return JSON.stringify(toWrite);
}
};
}();
This satisfies my need for good code writing.