What Is Variable Privacy?

It’s possible that you’ve never heard of the idea of variable or method privacy before. Yet, it is encountered so often as part of feature set in many computer languages, not just JavaScript.

A common running theme in software development is variable privacy. This is rarely taught because it’s more of a principle than a language feature.

In C++ you even have a special keyword called: private, that limits variable use to a particular class. In JavaScript… we don’t have private keyword.

But it doesn’t mean variable or method privacy are impossible to achieve with its current set of features. In fact, if you start paying attention, you will notice that the idea is omnipresent even in subtle language features:

console.log(x); // reference error
{
let x = 1;
}

Here x is private to the scope in which it was defined. You cannot access it outside of that scope, without generating an error. It is often taught that this is the difference between var and let.

I guess you can see how it works. But wait. Why?

Well, because var used to hoist the definition. And automatically shoving things into global scope isn’t good coding practice.

It is incredible how many times this privacy effect is observed, not just with let keyword alone but in many other JavaScript features… as well as in software development in general. So it is probably important. Let’s take a look:

  1. import / export provide a very similar idea of privacy: variables, functions and classes can be “exported” into your main application, without ever second guessing how they work. You will simply use exported function names to call functions and class names to instantiate objects.
  2. Functions also behave in this way by default: variables and functions defined inside the function are not visible outside of the function. Wait, that’s exactly what let does in a block-scope.
  3. Even functions that are used as constructors to instantiate an object use the this keyword which becomes a reference to the instance of the object. But again, it is only available from within the function’s inner scope. Wait, that is that same “let” effect!
  4. The same happens with class keyword. It has its own this keyword. All variables defined inside class scope become private to that scope.
  5. Hiding implementation is also at the heart of closures. A closure is when a function is defined inside another function. The inner function is not directly accessible from global scope unless it is explicitly returned first. Wait…that’s the whole “let” thing all over again.
  6. When an event callback function is created it has own lexical environment: any created variables in it are usually used to work within the confines of that event, rather than globally.

It looks like the concept of data privacy is used in a lot of features!

But why?

1. Separate Public And Private Code

As a programmer you will write code only you understand. This is your implementation. But you will expose methods for others to use. (In this case others can even be a future you.)

Privacy helps us draw a line between public and private data. If we are not mindful of the separation between implementation and the API we’re bound to write a lot of ADHD code that turns into spaghetti.

The public data is what’s revealed to the user of the API. An API is the epitome of public data: anyone can access and use it — that’s the whole point.

API is a set of clearly defined public methods to communicate to the software: without needing to know how it was implemented.

You call console.log all the time. You know what it does, but you never really need to understand how it works internally. So the console object can be thought of as an API to working with console and log is one of its publicly exposed methods. The implementation is private. You let Google Chrome developers take care of that.

2. Packaging

Code is often delivered in packages or modules. We import the API, but not implementation. As a programmer responsibility of implementation is on you. But you want to expose public methods to whoever wants to use your API.

Avoids conflict between multiple libraries added to the same project. (If programmers chose to name some variables using same identifier name.)

3. Automatically Prevent Future Bugs

Sticking to this practice prevents future bugs. You generally don’t want your modules be exposed to global scope context. This is why we no longer use var keyword to create variables.

A public data type: variable, object or function can be accessed from global scope. This means that if something goes wrong the error could be anywhere! And that’s the pattern var supports.

(global data sinks into all of its children scopes and essentially becomes available through your entire application!)

A private data type on the other hand can only be accessed from the same scope, function or class where it was defined. There is only one module to look at. If the error happens there (which the debugger will tell you about) the bug will be isolated to the island of that scope. Hours of debug time saved.

4. Coupling

But data is not all about the location where it is stored.

There is one other benefit to privacy related to coupling.

In other words, its dependency on something else.

If you are a fan of OOP design you will be working with classes to build instances of objects. These classes can inherit from other classes. Some classes can be composed together with other classes, creating dependencies.

What if class A requires to use class B?

Or class CarFactory requires class Vehicle?

class Vehicle {
constructor() {}
refuel() { console.log("refueling..."); }
}
class CarFactory {
constructor() {}
// method make_vehicle depends on Vehicle class
// which means implementation of CarFactory class
// also depends on Vehicle class too
make_vehicle( params ) {
return new Vehicle( params );
}
}
let factory = new CarFactory();// Produce fleet of Teslas...
let vehicle1 = factory.make_vehicle();
let vehicle2 = factory.make_vehicle();
let vehicle3 = factory.make_vehicle();
let vehicle4 = factory.make_vehicle();
let vehicle5 = factory.make_vehicle();

But there is a problem. Nothing in class Vehicle tells you where it will be used. It doesn’t know it will be used in CarFactory. Technically, you could have created a Vehicle on your own without needing CarFactory at all.

When bugs come (and they will) you won’t know whether CarFactory caused the bug related to Vehicle, or that Vehicle caused a bug when it was used outside of CarFactory.

But if you scratch the entire concept of object composition, and make all members private to the main class, it will be easier to track bugs. If something goes wrong you will 100% know the problem is within that object and not in some other place outside of your private module.

Image for post
Image for post

An Idea

When building software, make everything as private as possible from the start. Expose API by creating public methods only as it becomes necessary.

Written by

Issues. Every webdev has them. Published author of CSS Visual Dictionary https://amzn.to/2JMWQP3 few others…

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store